如何找到旋转角度以使用 css3d 制作 SVG 圆弧 "stand up"
How to find angle of rotation to make an SVG arc "stand up" with css3d
我有 arcs 连接 d3 力导向图中的节点,整个 SVG 用 CSS 转换。现在弧线感觉不像躺在地上那样好看,所以我想得到它们 "stand up",或者旋转 X,Y,Z 来获得效果。
我已将变换原点设置为连接节点的线的中心,但现在我无法找到必须旋转圆弧以使它们直立的角度。任何关于寻找角度的 idea/formula 都非常感谢。
我现在在 tick
函数中的代码如下所示:
force.on("tick", function() {
path.attr("d", function (d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy) -200;
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
})
.attr('style', function(d){
var rotateX = 0, rotateY = 0, rotateZ = 0;
return "transform-origin:" + (d.source.x + d.target.x)/2 + "px " + (d.source.y + d.target.y)/2 + "px" +
";transform:rotateX("+rotateX+"deg) rotateY("+rotateY+"deg) rotateZ("+rotateZ+"deg)";
});
rotateX、rotateY 和 rotateZ 角度正是我要找的!
我没有d3的实用知识,所以我已经解决了标准javascript布局的问题。
希望程序也能正常工作。
在demo中,点击2次设置圆弧的起点和终点。然后再次单击以查看它在 3d 中旋转。
你可以重复循环多少次。
在变换演算中,我们只是计算平面内与atan2的夹角,以及水平和垂直的差值。真正的诀窍是设置 90 度,这将使元素垂直 在 (表示法)平面旋转之后。
请注意,在代码片段中我没有应用 90 度,而是 80 度,因此从上方看时弧线仍然可见。
var sequence = 0;
var x1, y1, x2, y2;
function getCursorPosition(event) {
var x = event.clientX;
var y = event.clientY;
var ele = document.getElementById('container');
if (sequence == 0) {
x1 = x;
y1 = y;
sequence = 1;
ele.classList.remove("animate");
} else if (sequence == 1) {
x2 = x;
y2 = y;
sequence = 2;
Compute();
} else {
ele.classList.add("animate");
sequence = 0;
}
}
function Compute() {
var ele = document.getElementById('inner');
var width = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
ele.style.width = width + "px ";
ele.style.height = width / 2 + "px ";
ele.style.left = x1 + "px ";
ele.style.top = y1 + "px ";
var angle = Math.atan2(y2 - y1, x2 - x1);
var deg = angle * 180.0 / Math.PI;
ele.style.transform = "rotate(" + deg + "deg) rotateX(80deg) "
/*
var style = "width:" + width + "px ";
style += "left: " + x1 + "px ";
style += "top: " + y1 + "px ";
ele.setAttribute("style",style);
*/
}
.container {
width: 600px;
height: 400px;
border: solid 1px green;
perspective: 1000px;
transform-style: preserve-3d;
position: absolute;
background-image: repeating-linear-gradient(white 0px, wheat 50px, white 100px);
}
#inner {
width: 100px;
height: 50px;
border-radius: 0px 0px 100px 100px;
background-color: green;
position: absolute;
transform-origin: left top;
transform-style: preserve-3d;
}
.animate {
animation: rota 15s 1;
}
@keyframes rota {
from {
transform: perspective(1000px) rotateX(0deg);
}
to {
transform: perspective(1000px) rotateX(360deg);
}
}
<div class="container" id="container" onclick="getCursorPosition(event)">
<div id="inner">
</div>
</div>
我有 arcs 连接 d3 力导向图中的节点,整个 SVG 用 CSS 转换。现在弧线感觉不像躺在地上那样好看,所以我想得到它们 "stand up",或者旋转 X,Y,Z 来获得效果。
我已将变换原点设置为连接节点的线的中心,但现在我无法找到必须旋转圆弧以使它们直立的角度。任何关于寻找角度的 idea/formula 都非常感谢。
我现在在 tick
函数中的代码如下所示:
force.on("tick", function() {
path.attr("d", function (d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy) -200;
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
})
.attr('style', function(d){
var rotateX = 0, rotateY = 0, rotateZ = 0;
return "transform-origin:" + (d.source.x + d.target.x)/2 + "px " + (d.source.y + d.target.y)/2 + "px" +
";transform:rotateX("+rotateX+"deg) rotateY("+rotateY+"deg) rotateZ("+rotateZ+"deg)";
});
rotateX、rotateY 和 rotateZ 角度正是我要找的!
我没有d3的实用知识,所以我已经解决了标准javascript布局的问题。
希望程序也能正常工作。
在demo中,点击2次设置圆弧的起点和终点。然后再次单击以查看它在 3d 中旋转。
你可以重复循环多少次。
在变换演算中,我们只是计算平面内与atan2的夹角,以及水平和垂直的差值。真正的诀窍是设置 90 度,这将使元素垂直 在 (表示法)平面旋转之后。
请注意,在代码片段中我没有应用 90 度,而是 80 度,因此从上方看时弧线仍然可见。
var sequence = 0;
var x1, y1, x2, y2;
function getCursorPosition(event) {
var x = event.clientX;
var y = event.clientY;
var ele = document.getElementById('container');
if (sequence == 0) {
x1 = x;
y1 = y;
sequence = 1;
ele.classList.remove("animate");
} else if (sequence == 1) {
x2 = x;
y2 = y;
sequence = 2;
Compute();
} else {
ele.classList.add("animate");
sequence = 0;
}
}
function Compute() {
var ele = document.getElementById('inner');
var width = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
ele.style.width = width + "px ";
ele.style.height = width / 2 + "px ";
ele.style.left = x1 + "px ";
ele.style.top = y1 + "px ";
var angle = Math.atan2(y2 - y1, x2 - x1);
var deg = angle * 180.0 / Math.PI;
ele.style.transform = "rotate(" + deg + "deg) rotateX(80deg) "
/*
var style = "width:" + width + "px ";
style += "left: " + x1 + "px ";
style += "top: " + y1 + "px ";
ele.setAttribute("style",style);
*/
}
.container {
width: 600px;
height: 400px;
border: solid 1px green;
perspective: 1000px;
transform-style: preserve-3d;
position: absolute;
background-image: repeating-linear-gradient(white 0px, wheat 50px, white 100px);
}
#inner {
width: 100px;
height: 50px;
border-radius: 0px 0px 100px 100px;
background-color: green;
position: absolute;
transform-origin: left top;
transform-style: preserve-3d;
}
.animate {
animation: rota 15s 1;
}
@keyframes rota {
from {
transform: perspective(1000px) rotateX(0deg);
}
to {
transform: perspective(1000px) rotateX(360deg);
}
}
<div class="container" id="container" onclick="getCursorPosition(event)">
<div id="inner">
</div>
</div>