We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
实现效果如下:
当然开始之前,你需要先准备几张图片,这里建议 5 张。 因为这个效果的实现原理是以数据为基础的,我这里只有五个可以拿来即用的数据。 如果图片超出五张的话,你需要自己手动写一下需要的数据 : )
戳这里获取我使用的图片
页面基础布局和样式如下:
HTML:
<div class="slider_wrapper" id="slider-wrapper"> <div class="slider_imgs" id="slider-imgs"> <ul> <li><img src="./imgs/1.png" alt="slider_img" /></li> <li><img src="./imgs/2.png" alt="slider_img" /></li> <li><img src="./imgs/3.png" alt="slider_img" /></li> <li><img src="./imgs/4.png" alt="slider_img" /></li> <li><img src="./imgs/5.png" alt="slider_img" /></li> </ul> <div class="slider_arrow" id="slider-arrow"> <span id="slider-arrow-left"><</span> <span id="slider-arrow-right">></span> </div> </div> </div>
CSS:
div, span, ul, li, img { margin: 0; padding: 0; } body { overflow: hidden; background: #666; padding: 50px; } li { list-style: none; } .slider_wrapper { width: 1200px; margin: 0 auto; margin-top: 60px; } .slider_imgs { position: relative; height: 430px; margin: 0 auto; } .slider_imgs li { position: absolute; } .slider_imgs img { width: 100%; } .slider_arrow { z-index: 999; position: relative; top: 50%; opacity: 0; -webkit-user-select: none; -moz-user-select: none; user-select: none; transition: opacity 0.3s ease; } .slider_wrapper:hover .slider_arrow { opacity: 0.5; } #slider-arrow-left, #slider-arrow-right { z-index: 999; display: block; position: absolute; width: 50px; height: 50px; line-height: 40px; border-radius: 6px; text-align: center; font-size: 50px; font-weight: 600; background: #a9a9a9; color: #333; transform: translate(0, -50%); cursor: pointer; } #slider-arrow-right { right: 0; }
样式和 DOM 结构不多 BB,主要的心思放在效果实现上。
这里我用了一个封装好的运动函数: startMove,代码如下:
startMove
/** * 获取某个属性的值 * @param {Object} elem 当前元素 * @param {String} attr 属性 */ function getStyle(elem, attr) { if (window.getComputedStyle) { return window.getComputedStyle(elem, null)[attr]; } else { return elem.currentStyle[attr]; } } /** * 缓冲运动函数 * @param {Object} elem 当前元素 * @param {Object} json 要操作的属性 // 传透明度属性时,范围是0-100 * @param {Function} fn 回调函数 * @param {Number} slow 动画的缓慢程度 // 数值越大,动画越迟缓。 * @param {Number} time 每次动画执行时间 */ function startMove(elem, json, fn = null, slow = 10, time = 15) { clearInterval(elem.timer); elem.timer = setInterval(function() { var bStop = true; for (var attr in json) { var iCur = 0; var target = json[attr]; if (attr === "opacity") { iCur = getStyle(elem, attr) * 100 || 1; } else { iCur = parseInt(getStyle(elem, attr)) || 0; } var iSpeed = (target - iCur) / slow; iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); iCur += iSpeed; if (attr === "opacity") { elem.style.filter = "alpha(opacity=" + iCur + ")"; elem.style[attr] = iCur / 100; } else if (attr === "zIndex") { elem.style.zIndex = target; } else { elem.style[attr] = iCur + "px"; } iCur != target && (bStop = false); } if (bStop) { clearInterval(elem.timer); fn && fn(); } }, time); }
这个函数的作用是实现缓冲运动,可以同时操作多个 CSS 属性,实现一些比较复杂的动画。
举个栗子:
利用上面的 startMove 实现下面这个效果:
代码如下:
var oTest = document.getElementById("oTest"); startMove( oTest, { width: 100, height: 100, borderRadius: 100 }, function() { startMove( oTest, { width: 400, opacity: 60 }, function() { startMove( oTest, { left: 200, top: 100, width: 100 }, function() { startMove( oTest, { left: 150, top: 50, width: 200, height: 200 }, function() { startMove(oTest, { left: 200, top: 100, width: 100, height: 100 }); } ); } ); } ); }, 60, 20 );
当然,上面这个效果比较复杂,所以代码有点臃肿。这也是 startMove 函数的一个缺点。
回到正题,现在来看一下 3D 轮播的效果是怎么实现的:
首先准备五个数据(文章开始提到的,当然你可以自己随意调整),这五个数据分别对应着图片显示的大小,位置,透明度 和 层级关系。
var IMG_DATAS = [ { width: 300, top: -20, left: 150, opacity: 20, zIndex: 2 }, { width: 500, top: 30, left: 50, opacity: 80, zIndex: 3 }, { width: 600, top: 100, left: 300, opacity: 100, zIndex: 4 }, { width: 500, top: 30, left: 650, opacity: 80, zIndex: 3 }, { width: 300, top: -20, left: 750, opacity: 20, zIndex: 2 } ];
然后我们将这五个数据和五张图片分别传入运动函数 startMove:
var oImgsWrapper = document.getElementById("slider-imgs"); var aImgs = oImgsWrapper.getElementsByTagName("li"); function sliderMove() { IMG_DATAS.forEach(function(item, index) { startMove(aImgs[index], item); }); } sliderMove();
这样,初始加载页面时,图片就会自动去找自己的位置:
Cool!这就是面向数据的优点,我们只关心数据,通过数据来操控页面。数据的变化反应到页面上就实现了页面上的交互,动画,数据处理等等。
既然初始动画这么简单就完成了,那么切换的动画呢?!你可以先思考一下切换动画的实现。
这里揭晓一下答案:
既然是面向数据,我们就只关心数据,剩下的动画部分交给 startMove 处理就好了。
图片左右切换,实际也就是数组里五个数据的切换。我们只需模拟队列,改变数据的顺序即可:当图片左移时,将最后一个数据从数组中移出,然后将这个数据添加到数组开头,最后把处理后的数组传给 startMove 函数。这样,数据的流动反应到页面上就是图片的移动,很酷,不是吗?
图片右移和左移同理。
核心代码如下:
// 图片左移 IMG_DATAS.unshift(IMG_DATAS.pop()); // 图片右移 IMG_DATAS.push(IMG_DATAS.shift());
这里要特别注意一下:数据在数组中向左移动(也就是将数据从数组开头移出,然后添加到数组末尾),图片实际是向右移动的。这点不难理解,就好比水车,水往左流,而水车是向右旋转。
每次移动完以后,将处理后的数组传给 startMove:
function sliderMove() { IMG_DATAS.forEach(function(item, index) { startMove(aImgs[index], item); }); } sliderMove();
完整代码如下:
window.onload = function() { var IMG_DATAS = [ { width: 300, top: -20, left: 150, opacity: 20, zIndex: 2 }, { width: 500, top: 30, left: 50, opacity: 80, zIndex: 3 }, { width: 600, top: 100, left: 300, opacity: 100, zIndex: 4 }, { width: 500, top: 30, left: 650, opacity: 80, zIndex: 3 }, { width: 300, top: -20, left: 750, opacity: 20, zIndex: 2 } ]; var oBtnLeft = document.getElementById("slider-arrow-left"); var oBtnRight = document.getElementById("slider-arrow-right"); var oImgsWrapper = document.getElementById("slider-imgs"); var aImgs = oImgsWrapper.getElementsByTagName("li"); // 图片轮播 function sliderMove() { IMG_DATAS.forEach(function(item, index) { startMove(aImgs[index], item); }); } // 页面初始加载,执行一次动画 sliderMove(); // 点击左按钮 oBtnLeft.onclick = function() { IMG_DATAS.push(IMG_DATAS.shift()); sliderMove(); }; // 点击右按钮 oBtnRight.onclick = function() { IMG_DATAS.unshift(IMG_DATAS.pop()); sliderMove(); }; };
到此,基本的功能已经实现。
那么再思考一下,如何实现:点击图片将其显示在中间?
既然是面向数据,那么动画的实现原理都是类似的,只要合适的操纵数据即可。如果理解了上面左、右轮播的原理,那么这个效果的实现应该没太大问题,这里讲下我的思路。
index
middle
2
改进后的完整代码如下:
window.onload = function() { var IMG_DATAS = [ { index: 0, width: 300, top: -20, left: 150, opacity: 20, zIndex: 2 }, { index: 1, width: 500, top: 30, left: 50, opacity: 80, zIndex: 3 }, { index: 2, width: 600, top: 100, left: 300, opacity: 100, zIndex: 4 }, { index: 3, width: 500, top: 30, left: 650, opacity: 80, zIndex: 3 }, { index: 4, width: 300, top: -20, left: 750, opacity: 20, zIndex: 2 } ]; var oBtnLeft = document.getElementById("slider-arrow-left"); var oBtnRight = document.getElementById("slider-arrow-right"); var oImgsWrapper = document.getElementById("slider-imgs"); var aImgs = oImgsWrapper.getElementsByTagName("li"); // 计算中间的图片的索引 var nMiddleImgIndex = Math.floor(aImgs.length / 2); for (let i = 0; i < aImgs.length; i++) { aImgs[i].onclick = function() { // 计算数据需要模拟队列移动的次数 var nMoveLen = IMG_DATAS[i].index - nMiddleImgIndex; if (!nMoveLen) return; // 图片已经在中间 if (nMoveLen < 0) { // 点击左边的图片,图片右移 for (let j = 0; j < Math.abs(nMoveLen); j++) { IMG_DATAS.push(IMG_DATAS.shift()); } } else { // 点击右边的图片,图片左移 for (let j = 0; j < nMoveLen; j++) { IMG_DATAS.unshift(IMG_DATAS.pop()); } } sliderMove(); }; } // 图片轮播 function sliderMove() { IMG_DATAS.forEach(function(item, index) { startMove(aImgs[index], item); }); } // 页面初始加载,执行一次动画 sliderMove(); // 点击左按钮 oBtnLeft.onclick = function() { IMG_DATAS.push(IMG_DATAS.shift()); sliderMove(); }; // 点击右按钮 oBtnRight.onclick = function() { IMG_DATAS.unshift(IMG_DATAS.pop()); sliderMove(); }; };
Demo 体验地址:https://liuyib.github.io/blog/demo/blog/slider-3D/
以上 🚀
The text was updated successfully, but these errors were encountered:
No branches or pull requests
实现效果如下:
当然开始之前,你需要先准备几张图片,这里建议 5 张。
因为这个效果的实现原理是以数据为基础的,我这里只有五个可以拿来即用的数据。
如果图片超出五张的话,你需要自己手动写一下需要的数据 : )
页面基础布局和样式如下:
HTML:
查看内容
CSS:
查看内容
样式和 DOM 结构不多 BB,主要的心思放在效果实现上。
这里我用了一个封装好的运动函数:
startMove
,代码如下:这个函数的作用是实现缓冲运动,可以同时操作多个 CSS 属性,实现一些比较复杂的动画。
举个栗子:
利用上面的
startMove
实现下面这个效果:代码如下:
查看内容
当然,上面这个效果比较复杂,所以代码有点臃肿。这也是
startMove
函数的一个缺点。回到正题,现在来看一下 3D 轮播的效果是怎么实现的:
首先准备五个数据(文章开始提到的,当然你可以自己随意调整),这五个数据分别对应着图片显示的大小,位置,透明度 和 层级关系。
然后我们将这五个数据和五张图片分别传入运动函数
startMove
:这样,初始加载页面时,图片就会自动去找自己的位置:
Cool!这就是面向数据的优点,我们只关心数据,通过数据来操控页面。数据的变化反应到页面上就实现了页面上的交互,动画,数据处理等等。
既然初始动画这么简单就完成了,那么切换的动画呢?!你可以先思考一下切换动画的实现。
这里揭晓一下答案:
既然是面向数据,我们就只关心数据,剩下的动画部分交给
startMove
处理就好了。图片左右切换,实际也就是数组里五个数据的切换。我们只需模拟队列,改变数据的顺序即可:当图片左移时,将最后一个数据从数组中移出,然后将这个数据添加到数组开头,最后把处理后的数组传给 startMove 函数。这样,数据的流动反应到页面上就是图片的移动,很酷,不是吗?
图片右移和左移同理。
核心代码如下:
每次移动完以后,将处理后的数组传给
startMove
:完整代码如下:
查看内容
到此,基本的功能已经实现。
那么再思考一下,如何实现:点击图片将其显示在中间?
既然是面向数据,那么动画的实现原理都是类似的,只要合适的操纵数据即可。如果理解了上面左、右轮播的原理,那么这个效果的实现应该没太大问题,这里讲下我的思路。
index
属性,表示图片的索引。index
值,这里用变量middle
表示。比如:有五张图片,那么middle
应该为2
。index
属性值,将其与middle
比较,差值的绝对值就是对数据进行模拟队列操作的次数。改进后的完整代码如下:
查看内容
Demo 体验地址:https://liuyib.github.io/blog/demo/blog/slider-3D/
以上 🚀
The text was updated successfully, but these errors were encountered: