通过点移动SVG路径 [英] Moving SVG path through points

查看:27
本文介绍了通过点移动SVG路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能看起来很奇怪,但我想通过一个固定点移动一些 SVG 路径.我知道我们如何使用 通过路径动画点,我试图获得相同的结果,但点将被固定并且路径将通过它.

到目前为止,我认为我可以使用 path.getTotalLength(),我做了一个循环来在我的路径上创建点,我想动画我的路径以每个点为中心,但我的对 SVG 和 Javascript 的了解非常有限.

const path = document.getElementById('chemin')让 svg = document.getElementById("mySVG");让 totalLength = path.getTotalLength();让交叉点= 30;for (var i = 0; i <= 交叉点; i++) {让距离 = i * 1/交叉点 * totalLength;让点 = path.getPointAtLength(distance);addCircleToSVG(point.x, point.y);}函数 addCircleToSVG(x, y) {let circle = document.createElementNS("http://www.w3.org/2000/svg", 'circle');circle.setAttribute("cx", x);circle.setAttribute("cy", y);circle.setAttribute("r", "5");circle.setAttribute("fill", "#8888ff");svg.appendChild(圆圈);}

<svg version="1.1" id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"x="0px" y="0px" viewBox="0 0 1306 989" style="enable-background:new 0 0 1306 989;"xml:space="保留"><style type="text/css">.st1 {填充:#fff;中风:#000000;笔画宽度:3;行程斜接限制:10;}.st2 {填充:无;中风:#ff0000;笔画宽度:8;行程斜接限制:10;笔画线帽:圆形;}</风格><g><path id="chemin" class="st2" d="M315,443l13-11h13l13-2h9l7.5,1.5h10l8-4l4-5l15,5l10,4h12h16l16-2l4-1h11h9l8-24l7.5,1.5h12h16l16-2l4-1h11h9l8-24l5l-6l5-3v-4l4-3l5-1h11c0,0,0,0,2,0s12,0,12,0l6,3l3,4l4,4l6,2c0,0,1,0,3-1s6-3,6-3l3-2l5,1h6l8,3l8,1c0,0,4,1,5,1s9,0,9,0l7,1h9h5l6-2l4-1l4-3l5-2l6-4l4-5l4-4l2-5c0,0,1-2,1-4s0-5,0-5v-4c0,0,4,3,4,3l7,2l5,3l6,1l11,2l8,2l7,5l10,2c3-3,6-5,6-5l4-3l4-2l4,2l4-1l-2-6l5-5c0,0,8,3,8,0s4-6,4-6l6-4l3-4l6-6c0,0,0-3-2-7s-5-8-5-8s-2-5-3-9s-4-9-4-11s2-6,1-8s-5-7-5-7v-8l-1-7v-5l-8-11"></路径></svg>

一开始这似乎是一个想法,但现在我觉得它不会让我到达任何地方,我被卡住了......

一张图可能会让这更容易理解,这就是步骤"我要

解决方案

主要的想法是我在改变圆在路径上的位置的同时改变了 svg 元素的 viewBox 属性的值.这给人一种错觉,即路径在移动而不是点.

我正在使用输入类型范围来移动圆圈.

start 变量表示路径开始的点(d=M315,443...)以及点的初始位置:<代码>.

请阅读代码中的注释.

let lengthChemin = chemin.getTotalLength();//路径上圆的起点让开始={x:315,y:443}//同时移动滑块的拇指control.addEventListener("输入", ()=>{//获取输入的实际值让 val = parseInt(control.value);//获取圆在路径上的新位置让 pos = chemin.getPointAtLength(lengthChemin*val/100);//更新圆的位置更新元素({cx:pos.x,cy:pos.y},圆)//更新viewBox的值theSVG.setAttribute("viewBox",`${pos.x - start.x} ${pos.y - start.y} 1306 600`)})函数更新元素(o,元素){for(o 中的 var 名称){如果(o.hasOwnProperty(名称)){element.setAttributeNS(null, name, o[name]);}}返回元素;}

</路径><circle id="circle" cx="315" cy="443" r="10"/></svg>

<块引用>

观察:我只用路径和圆圈翻译组,因为我希望它在您运行代码段时可见.您可以删除它.

it might seem weird but i would like to move some SVG path through a fixed point. I get how we can animate a dot through a path with <animateMotion> and I'm trying to get the same result but the dot would be fixed and the path would move through it.

So far, I thought I could work with path.getTotalLength(), I made a loop to create dots on my path and I wanted to animate my path to be centered on each dot but my knowledge on SVG and Javascript is pretty limited.

const path = document.getElementById('chemin')
let svg = document.getElementById("mySVG");
let totalLength = path.getTotalLength();
let intersections = 30;

for (var i = 0; i <= intersections; i++) {
    let distance = i * 1 / intersections * totalLength;
    let point = path.getPointAtLength(distance);
    addCircleToSVG(point.x, point.y);
}

