Svg JointJs:缩放自定义形状html和元素(使用paperScroller.zoom)

Svg JointJs:缩放自定义形状html和元素(使用paperScroller.zoom),svg,jointjs,Svg,Jointjs,使用类似于paperScroller.zoom(0.2,{max:5})的东西只会使svg元素被缩放,而在我的自定义形状中,我也使用了html,它不会连续缩放 由于缩放时没有触发model.change事件,因此不会调用ElementView中的updateBox方法,因此html元素不会相应地同步其维度和位置。有办法解决这个问题吗?我为那些不使用rappid.js的人找到了一个解决办法(paperScroller仅适用于rappid) 假设您有一个与此类似的元素: 我的答案来源于Murah的相

使用类似于
paperScroller.zoom(0.2,{max:5})的东西
只会使svg元素被缩放,而在我的自定义形状中,我也使用了html,它不会连续缩放


由于缩放时没有触发model.change事件,因此不会调用ElementView中的updateBox方法,因此html元素不会相应地同步其维度和位置。有办法解决这个问题吗?

我为那些不使用
rappid.js
的人找到了一个解决办法(
paperScroller
仅适用于
rappid

假设您有一个与此类似的元素:

我的答案来源于Murah的相同答案,并假设您在
鼠标滚轮上更新了
论文的比例(+0.1-0.1)

  • 首先,在自定义
    ElementView
    中存储一个数字属性(初始化为1),该属性将存储刻度,我们将其命名为
    scale
    (通过
    this.scale
    访问)

  • 接下来,在覆盖的方法
    render
    (您的cutom
    ElementView
    )中,收听论文的
    mouseweel
    事件:
    this.paper.$el.on('mouseweel',…)
    ,在处理程序中更新
    scale
    属性(+=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')

    宽度
    高度
    x
    y
    乘以
    。按比例
    得出:

    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'))


我认为这是实现此行为的一个良好开端,您还应该调整元素内容的大小。

扩展Marc_Alx的答案

调用paper.translate()和paper.scale()在纸张上触发“translate”和“scale”事件

  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;
},
  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,
    });
  }
自定义元素可以在其自定义元素视图上侦听这些事件

例如,如果在鼠标滚轮事件上缩放:

  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;
},
  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,
    });
  }
自定义ElementView的updateBox应该从图纸中检索比例值

  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;
},
  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,
    });
  }

回答这个问题,因为我花了几个小时试图找到解决办法。事实证明,JointJS上有一个完美的演示(但不知怎么的,谷歌总是给你提供过时的教程。请参阅:)。但这与Raunak Mukhia的答案非常相似