Scale viewer(s) to match canvas size

Hey, I’m trying to fit several bpmn-viewer's in different div’s that are arranged using Bootstrap.css.
Although the import of the Bpmn files works without problems, the scaling is a challenge.

The approaches I tried so far:

(1) The use of fit-viewport, but it seems like that will only work for fullscreen viewers / divs:

bpmnViewer.get('canvas').zoom('fit-viewport')

(2) Calculate the zoom value by hand. However, the diagram is shifted to the middle and not drawn at (0,0), which results in the problem that the right side of the diagram is not visible:

// "width" holds the width of the canvas element
// "this.width" holds the width the imported bpmn-diagram
const width = document.getElementById(id).offsetWidth
bpmnViewer.get('canvas').zoom(width / this.width)

(3) Trying to move it manually afterwards:

bpmnViewer.get('canvas').scroll({ dx: -(width / 2), dy: -(height / 2) })

(4) The use of viewport, but scale was not set properly in my application:

bpmnViewer.get('canvas').viewbox({ x: 0, y: 0, width, height, scale: (width / this.width) })

Unfortunately, I got none of the above listed approaches working properly to fix my problem.
Did I miss something?

Thank you in advance for any help.

Could you share what worked and what did not?

Without an example of what you’re running into we can hardly help you.

Hey,

(1) fit-viewport seems to calculate the scaling based on the screen (or the parent)?

(2) Manually scaling lacks at shifting to the middle:

(3) Trying bpmnViewer.get('canvas').scroll({ dx: -(width / 2), dy: 0 }) (where width is the width of the canvas) looks like this. It seems like it is not exactly shifted to the middle:

(4) Using viewbox does not set the scaling:

And what I’m trying to do is an automatic or manual scaling (2) and move the element to (0, 0) because it seems to be shifted.

I finally found a solution (or more like a workaround):

(1) Center the view to the middle of the diagram (solution retrieved from Centering/zooming view to a specific element). this.width holds the width of the diagram and this.height the height of it:

const currentViewbox = bpmnViewer.get('canvas').viewbox()

const elementMid = {
    x: this.width / 2,
    y: this.height / 2
}

bpmnViewer.get('canvas').viewbox({
    x: elementMid.x - currentViewbox.width / 2,
    y: elementMid.y - currentViewbox.height / 2,
    width: currentViewbox.width,
    height: currentViewbox.height
})

(2) Zoom diagram to match the container using the solution (2) from above:

// "width" holds the width of the canvas element
// "this.width" holds the width the imported bpmn-diagram
const width = document.getElementById(id).offsetWidth
bpmnViewer.get('canvas').zoom(width / this.width)

Due to centering the diagram in the first step, it will still be centered afterwards, resulting in the desired behavior:

2 Likes

Thanks for sharing your solution. I’m pretty sure that will help others, too.