function addCircleToSVG(x, y) {
    let circle = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
    circle.setAttribute("cx", x);
    circle.setAttribute("cy", y);
    circle.setAttribute("r", "5");
    circle.setAttribute("fill", "#8888ff");
    svg.appendChild(circle);
}

<div class="svgDiv">
    <svg version="1.1" id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
        x="0px" y="0px" viewBox="0 0 1306 989" style="enable-background:new 0 0 1306 989;" xml:space="preserve">
        <style type="text/css">
            .st1 {
                fill: #fff;
                stroke: #000000;
                stroke-width: 3;
                stroke-miterlimit: 10;
            }

            .st2 {
                fill: none;
                stroke: #ff0000;
                stroke-width: 8;
                stroke-miterlimit: 10;
                stroke-linecap: round;
            }
        </style>
        <g>
            <path id="chemin" class="st2" d="M315,443l13-11h13l13-2h9l7.5,1.5h10l8-4l4-5l15,5l10,4h12h16l16-2l4-1h11h9l8-6h6l8-2l5-3l4-2l5-4l3-3v-4l4-3
                    l5-1h11c0,0,0,0,2,0s12,0,12,0l6,3l3,4l4,4l6,2c0,0,1,0,3-1s6-3,6-3l3-2l5,1h6l8,3l8,1c0,0,4,1,5,1s9,0,9,0l7,1h9h5l6-2l4-1l4-3
                    l5-2l6-4l4-5l4-4l2-5c0,0,1-2,1-4s0-5,0-5v-4c0,0,4,3,4,3l7,2l5,3l6,1l11,2l8,2l7,5l10,2c3-3,6-5,6-5l4-3l4-2l4,2l4-1l-2-6l5-5
                    c0,0,8,3,8,0s4-6,4-6l6-4l3-4l6-6c0,0,0-3-2-7s-5-8-5-8s-2-5-3-9s-4-9-4-11s2-6,1-8s-5-7-5-7v-8l-1-7v-5l-8-11">
            </path>
        </g>
    </svg>

</div>
        

It seemed like an idea at first but now I feel like it won't get me anywhere and I'm stuck...

EDIT: A picture might make this more understandable, that's the "steps" I want

解决方案

The main idea is that I'm changing the value of the viewBox attribute of the svg element while I'm changing the postion of the circle on the path. This is giving the illusion that the path is moving not the dot.

I'm using an input type range to move the circle.

The start variable represents the point where the path is starting (d="M315,443...) and also the initial position of the dot: <circle cx="315" cy="443".

Please read the comments in the code.

let lengthChemin = chemin.getTotalLength();
// the starting point of the circle on the path
let start={x:315,y:443}

//while moving the thumb of the slider
control.addEventListener("input", ()=>{
  // get the actual value of the input
  let val = parseInt(control.value);
  //get the new position of the circle on the path
  let pos = chemin.getPointAtLength(lengthChemin*val/100);
  //update the circle's position
  updateElement({cx:pos.x, cy:pos.y}, circle)
  //update the viewBox value
  theSVG.setAttribute("viewBox",`${pos.x - start.x} ${pos.y - start.y} 1306 600`)
})


function updateElement(o, element) {
  for (var name in o) {
    if (o.hasOwnProperty(name)) {
      element.setAttributeNS(null, name, o[name]);
    }
  }
  return element;
}

<input id="control" type="range" min="0" max="100" value="0" />

<svg id="theSVG" viewBox="0 0 1306 600">

  <g transform="translate(0,-250)">
    <path id="chemin" stroke="red" stroke-width="3" fill="none"  d="M315,443l13-11h13l13-2h9l7.5,1.5h10l8-4l4-5l15,5l10,4h12h16l16-2l4-1h11h9l8-6h6l8-2l5-3l4-2l5-4l3-3v-4l4-3
                    l5-1h11c0,0,0,0,2,0s12,0,12,0l6,3l3,4l4,4l6,2c0,0,1,0,3-1s6-3,6-3l3-2l5,1h6l8,3l8,1c0,0,4,1,5,1s9,0,9,0l7,1h9h5l6-2l4-1l4-3
                    l5-2l6-4l4-5l4-4l2-5c0,0,1-2,1-4s0-5,0-5v-4c0,0,4,3,4,3l7,2l5,3l6,1l11,2l8,2l7,5l10,2c3-3,6-5,6-5l4-3l4-2l4,2l4-1l-2-6l5-5
                    c0,0,8,3,8,0s4-6,4-6l6-4l3-4l6-6c0,0,0-3-2-7s-5-8-5-8s-2-5-3-9s-4-9-4-11s2-6,1-8s-5-7-5-7v-8l-1-7v-5l-8-11">
    </path>
    
    <circle id="circle" cx="315" cy="443" r="10"/>
  </g>
  
  
</svg>

Observation: I'm translating the group with the path and the circle ONLY because I want it to be visible when you run the snippet. You can remove this.

这篇关于通过点移动SVG路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