我想在没有SMIL或库(jquery、Snap.svg、Velocity.js等)的情况下变形/动画svg路径数据,只使用纯javascript(如果可能,还可以选择使用css)。我之所以这么做,是因为Chrome不赞成SMIL,他们建议用css或"Web动画"制作动画——它们对Web动画意味着什么??-。例如,我想将下面代码中id为"rect1"的路径变形为id为"direct2"的路径:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>morph/animate svg path data WITHOUT SMIL or libraries (jquery, Snap.svg, Velocity.js etc.), just pure javascript</title>
</head>
<body>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="500px" height="500px"
viewBox="0 0 500 500"
>
<g id="layer1">
<path id="rect1" d="m25 7.3 61 12-6 57-71 6z" stroke="#f00" stroke-miterlimit="10" stroke-width="2" fill="none"/>
</g>
<g id="layer2">
<path id="rect2" d="m9.3 34 59-27 26 41-54 42z" stroke="#f00" stroke-miterlimit="10" stroke-width="2" fill="none"/>
</g>
</svg>
<script>
// code for animating/morphing path with id "rect1" to path with id "rect 2"
</script>
</body>
</html>
要仅使用JavaScript来动画化路径数据,我建议缓存两条路径的原始路径数据。然后使用计时器逐步完成动画过程。在每个步骤中,计算从开始路径数据平滑移动到结束路径数据的当前路径数据。
以下代码等待1秒,然后运行2秒的动画。。。
<script>
(function() {
var path1;
var path2;
var startPoints;
var endPoints;
var currentStep = 0;
var maximumSteps = 100;
var timeBeforeFirstStep = 1000;
var timeBetweenSteps = 20;
function animatePath() {
if (currentStep < maximumSteps) {
currentStep = currentStep + 1;
for (var i = 0; i < path1.pathSegList.numberOfItems; i++) {
var item = path1.pathSegList.getItem(i);
if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
if (startPoints[i] && endPoints[i]) {
item.x = startPoints[i].x + (endPoints[i].x - startPoints[i].x) * (currentStep / maximumSteps);
item.y = startPoints[i].y + (endPoints[i].y - startPoints[i].y) * (currentStep / maximumSteps);
}
}
}
setTimeout(animatePath, timeBetweenSteps);
}
}
function window_load() {
path1 = document.getElementById("rect1");
path2 = document.getElementById("rect2");
startPoints = [];
for (var i = 0; i < path1.pathSegList.numberOfItems; i++) {
var item = path1.pathSegList.getItem(i);
if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
startPoints.push({"x": item.x, "y": item.y});
}
else {
startPoints.push(null);
}
}
endPoints = [];
for (var i = 0; i < path2.pathSegList.numberOfItems; i++) {
var item = path2.pathSegList.getItem(i);
if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
endPoints.push({"x": item.x, "y": item.y});
}
else {
endPoints.push(null);
}
}
setTimeout(animatePath, timeBeforeFirstStep);
}
window.addEventListener("load", window_load);
}());
</script>