---
title: "Configuring the viewer | Customer's Canvas On-Premises"
canonical: "https://customerscanvas.com/docs/on-premises/design-atoms-js/howto/viewer/"
---

# Configuring the viewer

> The `Viewer` component visualizes and interacts with design elements created by Customer's Canvas, serving as an interface tool for integrating editing and viewing functionalities into web applications.

In the [Working with the object model](https://customerscanvas.com/docs/on-premises/design-atoms-js/howto/working-with-object-model.md) topic, you learned how to use the object model of a product. However, to be able to use it in a full force, you need to connect it to a backend.

## Connecting the viewer

To integrate the `Viewer`, follow these steps:

1. Install the front-end library `@aurigma/design-atoms` via NPM:

   ```bash
   npm install @aurigma/design-atoms --save
   ```

2. Create an instance of the `Viewer` class:

   ```javascript
   const backendUrl = "http://<yourInstanceUrl>";
   const holderId = "#id-of-your-div";
   const holder = document.querySelector(holderId);
   const viewer = new Viewer({
       holderElement: holder,
       backendUrl: backendUrl,
       canvasBackground: { color: "white" }
   });
   ```

3. Ensure that a back-end server is set up separately. You can connect to an existing Customer's Canvas Design Editor instance or create a custom backend using the [Aurigma.DesignAtoms](https://customerscanvas.com/docs/on-premises/design-atoms-cs.md) NuGet package.

## Defining a print area

As an example, let's specify a print area and a bleed zone in the viewer:

```javascript title="Defining a Print Area"
// Import necessary classes from the Customer's Canvas SDK.
import { PrintArea, SafetyLine, PdfBox, RgbColor } from "@aurigma/design-atoms-model/Product";
import { RgbColor } from "@aurigma/design-atoms-model/Colors";
import { RectangleF } from "@aurigma/design-atoms-model/Math";

// Define safety lines.
const safetyLine = new SafetyLine();
safetyLine.margin = 10;
safetyLine.pdfBox = PdfBox.Bleed;
safetyLine.color = new RgbColor("lime");

// Add the safety line to a print area.
const printArea = new PrintArea(new RectangleF(0, 0, surface.Width, surface.Height));
printArea.safetyLines.add(safetyLine);

surface.printAreas.add(printArea);

// Enable safety lines in the viewer.
viewer.safetyLinesHandler.visible = true;
```

## Print area visualization

You can configure the visualization of print area boundaries in the viewer. This includes **bleed zones**, **trim lines**, **regions**, and **print areas**.

```javascript
viewer.configuration.printZone = {
    bleed: {
        visible: true,
        color: "rgba(0,0,255,0.5)",
        width: 1,
        step: 5
    },
    trim: {
        visible: true,
        color: "rgba(0,0,0,1)",
        width: 1,
        step: 3
    },
    region: {
        visible: true,
        color: "rgba(0,255,0,0.5)",
        width: 1,
        step: 5
    },
    printArea: {
        visible: true,
        default: {
            color: "rgba(255,0,0,0.5)",
            width: 2,
            step: 5,
            altColor: "rgba(255,255,0,0.3)"
        }
    }
};
```

For reference, see the [IPrintZoneConfiguration](https://customerscanvas.com/docs/on-premises/design-atoms-js/reference/design-atoms/IPrintZoneConfiguration.md) interface.

## Changing zoom mode

To dynamically adjust the zoom level for a better user experience:

```javascript title="Changing Zoom Mode"
// Import the Viewer and ZoomMode classes from the Customer's Canvas SDK.
import { Viewer, ZoomMode } from "@aurigma/design-atoms/Viewer";

// Function to set the zoom mode for the given viewer instance.
const setZoomMode = (viewer: Viewer, mode: ZoomMode) => {
    // Set the specified zoom mode on the viewer.
    viewer.zoomMode = mode;
    // Hide any hover effects currently visible on the canvas.
    viewer.canvas.hideHover();
    // Redraw the canvas to apply changes immediately.
    viewer.canvas.redraw();
};

// Call the function to set the best-fit zoom mode on the viewer.
setZoomMode(viewer, ZoomMode.bestFit);
```

## Subscribing to item events

To subscribe to events for items on the canvas (e.g., when a user moves an image):

```javascript title="Subscribing to Item Events"
viewer.eventManager.addItemChanged((item) => {
    // Handle item change event
});
```

## Customizing the Toolbar

### Enabling Delete and Edit buttons

To enable the Floating Toolbar with **Delete** and **Edit** buttons:

```javascript title="Enabling Floating Toolbar"
viewer.configuration.floatingToolbar = {
    enabled: true,
    cssClass: "my-toolbar-css-class",
    editButtonClass: "edit-btn",
    selectButtonClass: "select-btn",
    deleteButtonClass: "delete-btn",
    handleButtonClass: "handle-btn",
    bigButtonCssClass: "big",
};
viewer.configuration = viewer.configuration;
```

### Styling the Toolbar

Use CSS to customize the appearance of the toolbar:

```css title="Styling the Toolbar"
.my-toolbar-css-class {
    background-color: white;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    border-radius: 2px;
    padding: 4px;
    margin: 10px 1px;
}

.my-toolbar-css-class button {
    width: auto;
    height: 30px;
    padding: 9px;
    border: 0;
}

.my-toolbar-css-class button:hover {
    background-color: gray;
}

.my-toolbar-css-class .edit-btn::before {
    content: 'Edit';
}

.my-toolbar-css-class .select-btn::before {
    content: 'Select';
}

.my-toolbar-css-class .delete-btn::before {
    content: 'Delete';
}
```

### Handling Toolbar button events

To handle button clicks:

```javascript title="Handling Toolbar Button Events"
viewer.eventManager.addDeleteToolbarButtonClick((item) => { console.log('delete') });
viewer.eventManager.addEditToolbarButtonClick((item) => { console.log('edit') });
viewer.eventManager.addSelectToolbarButtonClick((item) => { console.log('select') });
viewer.eventManager.addHandleToolbarButtonClick((item) => { console.log('handle') });
```

### Disabling the Toolbar

To disable the Floating Toolbar:

```javascript title="Disabling the Toolbar"
viewer.canvas.floatingToolbarManager.enabled = false;
```

## Managing Layers

To move layers up and down, for example, text above an image, use the `bringItems` command:

```javascript title="Managing Layers"
const selectedItems = viewer.selectedItems;
const position = "bottom"; // Possible values: "front", "levelUp", "levelDown", "bottom"
viewer.commandManager.execute(ItemsCommand.bringItems, { items: selectedItems, position: position });
```

:::note
Ensure that the item has defined `itemPermisssions.allowZOrderChange=true`.
:::

## Snap lines

To enable snap lines for guiding users when moving items:

```javascript title="Enabling Snap Lines"
const itemConfig = { enabled: true, includeLocked: false, color: "magenta", priority: 1, tolerance: 5 };
const otherElementsConfig = { enabled: true, color: "magenta", priority: 1, tolerance: 5 };

viewer.configuration.snapLines = {
    snapElements: {
        items: itemConfig,
        printArea: otherElementsConfig,
        grid: otherElementsConfig,
        region: otherElementsConfig,
        safetyLines: otherElementsConfig
    }
};
viewer.configuration = viewer.configuration;
```

## Restricting item movements

To restrict users from moving images beyond the safety line, you can use the `region` property of `SurfaceContainer`:

```javascript title="Restricting Item Movements"
mainContainer.region = new RectangleF(300, 350, 400, 400);
```

## Displaying violation warnings

To display warnings when items are outside the print area or safety lines:

1. Set the main surface container name to "Main":

   ```javascript
   const mainContainer = new SurfaceContainer([imageItem], "Main");
   ```

2. Configure the violation service:

   ```javascript title="Configuring Violation Service"
   viewer.configuration.violationService = {
       bleedViolationWarningEnabled: false,
       inPlaceNotSupportedWarningEnabled: false,
       qualityChangeContainersEnabled: true,
       qualityMeter: { enabled: false, qualityLevels: { bad: 30, warning: 70 }, renderingDpi: 300 },
       regionViolationWarningEnabled: false,
       safetyLines: { enabled: true, mode: SafetyLineViolationMode.PartiallyInsideAny },
       textCropViolationWarningEnabled: false,
       enabled: true,
       violationWarningButtonsEnabled: true,
   };
   viewer.configuration = viewer.configuration;
   ```

3. Subscribe to violation events and display custom messages:

    ```javascript title="Subscribing to Violation Events"
    viewer.violationService.addItemViolationStateChanged((args) => {
        const msg = `Violation state changed for item [${args.new.item.name}] => ${ViolationState[args.new.state]}`;
        if (args.new.state == ViolationState.Bad || args.new.state == ViolationState.Warning) {
            console.warn(msg, args.new.messages);
        }
    });
    ```

## Visual Enhancements

### Displaying guiding lines during item movement

To show guiding lines (e.g., for centering objects relative to `printArea`), configure `snapLines`: in the **Editor.ts** at the very end of the `initViewer` method after the `Editor.configureCanvas` add:

```javascript title="Displaying Guiding Lines"
const viewerConfig = this._viewer.configuration;
const defaultElementConf = {
    tolerance: 5,
    color: "rgb(255,0,255)",
    enabled: false,
    priority: 0
};
viewerConfig.snapLines = {
    snapElements: {
        items: { ...defaultElementConf, includeLocked: false },
        printArea: { ...defaultElementConf },
        safetyLines: { ...defaultElementConf },
        region: { ...defaultElementConf },
        grid: { ...defaultElementConf }
    }
};
viewerConfig.snapLines.snapElements.printArea.enabled = true;
this._viewer.configuration = viewerConfig;
```

### Customizing the selection border

To customize the border of the selected items (e.g., change color and padding):

```javascript title="Customizing Selection Border"
viewer.canvas.style.selection.color = "#FFA500";
```

### Customizing the rotation button icon

To replace the rotation button icon with a custom image:

```javascript title="Customizing Rotation Button Icon"
let image = document.createElement("img");
image.onload = () => {
    viewer.canvas._canvasRenderer._rotationIconImage = image;
};
image.src = "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/atom.svg";
```
