如何使用JavaScript动画化SVG矩形的动画?

时间:2019-01-21 10:21:37

标签: javascript animation svg

对于我正在开发的游戏,

我希望能够绘制一个SVG矩形;使用百分比值(50%将绘制矩形笔画的一半)。
我需要用Javascript执行此操作,因为我会经常更新该值。

<svg id="rectangle-timer" style="width:100%;height:100%;">
    <rect width="100%" height="100%"/>
</svg>

我看到了不错的JS库,例如drawSVGVivus,但似乎它们可以使用路径,而不能使用矩形等基本形状。

任何人都可以帮忙吗?

谢谢。

2 个答案:

答案 0 :(得分:2)

大多数库使用path元素的原因是因为它们继承自SVGGeometryElement原型,这为您提供了方便的函数来计算路径长度。因此,如果我们将这个矩形换成这样的路径:

<path d="M 0 0 L 1 0 L 1 1 L 0 1 z" />

我们得到完全相同的输出,但是它的可控性要强得多。之后,我们只需调整样式中的strokeDasharray值即可扩展和删除一些笔触。对于此属性,我们只需要两个值:初始破折号和初始空白空间。因此,当进度为0时,我们希望第一个值为0,第二个为路径长度,而当我们接近1时,我们希望第二个值为0,第一个值增加为路径长度。

function update( amount ){
  
  const total = rect.getTotalLength();
  const filled = total * amount;
  const none = total - filled;
  
  rect.style.strokeDasharray = `${filled} ${none}`;
  
}

const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );

input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
    <path d="M 20 20 L 180 20 L 180 180 L 20 180 z" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>

<input id="input" type="range" min="0" max="1" step=".01" />

如果您坚持使用rect,则可以通过两次获取矩形的宽度和高度来获得其路径长度,如下所示:

function update( amount ){
  
  const total = rect.width.baseVal.value * 2 + rect.height.baseVal.value * 2;
  const filled = total * amount;
  const none = total - filled;
  
  rect.style.strokeDasharray = `${filled} ${none}`;
  
}

const rect = document.getElementById( 'rectangle' );
const input = document.getElementById( 'input' );

input.addEventListener( 'mousemove', event => update( input.value ));
update( input.value );
<svg width="200px" height="200px" viewBox="0 0 200 200">
    <rect x="20" y="20" width="160" height="160" id="rectangle" fill="none" stroke="black" stroke-width="10" />
</svg>

<input id="input" type="range" min="0" max="1" step=".01" />

但是,从长远来看,这将意味着通用性会降低,因此我建议切换到path

答案 1 :(得分:1)

这是我的解决方案:SVG具有preserveAspectRatio ="none" style="width:100%;height:100vh;"路径的总长度为2*window.innerWidth + 2*window.innerHeight; stroke-dasharraystroke-dashoffset都等于路径的总长度。

我正在使用输入type =“ range”为stroke-dashoffset设置动画。 为了保留笔触宽度并避免拉伸,我使用vector-effect="non-scaling-stroke"

我希望这是您所需要的。

function timer(){
let totalLength = 2*window.innerWidth + 2*window.innerHeight;
thePath.setAttributeNS(null, "style", `stroke-dashoffset:${totalLength * (1-range.value)}`)
}
timer()

range.addEventListener("input",timer);


setTimeout(function() {
		timer()
		addEventListener('resize', timer, false);
}, 15);
*{margin:0; padding:0;}
#thePath {
  stroke-dasharray: calc(2 * 100vw + 2* 100vh);
  stroke-dashoffset: calc(2 * 100vw + 2* 100vh);
}
#rectangle-timer{background:#dfdfdf}
[type="range"] {
  position: absolute;
  display: block;
  width: 200px;
  height: 20px;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
<svg id="rectangle-timer" viewBox="0 0 100 100" preserveAspectRatio ="none" style="width:100%;height:100vh;">

    <path id="thePath" d="M0,0L100,0 100,100 0,100 0,0" fill="none" stroke="skyBlue" stroke-width="25" vector-effect="non-scaling-stroke" />
</svg>

<input type="range" id="range" value=".5" min="0" max="1" step=".01"  />