如何为 svg 路径的渐进式绘图设置动画? [英] How can I animate a progressive drawing of svg path?

查看:23
本文介绍了如何为 svg 路径的渐进式绘图设置动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想仅使用带有 svg/canvas 和 js 最大值的 css 来为一条线的渐进绘制动画.可以在 here

I want to animate a progressive drawing of a line using only css with svg/canvas and js maximum. An idea of the line I want to draw can be found here

<svg width="640" height="480" xmlns="http://www.w3.org/2000/svg">
 <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
 <g>
  <title>Layer 1</title>
  <path d="m33,104c1,0 2.1306,-0.8037 23,3c9.07012,1.65314 10,2 24,2c7,0 29,0 33,0c8,0 9,0 11,0c2,0 8,0 11,0c9,0 17,0 18,0c10,0 12,0 20,0c1,0 6,0 7,0c2,0 3.07613,0.38268 4,0c2.61313,-1.08239 2,-3 2,-6c0,-1 0,-2 0,-3c0,-1 0,-2 0,-3c0,-1 0,-2 0,-3c0,-1 0.30745,-3.186 -1,-5c-0.8269,-1.14727 -0.09789,-2.82443 -2,-4c-0.85065,-0.52573 -2.82443,-0.09789 -4,-2c-0.52573,-0.85065 -2.58578,-0.58578 -4,-2c-0.70711,-0.70711 -1.81265,-1.20681 -4,-3c-2.78833,-2.28588 -3.64749,-2.97251 -8,-4c-2.91975,-0.68926 -4.82375,-2.48626 -7,-3c-2.91975,-0.68926 -5.15224,-0.23463 -7,-1c-1.30656,-0.5412 -4.38687,-1.91761 -7,-3c-1.84776,-0.76537 -5.03609,0.37821 -7,0c-5.28799,-1.01837 -8,-3 -9,-3c-2,0 -5.0535,-0.54049 -7,-1c-2.17625,-0.51374 -4.15224,-0.23463 -6,-1c-1.30656,-0.54119 -3,-1 -4,-1c-2,0 -5,-1 -6,-1c-1,0 -3,-2 -6,-2c-2,0 -5,-2 -6,-2c-2,0 -2.02583,-0.67963 -4,-1c-3.12144,-0.50654 -4.15224,-0.23463 -6,-1c-1.30656,-0.54119 -2,-1 -3,-1c-2,0 -3,0 -5,0c-1,0 -2,0 -3,0c-1,0 -2,0 -3,0c-1,0 -2,0 -3,0c-2,0 -3.85273,0.1731 -5,1c-1.81399,1.30745 -5.18601,1.69255 -7,3c-1.14727,0.8269 -1.82375,2.48626 -4,3c-0.97325,0.22975 -1.69344,1.45881 -3,2c-0.92388,0.38268 -1.45951,1.0535 -1,3c0.51374,2.17625 3.07844,2.78985 6,4c2.06586,0.85571 3.38688,1.91761 6,3c1.84776,0.76537 5.2987,-1.05146 7,0c1.90211,1.17557 3.82375,2.48626 6,3c0.97325,0.22975 3.29289,0.29289 4,1c0.70711,0.70711 4,2 9,4c5,2 8,4 11,4c2,0 5,0 7,0c3,0 5,0 7,0c2,0 4,0 7,0c2,0 4,0 8,0c3,0 7,0 10,0c4,0 7,0 12,0c3,0 5,0 6,0c2,0 3,0 5,0c1,0 1.09789,-0.82443 3,-2c0.85065,-0.52573 3.07613,0.38268 4,0c1.30656,-0.5412 0.71022,-2.04291 1,-3c1.04483,-3.45084 2.84723,-5.04132 4,-9c0.88414,-3.03616 1.85194,-5.22836 3,-8c0.5412,-1.30656 1.5405,-2.0535 2,-4c0.51375,-2.17625 2.71413,-4.21167 5,-7c2.68979,-3.28101 4,-6 5,-7c1,-1 2,-2 2,-4c0,-1 0.70711,-2.29289 0,-3c-0.70711,-0.70711 -2.07613,0.38268 -3,0c-1.30656,-0.54119 -2,-1 -4,-1c-3,0 -6.87856,-2.49346 -10,-3c-2.96126,-0.48055 -6.71201,-0.98162 -12,-2c-2.94586,-0.56732 -5,-1 -9,-1c-3,0 -6,-1 -8,-1c-2,0 -5,-3 -7,-3c-2,0 -5.38687,-0.91761 -8,-2c-0.92388,-0.38268 -3.0535,-0.54049 -5,-1c-2.17625,-0.51374 -4.58578,0.41421 -6,-1c-0.70711,-0.70711 -1,-1 -2,-1c-1,0 -2,0 -3,0c-1,0 -2,0 -4,0c-1,0 -2,0 -3,0c-1,0 -2,0 -4,0c-1,0 -2,0 -3,0c-2,0 -3,0 -5,0c-1,0 -2,0 -3,0c-1,0 -3,0 -4,0c-3,0 -5,0 -7,0c-2,0 -4,0 -6,0c-2,0 -3,0 -5,0c-1,0 -2,0 -3,0c-2,0 -4,0 -5,0c-1,0 -2,0 -4,0c-1,0 -2,0 -3,1l-1,0" id="svg_1" stroke-width="5" stroke="#000000" fill="none"/>
 </g>
</svg>

推荐答案

本回答中列出了三种技巧:

There are three techniques listed in this answer:

