我是新手,requestAnimationFrame并試圖了解如何開發使用CSS Keyframe Animation.
詳細說明,我可以執行以下操作CSS
顯示代碼片段
let curve = document.querySelector('#curve')
let dot = document.querySelector('#dot');
let d = curve.getAttribute('d');
dot.style.setProperty('--mp', '"' d '"')
#dot {
offset-path: path(var(--mp));
animation: move 3000ms infinite alternate ease-in-out;
}
@keyframes move {
100% {
offset-distance: 100%;
}
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
<g>
<circle id="dot" r="10" cy="0.5" cx="0.5" style="fill: #dd1819; "></circle>
</g>
<path id="curve" d="M 29.928125,119.32884 C 59.868756,78.85387 99.789596,30.283895 138.66049,30.104515 c 80.46172,-0.37133 90.87185,137.794285 140.7729,129.699295 40.35037,-6.54568 49.90105,-80.94994 86.53937,-78.86548 33.24073,1.89117 22.2547,70.77048 73.14399,70.77048 39.92084,0 58.65264,-56.66496 99.80211,-56.66496 49.90105,0 69.86147,80.94995 99.8021,48.56997" style="fill: none; stroke:black; stroke-width: 1;" />
</svg>
animation-direction: alternate;確保它來回播放并animation-iteration-count: infinite;確保它在無限回圈中運行。
我試圖了解是否可以在rAF. 這是我到目前為止嘗試過的
let u = 0;
let time = 3000;
let start = performance.now();
let curve = document.querySelector('#curve')
let totalLength = curve.getTotalLength();
let dot = document.querySelector('#dot');
const temp = [];
const move1 = () => {
let p = curve.getPointAtLength(u * totalLength);
dot.setAttribute("transform", `translate(${p.x}, ${p.y})`);
if (u < 1) {
u = (performance.now() - start) / time
temp.push(p);
requestAnimationFrame(move1)
}
};
move1();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
<g>
<circle id="dot" r="10" cy="0.5" cx="0.5" style="fill: #dd1819; "></circle>
</g>
<path id="curve" d="M 29.928125,119.32884 C 59.868756,78.85387 99.789596,30.283895 138.66049,30.104515 c 80.46172,-0.37133 90.87185,137.794285 140.7729,129.699295 40.35037,-6.54568 49.90105,-80.94994 86.53937,-78.86548 33.24073,1.89117 22.2547,70.77048 73.14399,70.77048 39.92084,0 58.65264,-56.66496 99.80211,-56.66496 49.90105,0 69.86147,80.94995 99.8021,48.56997" style="fill: none; stroke:black; stroke-width: 1;" />
</svg>
上面的rAF影片大概相當于
#dot {
offset-path: path(var(--mp));
animation: move 3000ms 1 forwards linear;
}
有什么辦法可以實作CSS
uj5u.com熱心網友回復:
關于使用的幾件事requestAnimationFrame(…):
最佳做法是使用由 提供給回呼的時間戳引數
requestAnimationFrame。無需performance.now()在函式內部呼叫。但是如果你這樣做了,一定要在影片之前做,否則影片將缺乏任何潛在的幀速率下降在速度較慢的 PC 尤其是手機上。回呼方法被傳遞一個引數,一個 DOMHighResTimeStamp 類似于回傳的
performance.now()那個,它指示當前時間(基于從時間開始的毫秒數)。獲取給定的時間戳并從中獲取您需要的內容。(這通常使用外部變數作為配置來完成。)我在影片的哪個迭代中?這次迭代進展到什么程度了?
這種方法是有效的,但不是最好的:最好的做法是只保存影片的最后一次、最后一個 requestID(由回傳
requestAnimationFrame(…))和最后一個狀態(iterationWithFraction)。然后在每一步中比較上一次和現在的時間,并將標準化的進度添加到狀態中。然后相應地更新影片。
總是比較第一個時間戳start會導致非常混亂的錯誤。(想象一下time設定為2000中間影片。)如果要結束影片,請查看
cancelAnimationFrame(requestID).
let time = 3000;
let start = performance.now();
let curve = document.querySelector('#curve')
let totalLength = curve.getTotalLength();
let dot = document.querySelector('#dot');
let d = curve.getAttribute('d');
const step = (timestamp) => {
// get current time normalized with "time" (2s passed = 0.6666, 3s passed = 1, 4s passed = 1.33333, ...)
const iterationWithFraction = (timestamp - start) / time;
// get current iteration as an integer
const iteration = Math.floor(iterationWithFraction);
// get current moment in iteration
let fraction = iterationWithFraction % 1;
// if iteration odd: invert fraction to get the desired alternation
if (iteration % 2 == 1) fraction = 1 - fraction;
// if you want an easing effect, you can do something like this now
fraction = fraction<.5 ? 2*fraction**2 : -1 (4-2*fraction)*fraction;
// do your animation
const point = curve.getPointAtLength(fraction * totalLength);
dot.setAttribute("transform", `translate(${point.x}, ${point.y})`);
// get next AF as the last thing of the function
requestAnimationFrame(step);
};
step(performance.now());
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
<g>
<circle id="dot" r="10" cy="0.5" cx="0.5" style="fill: #dd1819; "></circle>
</g>
<path id="curve" d="M 29.928125,119.32884 C 59.868756,78.85387 99.789596,30.283895 138.66049,30.104515 c 80.46172,-0.37133 90.87185,137.794285 140.7729,129.699295 40.35037,-6.54568 49.90105,-80.94994 86.53937,-78.86548 33.24073,1.89117 22.2547,70.77048 73.14399,70.77048 39.92084,0 58.65264,-56.66496 99.80211,-56.66496 49.90105,0 69.86147,80.94995 99.8021,48.56997" style="fill: none; stroke:black; stroke-width: 1;" />
</svg>
uj5u.com熱心網友回復:
不需要 CSS 或 JavaScript(我確實喜歡 JavaScript 和 Web 組件)
要添加緩動,請參閱:
在 SVG 中緩和 animateMotion
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/keySplines
<svg viewBox="0 0 640 720" xmlns="http://www.w3.org/2000/svg">
<path id="PATH" stroke="black" fill="none" d="m30 119c30-40 70-89 109-89 81 0 91 138 141 130 40-7 50-81 87-79 33 2 22 71 73 71 40 0 59-57 100-57 50 0 70 81 100 49" />
<circle r="10" fill="red">
<animateMotion dur="5s" keyPoints="0;1;0" keyTimes="0;.7;1"
calcMode="linear" repeatCount="indefinite">
<mpath href="#PATH" />
</animateMotion>
</circle>
</svg>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/492504.html
標籤:javascript svg CSS动画 请求动画帧
上一篇:是否可以制作帶有進度環的SVG影片,但左右沖刺設定都在移動?
下一篇:XPath到SVG元素?
