绘制包含多个路径的SVG,一个路径一次,使用JavaScript进行动画。

huangapple go评论70阅读模式
英文:

Draw SVG That Contains Multiple Paths, One Path At A Time, Animated With Javascript

问题

我是新手学习SVG动画,我查看了SNAP SVG和其他库,但找不到实现我的目标的方法。
我有一个SVG文件(或者SVG直接集成在HTML中),其中包含多个路径。
我想逐个显示SVG图像中的每个路径,并像下面的示例一样对每个路径进行动画处理:

为了更好地描述我想要的结果,请看这张图片:
绘制包含多个路径的SVG,一个路径一次,使用JavaScript进行动画。

这是一个包含4个路径的SVG元素。
我想使用JavaScript(而不是CSS)逐个绘制每个路径,然后像这样对它们进行动画处理:

绘制包含多个路径的SVG,一个路径一次,使用JavaScript进行动画。

从左到右,每次一个点。以获得类似手绘效果的图像。

编辑:根据@ian的答案,我制作了一个jsfiddle,展示了我到目前为止所做的工作。它逐个显示所有路径,但我想以某种方式模拟它们像绘图一样。所以在所有点之间绘制路径,使其看起来像上面的动画一样。

当前的代码是有效的,因为它逐个显示所有路径,但它没有“绘制它们”,它只是立即显示它们,而不是为每个路径创建动画。

编辑2:
我现在明白了我的形状的问题。它们不是带有点的线,而是一个对象。我需要找到将SVG路径对象转换为带有点的路径的解决方案。

https://jsfiddle.net/sodevrom/mvyru6g5/2/

var s = Snap("#svgout");
var svgin = Snap("#svgin");

function Drawing(svgin, transformString, timeBetweenDraws) {
    this.fragment = svgin;
    this.pathArray = this.fragment.selectAll('path');
    this.group = s.g().transform(transformString).drag();

    this.timeBetweenDraws = timeBetweenDraws;
};

Drawing.prototype.init = function (svgString, transformString) {
    this.group.clear();
    this.currentPathIndex = 0;
};

Drawing.prototype.endReached = function () {
    if (this.currentPathIndex >= this.pathArray.length) {
        return true;
    };
};

Drawing.prototype.callOnFinished = function () {
}

Drawing.prototype.initDraw = function () {
    this.init();
    this.draw();
};

Drawing.prototype.quickDraw = function () {
    this.init();
    this.timeBetweenDraws = 0;
    this.draw();
};

Drawing.prototype.draw = function () {

    if (this.endReached()) {
        if (this.callOnFinished) {
            this.callOnFinished();
            return
        };
    };
    var myPath = this.pathArray[this.currentPathIndex];

    this.leng = myPath.getTotalLength();



    this.group.append(myPath);

    myPath.attr({

        "stroke-dasharray": this.leng + " " + this.leng,
        "stroke-dashoffset": this.leng
    });

    this.currentPathIndex++;

    myPath.animate({"stroke-dashoffset": 2}, this.timeBetweenDraws, mina.easeout, this.draw.bind(this));

};

var myDrawing1 = new Drawing(svgin, 'translate(0,400) scale(0.100000,-0.100000)', 800);
myDrawing1.initDraw();

任何建议都将不胜感激。

谢谢

英文:

I am new to SVG animations, I looked in to SNAP SVG and other libraries, but I cannot find a way to achieve my goal.
I have a SVG file (or the SVG is directly integrated in HTML), that contains multiple paths.
I want to show the SVG image, one path at a time, and animate each path like the example at:

To better describe the result I want, please take a look at this image:
绘制包含多个路径的SVG,一个路径一次,使用JavaScript进行动画。

This is a svg element that contains 4 paths.
I want to show draw each path using javascript (not CSS), one after another, and animate them like:

绘制包含多个路径的SVG,一个路径一次,使用JavaScript进行动画。

From left to right, each point at a time. To obtain something like a hand drawn effect of the image.

EDIT: Based on the answer from @ian, I made a jsfiddle showing what I have done so far. It displays all paths one by one, but I want somehow to simulate them as a drawing. So drawing the path between all points so it looks like in the animation above.

The current code works, in sense that it shows all paths, one by one, but it does not "draw them", it just instantly displays them, instead of creating an animation for each point path.

EDIT 2:
I now understand the problem with my shape. They are not lines with points, but an object. I need to find a solution to turn the svg path object to a path with points.

https://jsfiddle.net/sodevrom/mvyru6g5/2/

var s = Snap("#svgout");
var svgin = Snap("#svgin");
function Drawing(svgin,transformString, timeBetweenDraws ) {
this.fragment =svgin;
this.pathArray = this.fragment.selectAll('path');
this.group = s.g().transform( transformString ).drag();
this.timeBetweenDraws = timeBetweenDraws;
};
Drawing.prototype.init = function( svgString, transformString ) {
this.group.clear();
this.currentPathIndex = 0;
};
Drawing.prototype.endReached = function() {
if( this.currentPathIndex >= this.pathArray.length ) {
return true;
};
};
Drawing.prototype.callOnFinished = function() {
}
Drawing.prototype.initDraw = function() {
this.init();
this.draw();
};
Drawing.prototype.quickDraw = function() {
this.init();
this.timeBetweenDraws = 0;
this.draw();
};
Drawing.prototype.draw = function() {
if( this.endReached() ) {
if( this.callOnFinished ) {
this.callOnFinished();
return
};
};
var myPath = this.pathArray[ this.currentPathIndex ] ;
this.leng = myPath.getTotalLength();
this.group.append( myPath );
myPath.attr({
"stroke-dasharray": this.leng + " " + this.leng,
"stroke-dashoffset": this.leng
});
this.currentPathIndex++;
myPath.animate({"stroke-dashoffset": 2}, this.timeBetweenDraws, mina.easeout, this.draw.bind( this ) );
};
var myDrawing1=new Drawing( svgin, 'translate(0,400) scale(0.100000,-0.100000)', 800 );
myDrawing1.initDraw();

Any suggestions is appreciated.

Thank you

答案1

得分: 2

如在评论中提到的,链接的SO回答是一个很好的起点。如果您想使绘图变得粗糙,一个选项是为每个路径设置超时(您必须匹配延迟与动画速度)。我在这里使用了style属性来实现这一点。

以下是一个简短的演示(CSS版本):

<!-- language: lang-css -->
    .paths path {
         --line-length: 100;
         --delay: 0s;
         --animation-speed: 1s;
           
         stroke-dasharray: var(--line-length);
         stroke-dashoffset: var(--line-length);
         animation: drawPath var(--animation-speed) linear 1 forwards;  
         animation-delay: var(--delay);
    }

    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }
<!-- language: lang-html -->
    <svg width="200" height="200" fill="none" xmlns="http://www.w3.org/2000/svg">
      <g class="paths">
        <path d="M0 50 L 100 50" stroke="red" stroke-width="5"/>
        <path d="M0 100 L 100 100" style="--delay: 1s" stroke="red" stroke-width="5"/>
        <path d="M0 150 L 100 150" style="--delay: 2s" stroke="red" stroke-width="5"/>
      </g>
    </svg>

如果您想使用JavaScript,有一个简单的解决方案。通过设置animation-name来使用JavaScript启动动画,这里是一个简短的演示。为了让所有路径依次绘制,我只是使用了一个Promise。

以下是一个简短的演示(JavaScript版本):

<!-- language: lang-js -->
    let paths = document.querySelectorAll('.paths path');

    function drawPath(path){
      return new Promise((resolve, reject) => {
          path.addEventListener("animationend", resolve);
          path.style.setProperty('animation-name', 'drawPath');
      });
    }

    // 仅供演示,我在循环中启动了所有路径。
    let promise = Promise.resolve();
    for(let path of paths){
        promise  = promise.then(() => drawPath(path));
    }
<!-- language: lang-css -->
    .paths path {
         --line-length: 100;
         --delay: 0.5s;
         --animation-speed: 1s;
           
         stroke-dasharray: var(--line-length);
         stroke-dashoffset: var(--line-length);
         animation-delay: var(--delay); 
         animation-duration: var(--animation-speed); 
         animation-fill-mode: forwards;
         animation-iteration-count: 1;
         animation-timing-function: linear; 
    }
    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }
<!-- language: lang-html -->
    <svg width="200" height="200" fill="none" xmlns="http://www.w3.org/2000/svg">
      <g class="paths">
        <path d="M0 50 L 100 50" stroke="red" stroke-width="5"/>
        <path d="M0 100 L 100 100" stroke="red" stroke-width="5"/>
        <path d="M0 150 L 100 150" stroke="red" stroke-width="5"/>
      </g>
    </svg>

注意:这只在线条是真正的线条而不是有填充的对象时才有效。

更新2:
我有一点时间重新编写/重绘了svg,以便代码可以使用JavaScript和CSS动画。图像看起来不再那么好,但可以进行调整。

以下是更新2的内容:

<!-- language: lang-js -->
    let groups = [
        {name:'#board', animate: false},
        {name:'#note', animate: true},
        {name:'#lines1', animate: true},
        {name:'#chart1', animate: true},
        {name:'#chart2', animate: true},
        {name:'#circle1', animate: true},
        {name:'#circle2', animate: false},
        {name:'#lines2', animate: true},
    ];

    function drawPath(path, shouldAnimate){
      return new Promise((resolve, reject) => {
        if(shouldAnimate){
            path.addEventListener("animationend", resolve);
            path.style.setProperty('animation-name', 'drawPath');
        } else {
            path.style.setProperty('stroke-dashoffset', '0');
            resolve();
        }   
      });
    }

    let promise = Promise.resolve();
    for(let groupName of groups){
        let paths = document.querySelectorAll(`${groupName.name} path`);
        for(let path of paths){
            promise  = promise.then(() => drawPath(path, groupName.animate));
        }
    }
<!-- language: lang-css -->
    path {
      fill: none;
      stroke: black;
      stroke-width: 3;
    }
          
    g path {
       --line-length: 1000;
       --delay: .5s;
       --animation-speed: .5s;

       stroke-dasharray: var(--line-length);
       stroke-dashoffset: var(--line-length);
       animation-delay: var(--delay); 
       animation-duration: var(--animation-speed); 
       animation-fill-mode: forwards;
       animation-iteration-count: 1;
       animation-timing-function: ease-in; 
    }

    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }
<!-- language: lang-html -->
    <svg version="1.0" width="160pt" height="250pt" id="svgin" xmlns="http://www.w3.org/2000/svg"
        xmlns:svg="http://www.w3.org/2000/svg">
        <g transform="translate(-98.084291,-32.694764)" id="board">
            <path d="m 128.59771,65.502953 145.17295,-4.950374 -10.41368,152.307811 10.69581,0.007 0.22371,16.11072 -148.46179,-2.84852 -2.17446,-8.91033 151.39294,2.59059 -0.54008,-6.54345 -145.67879,-5.15697 -5.23251,8.92744 4.76799,-8.74505 8.91742,-0.46453 z" id="path14" />
            <path d="

<details>
<summary>英文:</summary>

As mentioned in the comments, the linked SO Answer is a good starting point. If you want to stagger the drawing a crude, option would be to set the timeout on each path. _(you would have to match the delay with the animations speed)_. I did this here wit the `style` attribute.

**Here a short Demo *(CSS Version)*:**

&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-css --&gt;

    .paths path {
         --line-length: 100;
         --delay: 0s;
         --animation-speed: 1s;
           
         stroke-dasharray: var(--line-length);
         stroke-dashoffset: var(--line-length);
         animation: drawPath var(--animation-speed) linear 1 forwards;  
         animation-delay: var(--delay);
    }

    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }

&lt;!-- language: lang-html --&gt;

    &lt;svg width=&quot;200&quot; height=&quot;200&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
      &lt;g class=&quot;paths&quot;&gt;
        &lt;path d=&quot;M0 50 L 100 50&quot;  stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
        &lt;path d=&quot;M0 100 L 100 100&quot; style=&quot;--delay: 1s&quot; stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
        &lt;path d=&quot;M0 150 L 100 150&quot; style=&quot;--delay: 2s&quot; stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
      &lt;/g&gt;
    &lt;/svg&gt;

&lt;!-- end snippet --&gt;

**Update**  

If you want to use javascript, there is a easy solution. Start the animation with javascript, by setting the `animation-name`, here a short demo. And so that all the path are drawn in succession, I just use a promise.

**Here a short Demo *(Javascript-Version)*:**

&lt;!-- begin snippet: js hide: false console: false babel: false --&gt;

