简体   繁体   English

d3.js奇数旋转行为

[英]d3.js Odd Rotation Behavior

I'm in the early stages of a JS project. 我正处于JS项目的早期阶段。 Everything is going fine so far except for the positioning of one shape. 到目前为止,除了一个形状的定位外,一切都很顺利。 The shape in question is a teal diamond (square rotated 45 degrees). 所讨论的形状是蓝绿色钻石(正方形旋转45度)。 I can get the square on the screen no problem, but when I add: 我可以让屏幕上的方块没问题,但是当我添加:

    .attr("transform", "rotate(45)")

the square rotates properly, but shifts towards the left portion of the screen, like this: 正方形旋转正确,但向屏幕的左侧部分移动,如下所示:

在此输入图像描述

I am not sure what is causing this to happen. 我不确定是什么导致这种情况发生。 If it helps, here is some of the code that produced this result: 如果有帮助,这里有一些产生这个结果的代码:

var svg = d3.select("body")
            .append("svg")
            .attr("width", w)
            .attr("height", h);
        svg
            .append("rect")
            .attr("transform", "rotate(45)")
            .attr("x", 250)
            .attr("height", w / 10)
            .attr("width", w / 10)
            .attr("fill", "teal")

Note: If I put the "y" attribute in, the square disappears completely. 注意:如果我输入“y”属性,则方块完全消失。

What is causing this? 是什么造成的? Did I do something wrong that I just can't see? 我做错了什么,我看不到?

When you rotate the rect, you also rotate its coordinate system. 旋转矩形时,还可以旋转其坐标系。 So when you later move it 250 along the x axis, you're actually moving it 250 units along a 45 degree axis -- the result of the rotation. 因此,当您稍后沿x轴移动250时,您实际上是沿着45度轴移动250个单位 - 旋转的结果。

As a rule, when you introduce a transform attribute as you did for rotate , you should do all your transformation via this attribute. 通常,当您为rotate引入transform属性时,应该通过此属性执行所有变换。 So, you need to use translate instead of using the "x" attribute. 因此,您需要使用translate而不是使用"x"属性。 Then it would look like this: 然后它看起来像这样:

svg
  .append("rect")
  .attr("transform", "translate(250, 0) rotate(45)")
  // remove this: .attr("x", 250)
  .attr("height", w / 10)
  ...

This gets you the results I think you're looking for. 这可以为您提供我认为您正在寻找的结果。 Now note that the order of transformations matters here: if your transform was "rotate(45) translate(250, 0)" (ie first rotate then translate), you'd get the same, wrong results you got before. 现在请注意,转换的顺序在这里很重要:如果你的变换是"rotate(45) translate(250, 0)" (即先旋转然后翻译),你会得到与之前相同的错误结果。 That's because when you rotate first, your translation happens, as before, along a rotated x axis. 那是因为当您首先旋转时,您的平移将像以前一样沿着旋转的x轴发生。

In SVG you must set the transform origin to get it to rotate from the center, such as... 在SVG中,您必须设置变换原点以使其从中心旋转,例如......

.attr("transform", "rotate(45, 250, 100)");

Where 250, 100 is the x and y position of your rect minus it's radius. 其中250, 100是x,你的矩形的y坐标减去它的半径。 Putting it all together it would look like... 把它们放在一起它看起来像......

var svg = d3.select("body")
            .append("svg")
            .attr("width", 400)
            .attr("height", 300);
        svg
            .append("rect")
            .attr("transform", "rotate(30,"+ (diamond.x+diamond.width/2) + ","+ (diamond.y+diamond.width/2) +")")
            .attr("x", diamond.x)
            .attr("y", diamond.y)
            .attr("height", diamond.width)
            .attr("width", diamond.width)
            .attr("fill", "teal")​

You can view a demo here: 您可以在此处查看演示:

http://jsfiddle.net/uwM8u/ http://jsfiddle.net/uwM8u/

Here is an approach slightly different from the answer Duopixel gave. 这是一种与Duopixel给出的答案略有不同的方法。 Here you are not repeating the calculations for X and Y. In Duopixel's example, its a trivial improvement since he is merely referencing a structure. 在这里,你不是要重复X和Y的计算。在Duopixel的例子中,由于他只是引用一个结构,所以它是一个微不足道的改进。 Its often the case that X and Y are functions and I would not want to maintain that loging in two places. 通常情况下X和Y是函数,我不想在两个地方保持记录。 This approach allows you to set X and Y a node, then rotate on the center of said node. 此方法允许您将X和Y设置为节点,然后在所述节点的中心旋转。

You may find that after the rotation, you still want to tweak the final position, which could be done with another transform, or in the case of TEXT, you can use dx, dy. 您可能会发现在旋转之后,您仍然想要调整最终位置,这可以通过另一个变换完成,或者在TEXT的情况下,您可以使用dx,dy。

    svgNode.attr("transform", function (d) {

                    var w = +d3.select(this).attr("x") +  (this.getBBox().width / 2) ;
                    var h = +d3.select(this).attr("y") + (this.getBBox().height / 2);

                    return  "rotate(90," + w + "," + h + ")";

                })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM