图像序列在它出现之前开始动画
Posted
技术标签:
【中文标题】图像序列在它出现之前开始动画【英文标题】:Image sequence starts animating before it's in view 【发布时间】:2021-08-29 22:03:06 【问题描述】:我正在尝试复制苹果的图像排序动画 - https://www.apple.com/airpods-pro/。我设法找到了一些示例,它们都运行良好,但它们都在页面顶部触发,我希望我的在页面中间触发。我已经尝试将触发事件附加到#graphHolder 容器,但只要您在页面顶部滚动,它仍然会开始循环浏览图像。谁能指出我哪里出错了?这是一个 jsfiddle - https://jsfiddle.net/mvyw2bc3/2/
const html = document.documentElement;
const canvas = document.getElementById("hero-lightpass");
const context = canvas.getContext("2d");
const frameCount = 132;
const currentFrame = index => ( `https://res.cloudinary.com/icebreakernz/image/upload/v1623273037/globalcampaign/plastic-free/sequence-test/IB-Graph_Animation$index.toString().padStart(4, '0').jpg`
)
const preloadImages = () =>
for (let i = 1; i < frameCount; i++)
const img = new Image();
img.src = currentFrame(i);
;
const img = new Image()
img.src = currentFrame(1);
canvas.width=1920;
canvas.height=1080;
img.onload=function()
context.drawImage(img, 0, 0);
const updateImage = index =>
img.src = currentFrame(index);
context.drawImage(img, 0, 0);
window.addEventListener('scroll', () =>
const scrollTop = html.scrollTop;
const maxScrollTop = html.scrollHeight - window.innerHeight;
const scrollFraction = scrollTop / maxScrollTop;
const frameIndex = Math.min(
frameCount - 1,
Math.ceil(scrollFraction * frameCount)
);
requestAnimationFrame(() => updateImage(frameIndex + 1))
);
preloadImages()
【问题讨论】:
【参考方案1】:对于遇到同样问题的任何人,我最终选择了ScrollTrigger,这使它变得超级简单。在这里查看我的小提琴,看看它应该如何工作 - https://jsfiddle.net/jdrebugL/
const canvas = document.getElementById("hero-lightpass");
const context = canvas.getContext("2d");
canvas.width = 1920;
canvas.height = 1080;
const frameCount = 132;
const currentFrame = index => ( `https://res.cloudinary.com/icebreakernz/image/upload/v1623273037/globalcampaign/plastic-free/sequence-test/IB-Graph_Animation$(index + 1).toString().padStart(4, '0').jpg`
);
const images = []
const airpods =
frame: 0
;
for (let i = 0; i < frameCount; i++)
const img = new Image();
img.src = currentFrame(i);
images.push(img);
gsap.to(airpods,
frame: frameCount - 1,
snap: "frame",
scrollTrigger:
scrub: 1,
trigger: "#hero-lightpass",
start: "top top",
pin: true
,
onUpdate: render // use animation onUpdate instead of scrollTrigger's onUpdate
);
images[0].onload = render;
function render()
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(images[airpods.frame], 0, 0);
【讨论】:
【参考方案2】:难道你不能做一个交点观察者,让它在一个被推到图像底部的 div 上触发(可能是绝对位置和底部零,或者你知道什么),然后触发内的任何回调函数观察者?我不确定这是否有任何帮助,但这是我制作的一个函数,可让您在元素相交时调用回调函数
export const elementObserver = (callback, options) =>
if (typeof options.element != "undefined")
return new IntersectionObserver(
(entries, observer) =>
entries.forEach(entry =>
let target = entry.target;
if (entry.isIntersecting)
callback(options);
);
,
threshold: 0.5
).observe(options.element);
您需要在 javascript 映射中传递所有回调函数变量,并且映射必须有一个名为“元素”的键才能工作(元素是要监视交叉点的元素)......也在它的当前状态它是用 es6 编写的,但您可以轻松翻译它。 哦,也许可以使用阈值,但将其设置为 1 以进一步延迟动作
【讨论】:
感谢您的回复!最后我最终选择了 gsaps scrollTrigger。是一个非常优雅的解决方案。 太棒了!很高兴你找到了一个好的解决方案。您提到的插件听起来不错,但是如果您要走这条路,您可能应该考虑摇树,因为该插件可能比您需要的要多得多,而且您不希望所有这些额外的 js 拖慢您的速度。跨度> 是的,当然,谢天谢地,当您滚动浏览页面的其余部分时,我的设计中有很多动画元素,因此非常适合我的需要。我最初使用的是scrollmagic,但已经将其替换为支持此功能,否则如果它是一次性的,我会按照您所说的那样使用精简版。以上是关于图像序列在它出现之前开始动画的主要内容,如果未能解决你的问题,请参考以下文章