用原生JS实现3D轮播效果

实现思路:

  1. 先实现无缝轮播效果
  2. 添加3D效果
  3. 完善代码
  4. 增加自动轮播效果

效果如下:


视图中显示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,才能达到做好偷梁换柱。
除此之外,也遇到没有记住的小问题:

  1. 为什么将margin和padding设置为0后,容器之间还有间隙?
    容器之间存在空格字符或换行符,都视为一个空格字符,这个字符也有大小,也就是我们所见的间隙,将其父容器的font-size设为0则可以解决。
  2. mouseup触发一次后失效的问题:
    当mousedown触发后,可能会触发浏览器的默认事件,在mousedown的回调函数中使用e.preventDefault()禁止触发默认事件就可以。

最后

我把代码放到仓库啦,代码还有待完善的空间,请各位多多指教:
链接: 代码.

用原生JS实现3D轮播效果相关推荐

  1. 前端原生js实现图片轮播效果,超级简单,备注详细

    原生js实现简单轮播图,效果如下 纯生js实现轮播图 链接: link. 图片: 我们可以通过左右两边的箭头来播放图片,在我们的鼠标放在图片上时,自动播放结束,转化为手动播放,可以通过小圆点来点击切换 ...

  2. html图片3djs轮播,原生js实现3D轮播图

    3D轮播图是我做过复杂的图片轮播了,由于是利用坐标,层级之间的关系,所以实现起来原理比较简单但是bug巨多,在推推拖拖了好久后,下定决心重新整理成博客,与大家分享! 首先分析一下3D图片轮播的功能需求 ...

  3. js实现新闻轮播效果

    原生js实现新闻轮播效果,附详细注释 <!DOCTYPE html> <html lang="en"> <head><meta chars ...

  4. html多图轮播淡入淡出js,原生JS实现图片轮播与淡入效果的简单实例

    最近对css的兴趣提不起来,因为以前对图片轮播一直耿耿于怀苦于学艺不精,所以,花了点时间熟悉了一下js.然后一条道走到黑,用jquery和js写了一下轮播和图片淡入的效果.以后学习的路很长,希望自己在 ...

  5. html原生js实现图片轮播,原生JS实现图片轮播切换效果

    原生JS实现图片轮播切换效果 2019-01-06 编程之家 https://www.jb51.cc 编程之家收集整理的这篇文章主要介绍了原生JS实现图片轮播切换效果,编程之家小编觉得挺不错的,现在分 ...

  6. js实现图片3D轮播效果(收藏)

    3D的图片轮播效果很炫,写到这里只是为了不丢代码,不为别的. 效果预览: html代码: <head> <meta http-equiv="Content-Type&quo ...

  7. 原生js进阶版轮播图实现(走马灯效果,无缝衔接)

    原生js进阶版轮播图实现(走马灯效果,无缝衔接) 利用原生js手写一个轮播图,是上一篇文章的简易版的一个进阶,本次轮播图主要是利用定位和定时器实现了走马灯效果,并且是左右轮播.实现过程与代码也是很简单 ...

  8. php cms 轮播图,原生JS运动实现轮播图

    原生JS运动实现轮播图 **基本原理:**通过控制包含n张图片的ul的left值来实现图片自动运动的效果,其中列表中li元素的个数为n,第一个li和最后一个li里存放的图片应为同一张图片,当图片运动到 ...

  9. JS实现图片轮播效果(自动和手动)

    本次轮播效果图如下: 具有以下功能:1.自动播放(鼠标进入显示区域时停止播放) 2.左右焦点切换  3.底下小按钮切换 ps:由于很多同志反馈无法总有各种奇怪的情况,所以有需要的直接下载整个工程:JS ...

最新文章

  1. python使用matplotlib可视化线图(line plot)、为可视化图像添加双Y轴、分别可视化不同范围的数据(double y axis in matplotlib)
  2. .netcore 如何获取系统中所有session_集群化部署,Spring Security 要如何处理 session 共享?
  3. iOS开发之网络编程--1、NSURLSession的基本使用
  4. 在一台win10上启动多个mysql
  5. 关于如何将sublime的主题应用到webstorm上
  6. 折线图 java_java报表折线图
  7. 计算机控制基础知识,最新 分析计算机控制系统及其运算基础知识-精品
  8. 基于特征的文法分析以及概述自然语言处理
  9. 究竟如何保证session一致性?
  10. python判断手机号码是否正确_python检测手机号码是否合法
  11. 图像识别利用计算机对图像进行,图像识别技术的应用与发展
  12. linux允许8000端口,Linux中如何开启8080端口供外界访问 和开启允许对外访问的端口8000...
  13. 英文演讲稿(3-5分钟)
  14. Ubuntu14.04搭建LXR本地服务器阅读Linux内核代码
  15. 移植QT5.6到韦东山JZ2240嵌入式开发板(史上最最最最最详细的QT移植教程)
  16. shell 变量五 字符串掐头去尾
  17. Java后端开发工程师是否该转大数据开发?
  18. java中throw是什么意思_Java中throw和throws的区别是什么
  19. 非对称加密(RSA、数字签名、数字证书)
  20. java动态代理实现与原理详细分析

热门文章

  1. Granger Causality 格兰杰因果关系
  2. VS中fseek.cpp引发断点——将一个无效参数传递给了将无效参数视为严重错误的函数
  3. 从“Real如我”来看当前社交APP开发-深圳积木创意科技
  4. Prometheus+SpringBoot应用监控全过程详解
  5. HTML+CSS面试试题(部分)
  6. 10步Navicat for Mysql12.1.20破解激活方法(适用于Navica12.1系列软件)
  7. 哈希表的画法_2018年流行什么眉型
  8. 成为oracle白金会员,华为成为Linux基金会白金会员
  9. 第一篇,怎么增加SYN数据包的大小(syn flood攻击实验)
  10. input获取焦点边框 outline属性