Kun*_*jan 4 html css jquery svg css-animations
我想创建一个 CSS 动画,其中箭头在滚动时沿着 SVG 蛇形路径移动,并在每个新部分上更改图标。
我看了几个例子:
但我无法通过我的页面设计重新创建预期的行为。
到目前为止,这是我的代码:
window.addEventListener('scroll', function() {
let l = Path_440.getTotalLength();
let dasharray = l;
let dashoffset = l;
e = document.documentElement;
theFill.setAttributeNS(null, "stroke-dasharray", l);
theFill.setAttributeNS(null, "stroke-dashoffset", l);
dashoffset = l - window.scrollY * l / (e.scrollHeight - e.clientHeight);
//console.log('window.scrollY', window.scrollY, 'scrollTop', e.scrollTop, 'scrollHeight', e.scrollHeight, 'clientHeight', e.clientHeight, 'dash-offset', dashoffset);
theFill.setAttributeNS(null, "stroke-dashoffset", dashoffset);
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width="246" height="2990" viewBox="0 0 246 2990" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="Path_440" d="M210.001 1.5C210.001 1.5 41.0015 324.5 6.50082 617.5C-27.004 902.042 182.501 1032.5 240.001 1313C275.095 1484.2 29.8527 1661 41.0008 1914.5C50.4751 2129.94 230.431 2237.5 235.001 2431.5C240.42 2661.59 41.0008 2988 41.0008 2988" stroke="#F39029" stroke-width="4" stroke-dasharray="20 10"/>
</defs>
<use xlink:href="#Path_440" stroke="#000" stroke-width="4" stroke-dasharray="1"/>
<use id="theFill" xlink:href="#Path_440" stroke="#000" stroke-width="1"/>
</svg>
Run Code Online (Sandbox Code Playgroud)
现代策略是使用CSS 运动路径(又名CSS 中的offset-path
and path()
)。通过计算scrollProgress
SVG 路径的 ,您可以使用它来计算offset-distance
图标的百分比。只需确保图标绝对位于 SVG 的位置即可(0,0)
。
在 SVG 路径跨越整个页面的简单情况下,scrollProgress
只是window.scrollY / (docElt.scrollHeight - docElt.clientHeight)
. 但是,如果 SVG 路径不跨越整个滚动容器,则需要使用getBoundingClientRect()
来计算scrollProgress
并将其限制在 0 和 1 之间。下面的代码演示涵盖了这种更复杂的情况。
要在用户滚动时填充路径,请结合getTotalLength()
使用路径元素的方法来scrollProgress
计算用户沿路径的距离(以像素为单位) ( drawLength
) 以及他们还剩多少像素 ( 以像素为单位) ( rest
)。然后,您可以使用一个常见技巧将stroke-dasharray
其设置为${drawLength}px ${rest}px
。
最后,您还可以使用scrollProgress
CSS 来确定要显示的图标background-image
。用于offset-rotate: 0rad;
防止图标沿路径方向旋转。
pathIcon.style.offsetPath = `path('${Path_440.getAttribute("d")}')`;
const pathLength = Path_440.getTotalLength();
function clamp(min, val, max) {
return Math.min(Math.max(min, val), max);
}
function updatePath() {
const docElt = document.documentElement;
const pathBox = theFill.getBoundingClientRect();
// calculates scroll progress based on viewport progress
const scrollProgress =
clamp(0, -pathBox.y / (pathBox.height - docElt.clientHeight), 1);
pathIcon.style.offsetDistance = `${scrollProgress * 100}%`;
// These lines fill in the dashes as you scroll down.
const drawLength = pathLength * scrollProgress;
const rest = pathLength - drawLength;
theFill.style.strokeDasharray = `${drawLength}px ${rest}px`;
// You can update the icon/SVG here using your own logic.
// For the example, I'm changing the CSS background-image.
pathIcon.style.backgroundImage = `url(${getIconSrc(scrollProgress)})`;
}
function getIconSrc(scrollPercent) {
if (scrollPercent < 0.2) {
return 'https://via.placeholder.com/25x25/FF0000?text=red';
} else if (scrollPercent < 0.4) {
return 'https://via.placeholder.com/25x25/FFA500?text=orange';
} else if (scrollPercent < 0.6) {
return 'https://via.placeholder.com/25x25/FFFF00?text=yellow';
} else if (scrollPercent < 0.8) {
return 'https://via.placeholder.com/25x25/00FF00?text=green';
} else if (scrollPercent < 1) {
return 'https://via.placeholder.com/25x25/0000FF?text=blue';
} else if (scrollPercent === 1) {
// A scrollPercent of 1 indicates that we have reached the end of the path.
return 'https://via.placeholder.com/25x25/A020F0?text=purple';
}
}
updatePath();
window.addEventListener("scroll", () => updatePath());
Run Code Online (Sandbox Code Playgroud)
#pathIcon {
position: absolute;
inset: 0;
width: 25px;
height: 25px;
background-size: 25px;
offset-rotate: 0rad;
}
Run Code Online (Sandbox Code Playgroud)
<div style="height: 175px;"></div>
<div style="position: relative;">
<svg width="246" height="2990" viewBox="0 0 246 2990" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="Path_440"
d="M210.001 1.5C210.001 1.5 41.0015 324.5 6.50082 617.5C-27.004 902.042 182.501 1032.5 240.001 1313C275.095 1484.2 29.8527 1661 41.0008 1914.5C50.4751 2129.94 230.431 2237.5 235.001 2431.5C240.42 2661.59 41.0008 2988 41.0008 2988"
stroke-width="4" stroke="#F39029" />
</defs>
<use href="#Path_440" stroke-dasharray="20 10" />
<use id="theFill" href="#Path_440" />
</svg>
<div id="pathIcon"></div>
</div>
Run Code Online (Sandbox Code Playgroud)
希望在不久的将来,我们将获得滚动驱动的动画,甚至更好地支持浏览器中的 CSS 运动路径,这将使仅使用 CSS 沿路径制作元素动画变得更加简单。例如,如果您使用的是启用了该experimental-web-platform-features
标志的 Chrome Canary 115+,则以下 CSS 的效果即使不是更好,也同样有效。无需 JS:
#arrow {
offset-path: url(#Path_440);
offset-anchor: left;
animation: offsetDistance linear;
animation-timeline: scroll();
}
@keyframes offsetDistance {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
Run Code Online (Sandbox Code Playgroud)
<svg width="246" height="2990" viewBox="0 0 246 2990" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="Path_440"
d="M210.001 1.5C210.001 1.5 41.0015 324.5 6.50082 617.5C-27.004 902.042 182.501 1032.5 240.001 1313C275.095 1484.2 29.8527 1661 41.0008 1914.5C50.4751 2129.94 230.431 2237.5 235.001 2431.5C240.42 2661.59 41.0008 2988 41.0008 2988"
stroke-width="4" stroke="#F39029" />
</defs>
<use xlink:href="#Path_440" stroke-dasharray="20 10" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" id="arrow" style="position: absolute; left: 0; top: 0;" fill-rule="evenodd" clip-rule="evenodd">
<path d="M21.883 12l-7.527 6.235.644.765 9-7.521-9-7.479-.645.764 7.529 6.236h-21.884v1h21.883z" />
</svg>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
628 次 |
最近记录: |