【问题标题】:Bounding box / bbox for a group after rotation in svg.jssvg.js中旋转后组的边界框/ bbox
【发布时间】:2020-05-26 23:07:53
【问题描述】:

使用 svg.js,我绘制了一个(游戏)板,它本质上是一组六边形路径。添加完所有六边形后,我想将整个组旋转 -60 度,然后读出一个包含生成的(视觉)形状的最小矩形框。

我想要的板子和盒子的外观(红色手绘):

但我不知道如何获得红色盒子;我所得到的似乎都是蓝色形状周围的盒子(当然是整个组的 bbox,本身旋转):

我发现的一些提示是使用外部组(依次包含收集字段的组);旋转内组,从外组得到 bbox();不幸的是,这并没有改变什么。或者,网络上的一些来源建议改用 rbox(),但这又没有改变,甚至不在 svg.js 3.0 的文档中。

为了完整起见,执行相关操作的代码,尽管这似乎是一个更普遍的问题。我意识到我可以通过首先避免轮换来规避这个问题,但我想找到一种解决方案,无需手动调整即可解决一系列类似情况。

 draw_board() {
        let grp = this.canvas.group();
        for (let field of this.fields) {
            field.hex_display = grp.use(hexsym).size(this.w*this.hex_scale,this.h*this.hex_scale)
                .center(field.cx,field.cy)
                .addClass("hex_field")
                .addClass(this.color);

        }
        let count = this.field.length;
        let clipper = this.canvas.clip().path()
              .M(...this.center(0,0))
              .L(...this.center(0,count-1))
              .L(...this.center(count-1,count-1))
              .L(...this.center(count-1,0))
              .Z();
        grp.clipWith(clipper);
        grp.rotate(-60);
        let bb = grp.bbox();
        this.canvas.viewbox(bb.x,bb.y,bb.w,bb.h)
    }

有什么方法可以解决这个问题吗?

【问题讨论】:

标签: javascript svg svg.js


【解决方案1】:

这是扩展@RobertLongson 评论的示例。红色是getBoundingClientRect,绿色是getBBox。我不确定两者是否会为您解决问题。使用 getBoundingClientRect 需要计算 svg 相对于文档的位置——这就是它偏移的原因。

var rotate = 0;

function doRotation() {
  rotate += 10;
  if (rotate === 360) {
    rotate = 0;
  }
  var pathElement = document.querySelector('#path_1');
  pathElement.setAttribute('transform', 'rotate(' + rotate + ' 40 40 )');
  var groupElement = document.querySelector('#group_1');
  var rectBBox = document.querySelector('#rect_1');
  var rectBoundingClientRect = document.querySelector('#rect_2');

  var bboxGroup = groupElement.getBBox();
  rectBBox.setAttribute('x', bboxGroup.x);
  rectBBox.setAttribute('y', bboxGroup.y);
  rectBBox.setAttribute('width', bboxGroup.width);
  rectBBox.setAttribute('height', bboxGroup.height);

  var boundingClientRectGroup = groupElement.getBoundingClientRect();
  rectBoundingClientRect.setAttribute('x', boundingClientRectGroup.x);
  rectBoundingClientRect.setAttribute('y', boundingClientRectGroup.y);
  rectBoundingClientRect.setAttribute('width', boundingClientRectGroup.width);
  rectBoundingClientRect.setAttribute('height', boundingClientRectGroup.height);
}
setInterval(doRotation, 100);
svg {
  overflow: visible
}
<svg height="100px" viewBox="0 0 100 100">
  <g  id="group_1">
  <path id="path_1" d="M35,25 L60,25 L50,50 L25,50 Z"></path>
  </g>
  <rect vector-effect="non-scaling-stroke" id="rect_1" stroke="#00ff00" stroke-width="1" fill="none"> </rect> 
  <rect  vector-effect="non-scaling-stroke" id="rect_2" stroke="#ff0000" stroke-width="1" fill="none"></rect> 
</svg>

【讨论】:

    【解决方案2】:

    使用 rbox。就这么简单grp.rbox(this.canvas)

    Rbox 基本上是一个围绕 getBoundingClientRect 的包装器。但是,如果您传入一个元素,则框将转换为该元素的坐标系。在您的情况下,您需要画布坐标系统中的坐标。

    如果您在没有参数的情况下调用 rbox,它会在屏幕坐标中为您提供一个带有滚动条的框(与 getBoundingClientRect 不同)

    这里是文档的链接:https://svgjs.dev/docs/3.0/manipulating/#rbox

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 2015-12-27
      • 1970-01-01
      • 2014-01-24
      • 2019-01-18
      • 2018-05-08
      • 1970-01-01
      相关资源
      最近更新 更多