我制作了一个包装,我在他们的Airpods Pro页面上制作了和苹果一样的动画效果。这基本上是一个视频,当我滚动视频播放一点一点。视频的位置是固定的,所以文本很好地滚动在它上面。但是,只有在特定划分的偏移量(文本显示)之间,文本才是可见的。
那部分运作得很好。现在我希望当用户滚动到视频的末尾,这样动画就完成了,视频效果包装器从一个固定的位置转到一个相对的位置。因此,该网站将滚动它的内容后,通常视频动画。
这就是我已经尝试过的一个例子:
//If video-animation ended: Make position of video-wrapper relative to continue scrolling
if ($(window).scrollTop() >= $("#video-effect-wrapper").height()) {
$(video).css("position", "relative");
$("#video-effect-wrapper .text").css("display", "none");
}
这类作品..。但一切都很顺利。它也需要有可能向后滚动网页。
试图修复此问题时遇到的问题:
发布于 2020-01-26 23:12:11
当在Airpods Pro页面上进行一些反向工程时,我们注意到动画并不使用video
,而是使用canvas
。执行情况如下:
HTMLImageElement
的形式创建图像数组scroll
DOM事件作出反应,并使用requestAnimationFrame
请求一个与最近的图像对应的动画帧ctx.drawImage
(ctx
是canvas
元素的2d
上下文)显示图像。requestAnimationFrame
函数将帮助您实现更平滑的效果,因为帧将被延迟并与目标屏幕的“每秒帧”速率同步。
有关如何在滚动事件上正确显示框架的更多信息,可以阅读以下内容:事件
尽管如此,关于你的主要问题,我有一个工作解决办法,包括:
video
元素相同。它的目的是避免视频在设置为absolute
位置时与HTML的其余部分重叠。scroll
事件回调中,当占位符到达视图端口顶部时,将视频的位置设置为absolute
,并设置正确的top
值其思想是,视频始终保持在流之外,并发生在占位符在正确的时刻滚动到底部。
下面是JavaScript:
//Get video element
let video = $("#video-effect-wrapper video").get(0);
video.pause();
let topOffset;
$(window).resize(onResize);
function computeVideoSizeAndPosition() {
const { width, height } = video.getBoundingClientRect();
const videoPlaceholder = $("#video-placeholder");
videoPlaceholder.css("width", width);
videoPlaceholder.css("height", height);
topOffset = videoPlaceholder.position().top;
}
function updateVideoPosition() {
if ($(window).scrollTop() >= topOffset) {
$(video).css("position", "absolute");
$(video).css("left", "0px");
$(video).css("top", topOffset);
} else {
$(video).css("position", "fixed");
$(video).css("left", "0px");
$(video).css("top", "0px");
}
}
function onResize() {
computeVideoSizeAndPosition();
updateVideoPosition();
}
onResize();
//Initialize video effect wrapper
$(document).ready(function () {
//If .first text-element is set, place it in bottom of
//text-display
if ($("#video-effect-wrapper .text.first").length) {
//Get text-display position properties
let textDisplay = $("#video-effect-wrapper #text-display");
let textDisplayPosition = textDisplay.offset().top;
let textDisplayHeight = textDisplay.height();
let textDisplayBottom = textDisplayPosition + textDisplayHeight;
//Get .text.first positions
let firstText = $("#video-effect-wrapper .text.first");
let firstTextHeight = firstText.height();
let startPositionOfFirstText = textDisplayBottom - firstTextHeight + 50;
//Set start position of .text.first
firstText.css("margin-top", startPositionOfFirstText);
}
});
//Code to launch video-effect when user scrolls
$(document).scroll(function () {
//Calculate amount of pixels there is scrolled in the video-effect-wrapper
let n = $(window).scrollTop() - $("#video-effect-wrapper").offset().top + 408;
n = n < 0 ? 0 : n;
//If .text.first is set, we need to calculate one less text-box
let x = $("#video-effect-wrapper .text.first").length == 0 ? 0 : 1;
//Calculate how many percent of the video-effect-wrapper is currenlty scrolled
let percentage = n / ($(".text").eq(1).outerHeight(true) * ($("#video-effect-wrapper .text").length - x)) * 100;
//console.log(percentage);
//console.log(percentage);
//Get duration of video
let duration = video.duration;
//Calculate to which second in video we need to go
let skipTo = duration / 100 * percentage;
//console.log(skipTo);
//Skip to specified second
video.currentTime = skipTo;
//Only allow text-elements to be visible inside text-display
let textDisplay = $("#video-effect-wrapper #text-display");
let textDisplayHeight = textDisplay.height();
let textDisplayTop = textDisplay.offset().top;
let textDisplayBottom = textDisplayTop + textDisplayHeight;
$("#video-effect-wrapper .text").each(function (i) {
let text = $(this);
if (text.offset().top < textDisplayBottom && text.offset().top > textDisplayTop) {
let textProgressPoint = textDisplayTop + (textDisplayHeight / 2);
let textScrollProgressInPx = Math.abs(text.offset().top - textProgressPoint - textDisplayHeight / 2);
textScrollProgressInPx = textScrollProgressInPx <= 0 ? 0 : textScrollProgressInPx;
let textScrollProgressInPerc = textScrollProgressInPx / (textDisplayHeight / 2) * 100;
//console.log(textScrollProgressInPerc);
if (text.hasClass("first"))
textScrollProgressInPerc = 100;
text.css("opacity", textScrollProgressInPerc / 100);
} else {
text.css("transition", "0.5s ease");
text.css("opacity", "0");
}
});
updateVideoPosition();
});
下面是HTML:
<div id="video-effect-wrapper">
<video muted autoplay>
<source src="https://ndvibes.com/test/video/video.mp4" type="video/mp4" id="video">
</video>
<div id="text-display"/>
<div class="text first">
Scroll down to test this little demo
</div>
<div class="text">
Still a lot to improve
</div>
<div class="text">
So please help me
</div>
<div class="text">
Thanks! :D
</div>
</div>
<div id="video-placeholder">
</div>
<div id="other-parts-of-website">
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
</div>
你可以在这里试试:https://jsfiddle.net/crkj1m0v/3/
发布于 2020-01-26 23:30:33
如果您希望在回滚时将视频锁定回原处,则需要标记从fixed
切换到relative
的位置。
//Get video element
let video = $("#video-effect-wrapper video").get(0);
video.pause();
let videoLocked = true;
let lockPoint = -1;
const vidHeight = 408;
//Initialize video effect wrapper
$(document).ready(function() {
const videoHeight = $("#video-effect-wrapper").height();
//If .first text-element is set, place it in bottom of
//text-display
if ($("#video-effect-wrapper .text.first").length) {
//Get text-display position properties
let textDisplay = $("#video-effect-wrapper #text-display");
let textDisplayPosition = textDisplay.offset().top;
let textDisplayHeight = textDisplay.height();
let textDisplayBottom = textDisplayPosition + textDisplayHeight;
//Get .text.first positions
let firstText = $("#video-effect-wrapper .text.first");
let firstTextHeight = firstText.height();
let startPositionOfFirstText = textDisplayBottom - firstTextHeight + 50;
//Set start position of .text.first
firstText.css("margin-top", startPositionOfFirstText);
}
//Code to launch video-effect when user scrolls
$(document).scroll(function() {
//Calculate amount of pixels there is scrolled in the video-effect-wrapper
let n = $(window).scrollTop() - $("#video-effect-wrapper").offset().top + vidHeight;
n = n < 0 ? 0 : n;
// console.log('n: ' + n);
//If .text.first is set, we need to calculate one less text-box
let x = $("#video-effect-wrapper .text.first").length == 0 ? 0 : 1;
//Calculate how many percent of the video-effect-wrapper is currenlty scrolled
let percentage = n / ($(".text").eq(1).outerHeight(true) * ($("#video-effect-wrapper .text").length - x)) * 100;
//console.log(percentage);
//Get duration of video
let duration = video.duration;
//Calculate to which second in video we need to go
let skipTo = duration / 100 * percentage;
//console.log(skipTo);
//Skip to specified second
video.currentTime = skipTo;
//Only allow text-elements to be visible inside text-display
let textDisplay = $("#video-effect-wrapper #text-display");
let textDisplayHeight = textDisplay.height();
let textDisplayTop = textDisplay.offset().top;
let textDisplayBottom = textDisplayTop + textDisplayHeight;
$("#video-effect-wrapper .text").each(function(i) {
let text = $(this);
if (text.offset().top < textDisplayBottom && text.offset().top > textDisplayTop) {
let textProgressPoint = textDisplayTop + (textDisplayHeight / 2);
let textScrollProgressInPx = Math.abs(text.offset().top - textProgressPoint - textDisplayHeight / 2);
textScrollProgressInPx = textScrollProgressInPx <= 0 ? 0 : textScrollProgressInPx;
let textScrollProgressInPerc = textScrollProgressInPx / (textDisplayHeight / 2) * 100;
//console.log(textScrollProgressInPerc);
if (text.hasClass("first"))
textScrollProgressInPerc = 100;
text.css("opacity", textScrollProgressInPerc / 100);
} else {
text.css("transition", "0.5s ease");
text.css("opacity", "0");
}
});
//If video-animation ended: Make position of video-wrapper relative to continue scrolling
if (videoLocked) {
if ($(window).scrollTop() >= videoHeight) {
$('video').css("position", "relative");
videoLocked = false;
lockPoint = $(window).scrollTop() - 10;
// I gave it an extra 10px to avoid flickering between locked and unlocked.
}
} else if ($(window).scrollTop() < lockPoint) {
$('video').css("position", "fixed");
videoLocked = true;
}
});
});
body {
margin: 0;
padding: 0;
background-color: green;
}
#video-effect-wrapper {
height: auto;
width: 100%;
}
#video-effect-wrapper video {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: -2;
object-fit: cover;
}
#video-effect-wrapper::after {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
background: #000000;
background: linear-gradient(to top, #434343, #000000);
opacity: 0.4;
z-index: -1;
}
#video-effect-wrapper .text {
color: #FFFFFF;
font-weight: bold;
font-size: 3em;
width: 100%;
margin-top: 50vh;
font-family: Arial, sans-serif;
text-align: center;
opacity: 0;
/*
background-color: blue;
*/
}
#video-effect-wrapper .text.first {
margin-top: 50vh;
opacity: 1;
}
#video-effect-wrapper .text:last-child {
/*margin-bottom: 100vh;*/
margin-bottom: 50vh;
}
#video-effect-wrapper #text-display {
display: block;
width: 100%;
height: 225px;
position: fixed;
top: 50%;
transform: translate(0, -50%);
z-index: -1;
/*
background-color: red;
*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="video-effect-wrapper">
<video muted autoplay>
<source src="https://ndvibes.com/test/video/video.mp4" type="video/mp4" id="video">
</video>
<div id="text-display"></div>
<div class="text first">
Scroll down to test this little demo
</div>
<div class="text">
Still a lot to improve
</div>
<div class="text">
So please help me
</div>
<div class="text">
Thanks! :D
</div>
</div>
<div id="other-parts-of-website">
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
<p>
Normal scroll behaviour wanted.
</p>
</div>
https://stackoverflow.com/questions/59866246
复制相似问题