gpt4 book ai didi

javascript - 滚动时垂直 img-list 的有效 "parallax effect"

转载 作者:行者123 更新时间:2023-11-28 04:20:05 27 4
gpt4 key购买 nike

我有一个图片列表,我想在向下/向上滚动的同时缓慢向上/向下移动图片

图像本身由“object-fit: cover;”设置和“对象位置:中心 50%;”,所以我有空间将图像向下移动到“对象位置:中心 100%;”的最大值向上滚动时。相反,将图像向上移动到“object-position:center 0;”的最小值。向下滚动时。

简而言之:当用户向下滚动图片列表时,每张图片应该从其隐藏的顶部慢慢显示更多内容,反之亦然。

我在 whatsapp 客户端 (ios) 上发现了这个不错的视差效果。当用户向下滚动时,媒体内容会向上滚动一点,反之亦然。我想达到完全一样的效果。

所以我编写了以下代码 - 它可以工作,但是性能很差,我正在寻找更好的解决方案。有谁知道这个问题的更好解决方案?也许通过使用“纯 css parralax”(http://keithclark.co.uk/articles/pure-css-parallax-websites/)。这将是最好的解决方案 - 但是,我不能对我的问题采用这种技术。

您可以将它复制/粘贴到一个新的 index.html 中,它会按原样工作。

这是完整的工作代码(性能不佳):

(function() {
document.addEventListener('DOMContentLoaded', function() {

/** returns true, if node is in viewport.
*/
function node_is_in_viewport(element) {

var rect = element.getBoundingClientRect();
var html = document.documentElement;

return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
}

/** returns "y-value" of css-property "object-position"
*/
function getObjectPosY(translateString){
var n = translateString.indexOf('%');
var n1 = translateString.lastIndexOf("%");

var res = parseInt(translateString.slice(n+1,n1));
return res;
}

var list_img = document.querySelector('.list-img');
var pos_list = list_img.scrollTop;
var all_imgs = document.querySelectorAll('.list-img>li img');

console.log('actual position of the list:');
console.log(pos_list);

list_img.addEventListener('scroll', function(e){

var scroll = this.scrollTop;

// positive number means "scroll down"
// negative number means "scroll up"
var offsetScrollTreshold = scroll - pos_list; // unused

// move image 1 unit up/down
var offsetScroll = 3;
var speed = 1;

console.log('position of list (pos_list):');
console.log(pos_list);

console.log('scroll:');
console.log(scroll);

console.log('offset (scroll - pos_list):');
console.log(offsetScrollTreshold);

if(scroll > pos_list) {
console.log('User is scrolling DOWN');
console.log('I want to show more from the hidden top of all the images within the actual viewport while user is scrolling down. But each image should not exceed its original image size.');

list_img.classList.add('scroll-down');
list_img.classList.remove('scroll-up');

[].forEach.call(all_imgs, function(node) {

var node_in_view = node_is_in_viewport(node);

// if image is in viewport move it up to "make a parallax effect"
if(node_in_view){
console.log('-----');
console.log('actual img to move up (new Y must be lower):');
console.log(node.src);

var old_y = 0;

var theCSSprop = window.getComputedStyle(node, null).getPropertyValue('object-position');
if( theCSSprop.indexOf('%')!=-1 ){
console.log(theCSSprop);

// returns the actual "y"-position of the image
old_y = getObjectPosY(theCSSprop);
console.log('old_y:');
console.log(old_y);
}


// User is scrolling down, so I want to view more from the "top of the image" which is actually a little hidden (because of object-fit: center 50%)
// to view more from the top of the image, I have to set the y-value (actually: 50%) lower, but not more than 0.
if(old_y > 0 && old_y <= 100){

console.log('scroll image "slowly" up while user is scrolling down (parallax effect)');
var new_y = old_y - offsetScroll * speed;

if(new_y<0){
new_y = 0;
}

console.log('new_y:');
console.log(new_y);
node.style.objectPosition = '50% '+ new_y + '%';
}
}

});
}
else {

console.log('User is scrolling UP');
console.log('I want to show more from the hidden bottom of all the images within the actual viewport while user is scrolling up. But each image should not exceed its original image size.');

list_img.classList.remove('scroll-down');
list_img.classList.add('scroll-up');

[].forEach.call(all_imgs, function(node) {

var node_in_view = node_is_in_viewport(node);

// if image is in viewport move it down to "make a parallax effect"
if(node_in_view){

console.log('actual img to move down (new Y must be higher):');
console.log(node.src);

var theCSSprop = window.getComputedStyle(node, null).getPropertyValue('object-position');
if(theCSSprop.indexOf('%')!=-1){
console.log(theCSSprop);

// returns the actual "y"-position of the image
old_y = getObjectPosY(theCSSprop);

console.log('old_y:');
console.log(old_y);
}

// User is scrolling up, so I want to view more from the "bottom of the image" which is actually a little hidden (because of object-fit: center 50%)
// to view more from the bottom of the image, I have to set the y-value (actually: 50%) higher, but not more than 100%.
if(old_y >= 0 && old_y < 100){

console.log('scroll image "slowly" down while user is scrolling up (parallax effect)');

var new_y = old_y + offsetScroll * speed;

if(new_y>100){
new_y = 100;
}

console.log('new_y:');
console.log(new_y);

node.style.objectPosition = '50% '+ new_y + '%';
}
}
});
}

pos_list = scroll;
console.log('pos_list:');
console.log(pos_list);

});/*end eventlistener scroll */

}); /*end .DOMContentLoaded */
}());

   

body, html, #ctn_infinity, .list-img{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}

.list-img{
height: 90vh;
overflow: auto;
}


.list-img{
list-style: none;
width: 400px;
}

.list-img>li{
display: flex;
flex-direction: column;
border: 2px solid black;
margin: 16px auto;
}

.list-img div{
background: yellow;
}

.list-img img{
object-fit: cover;
width: 100%;
/* original image size: 400 width x 200 height */
/* I use object position center: when scrolling up or down, images should "slowly" show its hidden part of its images (max. 25px top or 25px down) */
height: 150px;
/* Unfortunately, I cannot use "transform: translateY(-5px);", because this will move the whole img-container instead of the img itself up/down" */
object-position: center 50%;
}



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML-TEST</title>


</head>
<body>
<div id="ctn_infinity">
<ul class="list-img">
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
<li><img src="http://lorempixel.com/400/200">
<div>lorem epsum..</div></li>
</ul>
</div>
</body>
</html>

最佳答案

我在 csstriggers.com 上找不到对象位置。但是我自己检查了一下,一旦我用 object-fit: cover 改变了一个元素的对象位置,我就得到了一个Recalculate style 和一个Paint

如果您不熟悉这些,这些是浏览器在特定事件后更新屏幕的方式。而且你的代码触发的事件非常繁重。现在,在每次滚动事件中,您的代码都会在浏览器窗口上触发昂贵的绘制事件。

基本上您要做的是重构它,这样您的代码就不必重新绘制。您可能希望将 objectPosition 更改为 .style.transorm = "translate3d(0, "+ new_y + ", 0)";。那些不应该像现在这样触发绘画事件。

尽管如此,它仍然有可能触发绘画。我建议您阅读有关滚动性能的内容,因为关于堆栈溢出的解释太多了,Paul Lewis wrote一篇关于此的好文章。

关于javascript - 滚动时垂直 img-list 的有效 "parallax effect",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42249364/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com