SVG getTotalLength() 不会 return 非缩放笔划的正确尺寸 - 获取 SVG 比例
SVG getTotalLength() won't return the right size for non-scaling-stroke - get SVG scale
我正在使用 javascript 获取路径长度并将其一半应用于 stroke-DashArray
。我的问题是我使用 vector-effect="non-scaling-stroke"
所以不管比例如何,它总是保持 stroke-width:2px;
非比例似乎影响笔划属性的每个部分,包括 DashArray 所以我需要获得比例然后缩放 svg path.getTotalLength();
.
有没有办法使用 javascript 获得 SVG 计算比例,用作路径长度的乘数?
我做了一个codepen.io来演示这个问题。只需调整视口大小即可查看笔划变化。
我认为你必须划分视图框大小/SVG 宽度
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button onclick="dashAni(myPath, 50, 3500)">start</button>
<svg id="mySVG" width="200" height="200" viewBox="0 0 500 500">
<path
vector-effect="non-scaling-stroke"
id="myPath" d="M 50,250 c 0 -100 150 -100 200 0
c 50 100 200 100 200 0
c -0 -100 -150 -100 -200 0
c -50 100 -200 100 -200 0
z"
stroke="#eee"
stroke-width="5" fill="none" />
</svg>
<script>
var dashAni = function(path, length, duration){
var dashPath = path.cloneNode(true);
mySVG.appendChild(dashPath);
var pathLen=path.getTotalLength()/2.5;
var aktPos=0
var sumSteps = duration / (1000/60) // 60 pics per second
var step=0;
var pathAnim;
dashPath.setAttribute('stroke-dasharray', length + ' ' + (pathLen - length));
dashPath.setAttribute('stroke', "red");
dashPath.setAttribute('stroke-dashoffset', aktPos);
var anim=function(){
aktPos = pathLen/sumSteps*step*-1;
//aktLen = easeInOutQuad(step/sumSteps)*len;
dashPath.setAttribute('stroke-dasharray', length + ' ' + pathLen);
dashPath.setAttribute('stroke-dashoffset', aktPos);
if (step <= (sumSteps)){
step++;
pathAnim = setTimeout(anim, 1000/60) //1000/60 pics/second
} else {
mySVG.removeChild(dashPath);
clearTimeout(pathAnim);
}
}
anim();
}
</script>
</body>
</html>
只想提请更多人注意上面 Sam 的 comment/answer,这对我有用!
path.getBoundingClientRect().width/path.getBBox().width
将 return 一个比例数字。
然后您可以将比例乘以路径长度 path.getTotalLength() * scale;
对于现在遇到这个问题的任何人来说,上面建议的缩放解决方案对我不起作用,我认为这是因为我没有按比例调整我的 svg 大小(它被设置为填充浏览器 window ).不过,我使用 boundingClientRect 和勾股定理为我的用例发现了一个简单的解决方案:
let boundingClient=el.getBoundingClientRect();
let pathLength=Math.sqrt(boundingClient.width**2 + boundingClient.height**2);
这对我来说非常准确,只要 window 调整大小时就需要重新计算。
我正在使用 javascript 获取路径长度并将其一半应用于 stroke-DashArray
。我的问题是我使用 vector-effect="non-scaling-stroke"
所以不管比例如何,它总是保持 stroke-width:2px;
非比例似乎影响笔划属性的每个部分,包括 DashArray 所以我需要获得比例然后缩放 svg path.getTotalLength();
.
有没有办法使用 javascript 获得 SVG 计算比例,用作路径长度的乘数?
我做了一个codepen.io来演示这个问题。只需调整视口大小即可查看笔划变化。
我认为你必须划分视图框大小/SVG 宽度
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button onclick="dashAni(myPath, 50, 3500)">start</button>
<svg id="mySVG" width="200" height="200" viewBox="0 0 500 500">
<path
vector-effect="non-scaling-stroke"
id="myPath" d="M 50,250 c 0 -100 150 -100 200 0
c 50 100 200 100 200 0
c -0 -100 -150 -100 -200 0
c -50 100 -200 100 -200 0
z"
stroke="#eee"
stroke-width="5" fill="none" />
</svg>
<script>
var dashAni = function(path, length, duration){
var dashPath = path.cloneNode(true);
mySVG.appendChild(dashPath);
var pathLen=path.getTotalLength()/2.5;
var aktPos=0
var sumSteps = duration / (1000/60) // 60 pics per second
var step=0;
var pathAnim;
dashPath.setAttribute('stroke-dasharray', length + ' ' + (pathLen - length));
dashPath.setAttribute('stroke', "red");
dashPath.setAttribute('stroke-dashoffset', aktPos);
var anim=function(){
aktPos = pathLen/sumSteps*step*-1;
//aktLen = easeInOutQuad(step/sumSteps)*len;
dashPath.setAttribute('stroke-dasharray', length + ' ' + pathLen);
dashPath.setAttribute('stroke-dashoffset', aktPos);
if (step <= (sumSteps)){
step++;
pathAnim = setTimeout(anim, 1000/60) //1000/60 pics/second
} else {
mySVG.removeChild(dashPath);
clearTimeout(pathAnim);
}
}
anim();
}
</script>
</body>
</html>
只想提请更多人注意上面 Sam 的 comment/answer,这对我有用!
path.getBoundingClientRect().width/path.getBBox().width
将 return 一个比例数字。
然后您可以将比例乘以路径长度 path.getTotalLength() * scale;
对于现在遇到这个问题的任何人来说,上面建议的缩放解决方案对我不起作用,我认为这是因为我没有按比例调整我的 svg 大小(它被设置为填充浏览器 window ).不过,我使用 boundingClientRect 和勾股定理为我的用例发现了一个简单的解决方案:
let boundingClient=el.getBoundingClientRect();
let pathLength=Math.sqrt(boundingClient.width**2 + boundingClient.height**2);
这对我来说非常准确,只要 window 调整大小时就需要重新计算。