javascript
用原生JS实现3D轮播效果
用原生JS實現3D輪播效果
實現思路:
效果如下:
視圖中顯示3張圖片,并通過CSS的透視和旋轉實現3D效果,當無任何操作時,圖片自動循環輪播。當鼠標劃到輪播圖時,則停止輪播,滑出時繼續自動輪播,此效果通過觸發mouseenter和mouseleave事件和計時器來實現。當鼠標在輪播圖上向左右滑動時,根據方向輪播下一站或上一張圖片,通過觸發mousedown和mouseup事件時,的鼠標的clientX來判斷方向。
無縫輪播思路
視圖中都會顯示3張圖片,當我們輪播到最后一張圖片時,我們該怎么辦呢???
我的思路:
如果要達到循環輪播效果,那么最后一張圖片結束后,我們就應該繼續輪播第一張圖片,當最后一張圖片為視圖中的最左側的圖片時則視圖中顯示的圖片應當是最后一張、第一張和第二張圖片,為了能讓這三張圖片組合到一起,所以我在最后添加了第一張圖片和第二張圖片,當繼續輪播時,則從正方向的第一張和第二張圖片開始(相當于我們開到的是倒數的兩張,但輪播時是正數的兩張開始),如果是逆向輪播,則看到的是正序的前兩張,輪播時從倒序輪播。
思路圖大致如下:
用一句話就是:正序的0、1與逆序的0、1進行偷梁換柱,達到循環輪播效果。
代碼
HTML部分:
<div class="container"><div class="wrapper"><div class="slide pre-slide"><img src="img/img1.jpg"></div><div class="slide cur-slide"><img src="img/img2.jpg"></div><div class="slide next-slide"><img src="img/img3.jpg"></div><div class="slide"><img src="img/img4.jpg"></div></div></div>CSS部分
<style>* {margin: 0;padding: 0;}body {background-color: #000;}.container {margin: 50px auto;width: 1000px;height: 500px;/*background-color: #ececec;*/overflow: hidden;position: relative;}.wrapper {height: 500px;width: 900px;/*border: 1px solid #000;*//*注意:這里解決了slide的子元素之間的間距問題————即使設置了margin和padding時,子元素之間仍有間距(子元素之間存在空格或換行字符),所以這里需要設置字體大小為0*/font-size: 0px;/**/position: absolute;left: 0;top: 0;}.wrapper:hover {cursor: pointer;}.slide {width: 300px;height: 500px;display: inline-block;border: none;font-size: 32px;font-weight: 900;text-align: center;perspective: 600px;}.slide img {width: 100%;height: 100%;transform: translateZ(-500px);}.pre-slide img {/*background-color: rgb(56, 233, 50);*/transform: translateZ(0px) rotateY(45deg);transition: all 1.5s;}/**/.cur-slide img {/*background-color: rgb(57, 180, 236);*/transform: translateZ(100px);transition: all 1.5s;}.next-slide img {/*background-color: #f4f81c;*/transform: translateZ(0px) rotateY(-45deg);transition: all 1.5s;}JS部分
<script>/** * distance用來記錄每次輪播時的偏移量* prePos用來記錄輪播圖最左邊元素的Index* downPos用來記錄mousedown時鼠標的clientX* flag用來記錄窗口移動的方向,true向左,false向右* * * */let wrapper, slides, container, downPos, prePos, timeID, num;init();function init() {prePos = 0;flag = true;wrapper = document.querySelector('.wrapper')slides = document.getElementsByClassName('slide')container = document.querySelector('.container')num = slides.length;let firstNode = slides[0].cloneNode(true);let secondNode = slides[1].cloneNode(true);wrapper.appendChild(firstNode);wrapper.appendChild(secondNode);distance = slides[0].clientWidth;//初始化處理//根據slide的多少動態設置wrapper的寬度wrapper.style['width'] = slides.length * distance + 'px';container.style.width = 3 * distance + 'px';//wrapper.style.left = -distance + 'px';//console.log(wrapper.style);timeID = setInterval(move, 3000);wrapper.addEventListener('mousedown', handelMouseDown, true);wrapper.addEventListener('mouseenter', handleMouseenter);wrapper.addEventListener('mouseleave', handleMouseleave);}function move() {updateClassName(prePos, 'slide')updateClassName(prePos + 1, 'slide')updateClassName(prePos + 2, 'slide')if (flag) {if (prePos === slides.length - 3) {prePos = 0;} else {prePos++;}} else {if (prePos === 0) {prePos = slides.length - 3;} else {prePos--;}}//console.log(prePos);wrapper.style.left = -prePos * distance + 'px';console.log(prePos);updateClassName(prePos, 'slide pre-slide')updateClassName(prePos + 1, 'slide cur-slide')updateClassName(prePos + 2, 'slide next-slide')}function updateClassName(pos, name) {switch (pos) {case 0:case slides.length - 2:console.log(name);slides[0].className = slides[slides.length - 2].className = namebreak;case 1:case slides.length - 1:slides[1].className = slides[slides.length - 1].className = namebreak;default:slides[pos].className = name;break;}}function handelMouseUp(e) {//console.log(e.clientX);if (e.clientX < downPos) {//console.log('左');flag = true;} else if (e.clientX > downPos) {//console.log('右');flag = false;}move();}function handleMouseenter(e) {//console.log('enter');clearInterval(timeID);}function handleMouseleave() {//console.log('leave');flag = true;timeID = setInterval(move, 3000)}function handelMouseDown(e) {//console.log(e.target);//此處解決連續對同一個sliede的mousedown和mouseup使用一次后失效的問題//原因://觸發了瀏覽器的 drag 操作,導致mouseup丟失。//由于鼠標離開了操作的區域,觸發了mouseleave導致mouseup丟失。e.preventDefault(); //我可能遇到的是第一種情況//e.stopPropagation();downPos = e.clientX;wrapper.addEventListener('mouseup', handelMouseUp);} </script>在實現過程中可能會遇到一些問題,我遇到的都體現在代碼注釋里面啦。
總結一下:
在開始的時候我為了簡單化問題,于是我是只用了幾個div進行輪播,當基本上實現無縫輪播的時候,我在另一個文件中進行圖片的3D效果測試(我也剛接觸前端不久,對CSS3的動畫掌握也不太熟練),當覺得兩個效果都差不多時再合并代碼,將圖片的3D效果添加到輪播圖中。合并后,也出現了一個問題,比如當輪播到最后一張后繼續正向輪播和到第一張后要逆向輪播時,偷梁換柱的過程中,會出現輪播效果和前一次相同方向輪播的效果不一致的問題。關于這一點,我被自己繞了很久,當后面想通后,也就清晰明了了。出現這個問題的原因是因為我在代碼實現的過程中,將正序的0、1和逆序的0、1獨立化了,而它們本不應該相互獨立,如果獨立了,它們就存在className不一致的問題,那么它們在輪播前的一次狀態就不一樣,那么效果的呈現也就不一樣了,于是出現了updateClassName方法,當修改每個slide的className時,不管是正序0\1或是倒敘的,其正序的0與倒敘的0、正序的1和倒敘的1的className都要更新為最新的className,才能達到做好偷梁換柱。
除此之外,也遇到沒有記住的小問題:
容器之間存在空格字符或換行符,都視為一個空格字符,這個字符也有大小,也就是我們所見的間隙,將其父容器的font-size設為0則可以解決。
當mousedown觸發后,可能會觸發瀏覽器的默認事件,在mousedown的回調函數中使用e.preventDefault()禁止觸發默認事件就可以。
最后
我把代碼放到倉庫啦,代碼還有待完善的空間,請各位多多指教:
鏈接: 代碼.
總結
以上是生活随笔為你收集整理的用原生JS实现3D轮播效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 固态硬盘对于linux提升,固态硬盘在L
- 下一篇: 超详细,wepy小程序如何引入第三方插件