&lt;!-- language: lang-js --&gt;

    let paths = document.querySelectorAll(&#39;.paths path&#39;);

    function drawPath(path){
      return new Promise((resolve, reject) =&gt; {
          path.addEventListener(&quot;animationend&quot;, resolve);
          path.style.setProperty(&#39;animation-name&#39;, &#39;drawPath&#39;);
      });
    }

    // Just for the demo, I&#39;m starting all path&#39;s in a loop.
    let promise = Promise.resolve();
    for(let path of paths){
        promise  = promise.then( () =&gt; drawPath(path));
    }

&lt;!-- language: lang-css --&gt;

    .paths path {
         --line-length: 100;
         --delay: 0.5s;
         --animation-speed: 1s;
           
         stroke-dasharray: var(--line-length);
         stroke-dashoffset: var(--line-length);
         animation-delay: var(--delay); 
         animation-duration: var(--animation-speed); 
         animation-fill-mode: forwards;
         animation-iteration-count: 1;
         animation-timing-function: linear; 

    }
    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }

&lt;!-- language: lang-html --&gt;

    &lt;svg width=&quot;200&quot; height=&quot;200&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
      &lt;g class=&quot;paths&quot;&gt;
        &lt;path d=&quot;M0 50 L 100 50&quot; stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
        &lt;path d=&quot;M0 100 L 100 100&quot; stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
        &lt;path d=&quot;M0 150 L 100 150&quot; stroke=&quot;red&quot; stroke-width=&quot;5&quot;/&gt;
      &lt;/g&gt;
    &lt;/svg&gt;

&lt;!-- end snippet --&gt;

&gt; **Info:** this will only work, if the lines are real lines, not objects with filling.

**Update 2:**  

I had a bit of time and rewrote/re-drew the `svg`, so that the code could work, with javascript and css animations. The image doesn&#39;t look anymore as good, but it could be tweaked.

&lt;!-- begin snippet: js hide: false console: false babel: false --&gt;

&lt;!-- language: lang-js --&gt;

    let groups = [
        {name:&#39;#board&#39;, animate: false},
        {name:&#39;#note&#39;, animate: true},
        {name:&#39;#lines1&#39;, animate: true},
        {name:&#39;#chart1&#39;, animate: true},
        {name:&#39;#chart2&#39;, animate: true},
        {name:&#39;#circle1&#39;, animate: true},
        {name:&#39;#circle2&#39;, animate: false},
        {name:&#39;#lines2&#39;, animate: true},
    ];

    function drawPath(path, shouldAnimate){
      return new Promise((resolve, reject) =&gt; {
        if(shouldAnimate){
            path.addEventListener(&quot;animationend&quot;, resolve);
            path.style.setProperty(&#39;animation-name&#39;, &#39;drawPath&#39;);
        } else {
            path.style.setProperty(&#39;stroke-dashoffset&#39;, &#39;0&#39;);
            resolve();
        }   
      });
    }

    let promise = Promise.resolve();
    for(let groupName of groups){
        let paths = document.querySelectorAll(`${groupName.name} path`);
        for(let path of paths){
            promise  = promise.then( () =&gt; drawPath(path, groupName.animate));
        }
    }

&lt;!-- language: lang-css --&gt;

    path {
      fill: none;
      stroke: black;
      stroke-width: 3;
    }
          
    g path {
       --line-length: 1000;
       --delay: .5s;
       --animation-speed: .5s;

       stroke-dasharray: var(--line-length);
       stroke-dashoffset: var(--line-length);
       animation-delay: var(--delay); 
       animation-duration: var(--animation-speed); 
       animation-fill-mode: forwards;
       animation-iteration-count: 1;
       animation-timing-function: ease-in; 
    }

    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }

&lt;!-- language: lang-html --&gt;

    &lt;svg version=&quot;1.0&quot; width=&quot;160pt&quot; height=&quot;250pt&quot; id=&quot;svgin&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;
        xmlns:svg=&quot;http://www.w3.org/2000/svg&quot;&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;board&quot;&gt;
            &lt;path d=&quot;m 128.59771,65.502953 145.17295,-4.950374 -10.41368,152.307811 10.69581,0.007 0.22371,16.11072 -148.46179,-2.84852 -2.17446,-8.91033 151.39294,2.59059 -0.54008,-6.54345 -145.67879,-5.15697 -5.23251,8.92744 4.76799,-8.74505 8.91742,-0.46453 z&quot; id=&quot;path14&quot; /&gt;
            &lt;path d=&quot;m 190.71946,63.346105 2.04342,-11.238826 c 4.65482,0.907554 9.67602,-3.764323 13.96338,1e-6 l 2.384,10.217114 z&quot; id=&quot;path15&quot; /&gt;
            &lt;path d=&quot;m 154.61899,226.47936 20.43422,0.34056 -37.12218,116.4751 -17.36909,-0.34057 z&quot; id=&quot;path16&quot; /&gt;
            &lt;path d=&quot;m 192.76288,227.1605 5.44913,67.43294 11.23882,3.74628 7.49255,-71.17922 z&quot; id=&quot;path17&quot; /&gt;
            &lt;path d=&quot;m 237.03704,228.52278 34.39761,117.4968 12.26054,2.384 5.78969,-6.81141 -35.41932,-113.06939 z&quot; id=&quot;path18&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;note&quot;&gt;
            &lt;path d=&quot;m 143.72073,79.693487 42.57131,-2.724564 -4.08685,42.911877 -34.73818,3.4057 z&quot; id=&quot;path19&quot; style=&quot;--line-length: 300;&quot; /&gt;
            &lt;path d=&quot;m 168.92295,72.882078 5.44912,-1.021712 v 15.325671 l -6.13026,0.681141 z&quot; id=&quot;path20&quot; style=&quot;--line-length: 100;&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;lines1&quot;&gt;
            &lt;path d=&quot;m 199.23372,80.715198 56.19412,-2.043423 v 0 z&quot; id=&quot;path21&quot; /&gt;
            &lt;path d=&quot;m 198.55258,95.700298 27.92677,-2.724564&quot; id=&quot;path22&quot; /&gt;
            &lt;path d=&quot;m 196.84972,109.32312 22.47765,-2.384&quot; id=&quot;path23&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;chart2&quot;&gt;
            &lt;path d=&quot;m 143.03959,148.48872 15.32567,19.07194 13.62282,-35.41932 15.66624,29.9702 28.26735,-37.46275 20.43423,22.47765 23.83993,-20.09366 -4.42742,14.9851 -12.26053,-12.60111 14.9851,-3.4057&quot; id=&quot;path25&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-96.639373,-33.417223)&quot; id=&quot;lines2&quot;&gt;
            &lt;path d=&quot;m 149.16986,180.50234 26.90507,1.70285&quot; id=&quot;path26&quot; /&gt;
            &lt;path d=&quot;m 192.42231,179.8212 58.57812,2.72456&quot; id=&quot;path27&quot; /&gt;
            &lt;path d=&quot;m 151.55385,197.87143 98.08429,1.36229&quot; id=&quot;path28&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;circle1&quot;&gt;
            &lt;path d=&quot;m 216.84634,154.57013 c -9.04033,2.26643 -11.0175,13.0598 0.60268,14.05192 8.33693,-2.77932 9.38648,-12.18918 -0.60268,-14.05192 z&quot; id=&quot;path29&quot; /&gt;
        &lt;/g&gt;
        &lt;g transform=&quot;translate(-98.084291,-32.694764)&quot; id=&quot;chart1&quot;&gt;
            &lt;path d=&quot;m 147.80758,166.87952 11.91996,-33.03533 12.94168,28.60792 20.43423,-45.29587 18.3908,33.03533 42.23074,-58.237547 -18.05023,9.876547 18.73137,-10.557688 -1.02171,20.434228 -19.75309,-7.83312&quot; id=&quot;path24&quot; /&gt;
        &lt;/g&gt;
        &lt;g id=&quot;circle2&quot;&gt;
            &lt;path d=&quot;m 247.02185,170.9168 c 9.59854,-2.57543 11.6978,-14.84031 -0.6399,-15.96768 -8.85171,3.15823 -9.96606,13.85098 0.6399,15.96768 z&quot; id=&quot;path29-0&quot; transform=&quot;translate(-98.084291,-32.694764)&quot; /&gt;
        &lt;/g&gt;
    &lt;/svg&gt;

&lt;!-- end snippet --&gt;



</details>



# 答案2
**得分**: 0

我们可以使用Snap中的虚线偏移技术,它可以动画化stroke-dashoffset。以下是示例,包括在Snap中使用原型,还可以允许链式动画。

您可以使用现有元素而不是下面的字符串示例,使用:

``` var element = Snap( someCSSSelector );```

您可以从[tutorial site][1](我的原始代码)运行下面的示例代码:

```javascript
var s = Snap("#svgout");

var svgString1 = '<path id="s3" d="M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z"  stroke="blue"/>';
var svgString2 = '<path id="s3" d="M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z"  stroke="red"/>';


function Drawing( svgString, transformString, timeBetweenDraws ) {
    this.fragment = Snap.parse( svgString );
    this.pathArray = this.fragment.selectAll('path');
    this.group = s.g().transform( transformString ).drag();
    this.timeBetweenDraws = timeBetweenDraws;
};

Drawing.prototype.init = function( svgString, transformString ) {
      this.group.clear();
      this.currentPathIndex = 0;

};

Drawing.prototype.endReached = function() {
    if( this.currentPathIndex >= this.pathArray.length ) {
        return true;
    };
};

Drawing.prototype.callOnFinished = function() {
}

Drawing.prototype.initDraw = function() {
    this.init();
    this.draw();
};

Drawing.prototype.quickDraw = function() {
    this.init();
    this.timeBetweenDraws = 0;
    this.draw();
};

Drawing.prototype.draw = function() {         // this is the main animation bit
    if( this.endReached() ) {
        if( this.callOnFinished ) {
            this.callOnFinished();
            return
        };
    };
    var myPath = this.pathArray[ this.currentPathIndex ] ;

    this.leng = myPath.getTotalLength();

    this.group.append( myPath );

     myPath.attr({
       fill: 'none',
       "stroke-dasharray": this.leng + " " + this.leng,
       "stroke-dashoffset": this.leng
     });

     this.currentPathIndex++;

     myPath.animate({"stroke-dashoffset": 0}, this.timeBetweenDraws, mina.easeout, this.draw.bind( this ) );

};



var myDrawing1 = new Drawing( svgString1, 't0, 0, s1.8', 800 );
var myDrawing2 = new Drawing( svgString2, 't69,50 s1.8', 3000 );
var myDrawing3 = new Drawing( svgString2, 't150,150 s1.8', 5000 );

myDrawing1.initDraw();
myDrawing1.callOnFinished = function() { myDrawing2.initDraw() };
myDrawing2.callOnFinished = function() { myDrawing3.initDraw() };
英文:

We can use the dash offset technique with Snap, which animates stroke-dashoffset. Example, including using prototypes with Snap is below, it will also allow chaining of animations.

You can use an existing element rather than the string example below, using

var element = Snap( someCSSSelector );

You can run below example code below from tutorial site (my original code)

var s = Snap(&quot;#svgout&quot;);
var svgString1 = &#39;&lt;path id=&quot;s3&quot; d=&quot;M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z&quot;  stroke=&quot;blue&quot;/&gt;&#39;;
var svgString2 = &#39;&lt;path id=&quot;s3&quot; d=&quot;M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z&quot;  stroke=&quot;red&quot;/&gt;&#39;;
function Drawing( svgString, transformString, timeBetweenDraws ) {
this.fragment = Snap.parse( svgString );
this.pathArray = this.fragment.selectAll(&#39;path&#39;);
this.group = s.g().transform( transformString ).drag();
this.timeBetweenDraws = timeBetweenDraws;
};
Drawing.prototype.init = function( svgString, transformString ) {
this.group.clear();
this.currentPathIndex = 0;
};
Drawing.prototype.endReached = function() {
if( this.currentPathIndex &gt;= this.pathArray.length ) {
return true;
};
};
Drawing.prototype.callOnFinished = function() {
}
Drawing.prototype.initDraw = function() {
this.init();
this.draw();
};
Drawing.prototype.quickDraw = function() {
this.init();
this.timeBetweenDraws = 0;
this.draw();
};
Drawing.prototype.draw = function() {         // this is the main animation bit
if( this.endReached() ) {
if( this.callOnFinished ) {
this.callOnFinished();
return
};
};
var myPath = this.pathArray[ this.currentPathIndex ] ;
this.leng = myPath.getTotalLength();
this.group.append( myPath );
myPath.attr({
fill: &#39;none&#39;,
&quot;stroke-dasharray&quot;: this.leng + &quot; &quot; + this.leng,
&quot;stroke-dashoffset&quot;: this.leng
});
this.currentPathIndex++;
myPath.animate({&quot;stroke-dashoffset&quot;: 0}, this.timeBetweenDraws, mina.easeout, this.draw.bind( this ) );
};
var myDrawing1 = new Drawing( svgString1, &#39;t0, 0, s1.8&#39;, 800 );
var myDrawing2 = new Drawing( svgString2, &#39;t69,50 s1.8&#39;, 3000 );
var myDrawing3 = new Drawing( svgString2, &#39;t150,150 s1.8&#39;, 5000 );
myDrawing1.initDraw();
myDrawing1.callOnFinished = function() { myDrawing2.initDraw() };
myDrawing2.callOnFinished = function() { myDrawing3.initDraw() };

huangapple
  • 本文由 发表于 2023年8月4日 04:59:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831569.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定