Using something like paperScroller.zoom(0.2, { max: 5 });
only causes svg elements to be zoomed, whereas in my custom shape, I've used html as well, which doesn't scale in tandem.
Since there's no model.change event firing on scaling, the updateBox method in ElementView doesn't get called and so the html elements don't sync their dimensions and positioning accordingly. Is there a way to work around this?
Extending on Marc_Alx's answer.
Calling paper.translate() and paper.scale() fires 'translate' and 'scale' events on the paper.
Custom Elements can listen to these events on their custom ElementView.
For example, if you scale on mousewheel event:
paper.on('blank:mousewheel', (event, x, y, delta) => {
const scale = paper.scale();
paper.scale(scale.sx + (delta * 0.01), scale.sy + (delta * 0.01),);
});
Override render methods of your custom ElementView to listen to 'scale' event on the paper.
render(...args) {
joint.dia.ElementView.prototype.render.apply(this, args);
this.listenTo(this.paper, 'scale', this.updateBox);
this.listenTo(this.paper, 'translate', this.updateBox);
this.paper.$el.prepend(this.$box);
this.updateBox();
return this;
},
And the custom ElementView's updateBox should retrieve the scale value from the paper.
updateBox() {
if (!this.paper) return;
const bbox = this.getBBox({ useModelGeometry: true });
const scale = joint.V(this.paper.viewport).scale();
// custom html updates
this.$box.find('label').text(this.model.get('label'));
this.$box.find('p').text(this.model.get('response'));
// end of custom html updates
this.$box.css({
transform: `scale(${scale.sx},${scale.sy})`,
transformOrigin: '0 0',
width: bbox.width / scale.sx,
height: bbox.height / scale.sy,
left: bbox.x,
top: bbox.y,
});
}
I've found a workaround for those who are not using rappid.js
(paperScroller
is only available for rappid
).
Assuming you have an element similar to this one : http://jointjs.com/tutorial/html-elements
My answer is inspired from Murasame answer's from How to scale jonitjs graphs? and assume that you update scale of your paper
on mousewheel
(+0.1 -0.1).
First inside your custom ElementView
store a numeric property (initialized to 1) that will store the scale, let's name it scale
(accessed via this.scale
).
Next in the overrided method render
(of your cutom ElementView
) listen to mousewheel
events of the paper : this.paper.$el.on('mousewheel',…)
in the handler update the scale
property (+=0.1 or -=0.1), then call updateBox
Finally in the updateBox
method at this line :
this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
Multiply width
, height
, x
, y
by this.scale
to get :
this.$box.css({ width: bbox.width*this.scale, height: bbox.height*this.scale, left: bbox.x*this.scale, top: bbox.y*this.scale, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
I think it's a good start for implementing this behavior, you should also size the content of your element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With