SVG 在路径上找到点到 x 轴的方向(角度)

SVG find orientation(angle) of a point to the x axis on a path

我通过在路径上移动一个对象来产生视差,它与 getPointAtlength() 一起工作正常,但我还需要随着路径旋转这个对象。

我需要类似 getPointAtLength() 的东西,但对于角度,我得到了点的角度。 Rapheal 似乎有一个方法,但它对在 html 中创建的 svg 元素不友好,或者我不知道如何处理它。有什么想法吗?

var l = document.getElementById('path');
var element=$('#svg_26')
$(window).scroll(function(){
    var pathOffset=parseInt($('#l1').css('stroke-dashoffset'));
    var p = l.getPointAtLength(-1*pathOffset);
    translation = 'translate('+p.x+'px,'+p.y+'px)'
    $(element).css('transform',translation);
})

拉斐尔中的 getPointAtLength returns 具有属性 'alpha' 的对象。 Alpha 是您需要沿着曲线的角度。在上面的示例中,它将是 p.alpha

因此您应该能够对旋转 p.alpha、

的对象应用旋转

例如..

myRaphElement.transform('t' + p.x + ',' + p.y + 'r' + p.alpha).

最后一部分将围绕其中心旋转元素。

如果你不能创建 raph 元素本身,因为 svg 是内联的,我怀疑你最好使用像 Snap.svg 这样的库(它与同一作者的命令基本相同),或者您可以使用 'rotate('+l.alpha+','+l.x+','+l.y+')' 之类的东西通过 css 变换动态旋转

编辑:我误读了标签中的 Raphael,但未被使用。

我个人会在这种情况下使用 Snap,因为 Raphael 并没有在这里添加太多内容。您可以在屏幕外创建一个与内联元素具有相同路径的 Raphael 元素,只是为了使用角度,但是为此加载库感觉有点过分了。

在 Snap 中,您可以使用...访问元素

myElement = Snap('#svg_26')
p = myElement.getPointAtLength(-1*pathOffset);    
myElement.transform('t' + p.x + ',' + p.y + 'r' + p.alpha)

使用库来完成这种任务就太过分了。编写自己的函数来计算角度实际上非常简单。您所要做的就是两次使用 pointAtLength 并稍微偏移一下:

var p1 = path.getPointAtLength(l)
var p2 = path.getPointAtLength(l + 3)

然后使用 Math.atan2

计算所得直线与 x 轴的角度
var deg = Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI);

这里有一个使用上述公式的小例子

var path = document.getElementById("path")
var obj = document.getElementById("obj")
var l = 0
var tl = path.getTotalLength()

function getPointAtLengthWithRotation(path, length) {
  var p1 = path.getPointAtLength(length)
  var p2 = path.getPointAtLength(length + 3)
  var deg = Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI);
  return {
    x: p1.x,
    y: p1.y,
    angle: deg
  }
}

setInterval(function() {
  l += 1
  if (l > tl) l = 0;
  var p = getPointAtLengthWithRotation(path, l)
  obj.setAttribute("transform", "translate(" + p.x + "," + p.y + ") rotate(" + (p.angle + 180) + ")")
}, 30)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
  <path id="path" d="M 81.713425,82.629068 C 77.692791,85.788547 73.298237,77.367896 68.194886,79.039107 63.091534,80.710434 58.027628,96.952068 53.04637,97.140958 48.065112,97.329732 50.503508,75.285207 45.397105,74.05952 40.290703,72.833834 38.487501,93.968537 33.85932,91.287114 29.23114,88.605807 32.245641,70.914733 29.647307,66.19971 27.048973,61.484686 19.604932,68.733636 17.542589,63.315055 15.480245,57.896474 32.172733,59.004979 32.053727,53.363216 31.93472,47.721442 8.0865997,39.989401 9.2246856,34.665848 10.362772,29.342295 28.830448,38.693055 31.065274,33.7132 33.300101,28.733334 22.734045,13.601966 26.210126,9.6067771 29.686208,5.6115765 41.809938,29.357138 46.524268,27.383715 c 4.71433,-1.973424 3.011846,-23.1001292 8.022646,-23.3332919 5.0108,-0.2331744 4.529056,18.3713929 9.45006,20.4259809 4.921003,2.054588 12.017373,-15.4803016 16.717604,-13.058602 4.700233,2.421699 -6.261038,14.180819 -2.913997,18.778859 3.347041,4.59804 12.339067,-3.78046 13.896719,1.543011 1.557652,5.323471 -9.713912,13.199372 -9.176986,18.679109 0.536926,5.479772 19.347976,2.957331 18.124596,8.213665 -1.223374,5.256392 -21.036293,1.236997 -24.253076,5.968111 -3.216785,4.731114 9.342224,14.869033 5.321591,18.028511 z"
  fill="none" stroke="grey" />
  <path id="obj" d="M-5 -5 L5 0L-5 5z" fill="green" />
</svg>

<svg viewBox="0 0 150 100" width="300" height="200">
  <path id="path" d="M 81.713425,82.629068 C 77.692791,85.788547 73.298237,77.367896 68.194886,79.039107 63.091534,80.710434 58.027628,96.952068 53.04637,97.140958 48.065112,97.329732 50.503508,75.285207 45.397105,74.05952 40.290703,72.833834 38.487501,93.968537 33.85932,91.287114 29.23114,88.605807 32.245641,70.914733 29.647307,66.19971 27.048973,61.484686 19.604932,68.733636 17.542589,63.315055 15.480245,57.896474 32.172733,59.004979 32.053727,53.363216 31.93472,47.721442 8.0865997,39.989401 9.2246856,34.665848 10.362772,29.342295 28.830448,38.693055 31.065274,33.7132 33.300101,28.733334 22.734045,13.601966 26.210126,9.6067771 29.686208,5.6115765 41.809938,29.357138 46.524268,27.383715 c 4.71433,-1.973424 3.011846,-23.1001292 8.022646,-23.3332919 5.0108,-0.2331744 4.529056,18.3713929 9.45006,20.4259809 4.921003,2.054588 12.017373,-15.4803016 16.717604,-13.058602 4.700233,2.421699 -6.261038,14.180819 -2.913997,18.778859 3.347041,4.59804 12.339067,-3.78046 13.896719,1.543011 1.557652,5.323471 -9.713912,13.199372 -9.176986,18.679109 0.536926,5.479772 19.347976,2.957331 18.124596,8.213665 -1.223374,5.256392 -21.036293,1.236997 -24.253076,5.968111 -3.216785,4.731114 9.342224,14.869033 5.321591,18.028511 z"
  fill="none" stroke="grey" />
  <polygon points="0,0 -5,-5 -5,5"  style="fill:green">
    <animateMotion begin="0s" dur="10s" rotate="auto" repeatCount="indefinite">
        <mpath xlink:href="#path"></mpath>
    </animateMotion>
  </polygon>
</svg>