有一个全 SVG 解决方案,包括逐步修改形状的 stroke-dasharray 以绘制越来越长的破折号",然后是一个巨大的间隙.

There is an all-SVG solution that involves progressively modifying the stroke-dasharray for the shape to draw a longer and longer 'dash' followed by an enormous gap.

相关代码:

var distancePerPoint = 1;
var drawFPS          = 60;

var orig = document.querySelector('path'), length, timer;
orig.addEventListener('mouseover',startDrawingPath,false);
orig.addEventListener('mouseout', stopDrawingPath, false);

function startDrawingPath(){
  length = 0;
  orig.style.stroke = '#f60';
  timer = setInterval(increaseLength,1000/drawFPS);
}

function increaseLength(){
  var pathLength = orig.getTotalLength();
  length += distancePerPoint;
  orig.style.strokeDasharray = [length,pathLength].join(' ');
  if (length >= pathLength) clearInterval(timer);
}

function stopDrawingPath(){
  clearInterval(timer);
  orig.style.stroke = '';
  orig.style.strokeDasharray = '';
}

<小时>

或者,您仍然可以使用所有 SVG 并选择一次一条命令构建 SVG 路径:


Alternatively, you can still use all SVG and choose to build the SVG path one command at a time:

相关代码:

// Assumes 'orig' and dup' are SVG paths
function addNextPathSegment(){
  var nextIndex   = dup.pathSegList.numberOfItems;
  if (nextIndex<orig.pathSegList.numberOfItems){
    var nextSegment = orig.pathSegList.getItem(nextIndex);
    var segmentDup  = cloneSVGPathSeg( dup, nextSegment );
    dup.pathSegList.appendItem( segmentDup );
  }
}

function cloneSVGPathSeg( path, seg ){
  switch(seg.pathSegTypeAsLetter){
    case 'M': return path.createSVGPathSegMovetoAbs(seg.x,seg.y);                                                     break;
    case 'm': return path.createSVGPathSegMovetoRel(seg.x,seg.y);                                                     break;
    case 'L': return path.createSVGPathSegLinetoAbs(seg.x,seg.y);                                                     break;
    case 'l': return path.createSVGPathSegLinetoRel(seg.x,seg.y);                                                     break;
    case 'H': return path.createSVGPathSegLinetoHorizontalAbs(seg.x);                                                 break;
    case 'h': return path.createSVGPathSegLinetoHorizontalRel(seg.x);                                                 break;
    case 'V': return path.createSVGPathSegLinetoVerticalAbs(seg.y);                                                   break;
    case 'v': return path.createSVGPathSegLinetoVerticalRel(seg.y);                                                   break;
    case 'C': return path.createSVGPathSegCurvetoCubicAbs(seg.x,seg.y,seg.x1,seg.y1,seg.x2,seg.y2);                   break;
    case 'c': return path.createSVGPathSegCurvetoCubicRel(seg.x,seg.y,seg.x1,seg.y1,seg.x2,seg.y2);                   break;
    case 'S': return path.createSVGPathSegCurvetoCubicSmoothAbs(seg.x,seg.y,seg.x2,seg.y2);                           break;
    case 's': return path.createSVGPathSegCurvetoCubicSmoothRel(seg.x,seg.y,seg.x2,seg.y2);                           break;
    case 'Q': return path.createSVGPathSegCurvetoQuadraticAbs(seg.x,seg.y,seg.x1,seg.y1);                             break;
    case 'q': return path.createSVGPathSegCurvetoQuadraticRel(seg.x,seg.y,seg.x1,seg.y1);                             break;
    case 'T': return path.createSVGPathSegCurvetoQuadraticSmoothAbs(seg.x,seg.y);                                     break;
    case 't': return path.createSVGPathSegCurvetoQuadraticSmoothRel(seg.x,seg.y);                                     break;
    case 'A': return path.createSVGPathSegArcAbs(seg.x,seg.y,seg.r1,seg.r2,seg.angle,seg.largeArcFlag,seg.sweepFlag); break;
    case 'a': return path.createSVGPathSegArcRel(seg.x,seg.y,seg.r1,seg.r2,seg.angle,seg.largeArcFlag,seg.sweepFlag); break;
    case 'z':
    case 'Z': return path.createSVGPathSegClosePath();                                                                break;
  }
}

<小时>

最后,您可以选择通过定期对 SVG 路径进行采样并绘制到画布来绘制到 HTML5 画布的路径.(请注意,无需显示 SVG 路径即可实现此操作;您可以完全在 JavaScript 中构建 SVG 路径元素并对其进行采样):


Finally, you may choose to draw your path to an HTML5 canvas by sampling the SVG path periodically and drawing to the canvas. (Note that the SVG path does not need to be displayed for this to happen; you can build an SVG path element entirely in JavaScript and sample it):

相关代码:

function startDrawingPath(){
  points = [];
  timer = setInterval(buildPath,1000/drawFPS);
}

// Assumes that 'orig' is an SVG path
function buildPath(){
  var nextPoint = points.length * distancePerPoint;
  var pathLength = orig.getTotalLength();
  if (nextPoint <= pathLength){
    points.push(orig.getPointAtLength(nextPoint));
    redrawCanvas();
  } else stopDrawingPath();
}

function redrawCanvas(){
  clearCanvas();
  ctx.beginPath();
  ctx.moveTo(points[0].x,points[0].y);
  for (var i=1;i<points.length;i++) ctx.lineTo(points[i].x,points[i].y);
  ctx.stroke();
}

这篇关于如何为 svg 路径的渐进式绘图设置动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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