簡體   English   中英

滾動時垂直img列表的有效“視差效果”

[英]efficient “parallax effect” for vertical img-list while scrolling

我有一張圖像列表,向下/向上滾動的同時緩慢向上/向下移動圖像

圖像本身由“ object-fit:cover;”設置。 和“ object-position:center 50%;”,因此我有空間將圖像向下移動到“ object-position:center 100%;”的最大值 同時向上滾動。 相反,將圖像移至“對象位置:中心0;”的最小值。 同時向下滾動。

簡而言之:當用戶向下滾動圖像列表時,每個圖像應從其隱藏的頂部緩慢顯示更多,反之亦然。

我在whatsapp客戶端(ios)上發現了這種很好的parralax效果。 當用戶向下滾動時,媒體內容會向上滾動一點,反之亦然。 我想要達到完全相同的效果。

因此,我編寫了以下代碼-可以運行,但是性能很差,我正在尋找更好的解決方案。 有誰知道這個問題的更好的解決方案? 也許可以使用“純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 stylePaint

如果您不熟悉這些,可以通過以下方法在特定事件后瀏覽器更新屏幕。 代碼觸發的事件非常繁重。 現在,在每次滾動事件中,您的代碼都會在瀏覽器窗口上觸發昂貴的繪制事件。

基本上,您想要做的就是重構它,這樣您的代碼就不必重新繪制。 您可能需要將objectPosition更改為.style.transorm = "translate3d(0, " + new_y + ", 0)"; 那些不應該像現在那樣觸發繪畫事件。

與此相關的是,它可能仍會觸發油漆。 我建議您閱讀有關滾動性能的文章,因為它不能過多地解釋堆棧溢出, Paul Lewis撰寫了一篇不錯的文章。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM