【发布时间】:2016-04-22 08:33:49
【问题描述】:
使用 paperScroller.zoom(0.2, { max: 5 }); 之类的东西只会导致 svg 元素被缩放,而在我的自定义形状中,我也使用了 html,它不会同时缩放。
由于缩放时没有触发 model.change 事件,因此不会调用 ElementView 中的 updateBox 方法,因此 html 元素不会相应地同步它们的尺寸和位置。有没有办法解决这个问题?
【问题讨论】:
使用 paperScroller.zoom(0.2, { max: 5 }); 之类的东西只会导致 svg 元素被缩放,而在我的自定义形状中,我也使用了 html,它不会同时缩放。
由于缩放时没有触发 model.change 事件,因此不会调用 ElementView 中的 updateBox 方法,因此 html 元素不会相应地同步它们的尺寸和位置。有没有办法解决这个问题?
【问题讨论】:
扩展 Marc_Alx 的答案。
调用 paper.translate() 和 paper.scale() 会在纸上触发“翻译”和“缩放”事件。
自定义元素可以在其自定义 ElementView 上监听这些事件。
例如,如果您在鼠标滚轮事件上进行缩放:
paper.on('blank:mousewheel', (event, x, y, delta) => {
const scale = paper.scale();
paper.scale(scale.sx + (delta * 0.01), scale.sy + (delta * 0.01),);
});
覆盖自定义 ElementView 的渲染方法以监听纸上的“缩放”事件。
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;
},
并且自定义 ElementView 的 updateBox 应该从纸上检索比例值。
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,
});
}
【讨论】:
我为不使用rappid.js 的用户找到了一种解决方法(paperScroller 仅适用于rappid)。
假设你有一个类似的元素:http://jointjs.com/tutorial/html-elements
我的答案灵感来自 How to scale jonitjs graphs? 的 Murasame 答案,并假设您在 mousewheel (+0.1 -0.1) 上更新了 paper 的比例。
首先在您的自定义ElementView 中存储一个用于存储比例的数字属性(初始化为1),我们将其命名为scale(通过this.scale 访问)。
接下来在被覆盖的方法render(你的自定义ElementView)中监听论文的mousewheel事件:this.paper.$el.on('mousewheel',…)在处理程序中更新scaleproperty(+=0.1或- =0.1),然后拨打updateBox
最后在updateBox方法的这一行:
this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
将width、height、x、y乘以this.scale得到:
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)' });
我认为这是实现此行为的良好开端,您还应该调整元素内容的大小。
【讨论】:
回答这个问题,因为我花了几个小时试图找到解决方案。事实证明,JointJS 上有一个完美运行的演示(但不知何故,谷歌总是给你过时的教程。见:https://github.com/clientIO/joint/issues/1220)。不过,这与 Raunak Mukhia 的回答非常相似。
https://github.com/clientIO/joint/blob/master/demo/shapes/src/html.js
【讨论】: