摘要:你的网站真的需要一个轮播图吗轻轻问自己三声,谷歌一下对轮播图效果的相关调查和建议,再决定是否要着手制作你的轮播图。在接近块间距时关闭动画移至另一块相应位置。表示接近边缘的图片。可把一部分放到里或轮播图前,阻塞渲染。
轮播图千种万种,怎样才能做出符合要求的轮播图?原理上天入地,如何优化才能达到极限丝滑?本文作者将解答这一切,通过现场制作一个轮播图,带你详细了解、理解,制作 All kinds of 高性能轮播图 !
仿自 Google Play
不过,在事实上,轮播图的点击率通常都很低,很少能引起用户的注意,而却往往占用了页面某个极重要的位置。你的网站真的需要一个轮播图吗?轻轻问自己三声,谷歌一下对轮播图效果的相关调查和建议,再决定是否要着手制作你的轮播图。
2017.8.20 更新——————————
1. 代码简洁化 & 语言精简
2. 删去不被推荐的有限部分
3. API 重写
! ES6 API 重写
ES6 啊,,牛逼啊!我TM要火啊!!
然而并没有。
1. 结构
div.father包裹图片。div.viewport为视口部分。
.viewport {
width: 900px;
height: 300px;
overflow: hidden;
position: relative;
}
.father {
height: inherit;
width: 3000%; /* 子元素 float 无法撑开 */
transform: translate3d(0, 0, 0);
transition: transform 0.3s ease-in-out;
}
.father > div {
width: 550px;
height: inherit;
float: left;
}
.mother {
width: 30px;
height: inherit;
line-height: 300px;
text-align: center;
cursor: pointer;
user-select:none;
background: rgba(0,0,0,0.15);
position: absolute;top: 0;
} .mother.left { left: 0 } .mother.right { right: 0 }
transform: translate3d()使用 GPU 加速。
2. 代码实现
class Lunbo {
constructor(element) {
this.viewport = element;
this.father = element.children[0];
this.photos = this.father.children;
// 自设的图片宽, 包括 margin
this.photoWidth = this.photos[0].offsetWidth + parseInt(getComputedStyle(this.photos[0]).marginLeft) + parseInt(getComputedStyle(this.photos[0]).marginRight);
// 注册移动事件
element.children[1].addEventListener("click", this.left.bind(this));
element.children[2].addEventListener("click", this.right.bind(this));
}
load() {
}
left() {
this.load(this.showingId - 1);
}
right() {
this.load(this.showingId + 1);
}
}
页面加载时:选取一张作为焦点
切换时:fatherGo(to)负责跳转到指定的焦点图;
高效 & 无限轮播
(此处以下所有代码仅显示添加 / 修改部分)
思路也是难点。一题,这样解决:
class Lunbo {
constructor(element) {
// (可视宽 -焦点图片宽) / 2,焦点图到视口左或右的距离
this.partnerWidth = (this.viewport.clientWidth - this.photoWidth) / 2;
}
// 计算移动距离
countX(id) {
return -id * this.photoWidth + this.partnerWidth;
}
// 切换 / 载入 / 移动图片。无参数则除法求整,仅用来切换到一个瞎选的初始焦点
load(newId = parseInt(this.photos.length / 2) - 1) {
this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`;
this.showingId = newId;
}
}
// 切换至初始焦点
const Example = new Lunbo(document.getElementById("example"));
Example.load();
countX(id) 解释:
若将 Id = 2 对应图片(第 3 张)作焦点,向左挪过去两张(此时该图靠最左),后加回partnerWidth
二题:
ABCDEABCDEABCDE
三倍于展示图,JS 动态生成亦可。称之三个块。
.moving { transition: none }
在接近块间距时关闭动画移至另一块相应位置。
class Lunbo {
constructor(element) {
// 表示接近边缘的图片 Id。接近左边缘的即第2 张图,右边缘的则为倒数第二张
this.closeLeftId = 1;
this.closeRightId = this.photos.length - 2;
this.photosQuantity = this.photos.length / 3;
// 当运动到上面两个 Id 时默默移动到的对应 Id
// 接近左边时跳转到右边块的第二张
// 接近右边则跳转到左边块的倒数第二张
this.backLeftId = this.photosQuantity - 2;
this.backRightId = this.photosQuantity * 2 + 1;
}
load(newId = parseInt(this.photos.length / 2) - 1) {
this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`;
if (newId === this.closeLeftId){
newId = this.backRightId;
} else if (newId === this.closeRightId){
newId = this.backLeftId;
} else {
this.showingId = newId;
return;
}
this.father.addEventListener("transitionend", this.backMove.bind(this, newId), {once: true});
}
backMove(newId) {
this.father.classList.add("moving");
this.father.clientWidth();
this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`;
this.father.clientWidth();
this.father.classList.remove("moving");
this.showingId = newId;
}
}
4. 整理代码
17.8.20
代码已通过测试。你需要码更多的代码,兼容各个浏览器,以及让它可以被更好地维护,然后做得更好(装)看(B)一些。
高级选项一味把放到
前只会适得其反——你需要 “加载优化” ;焦点图没有特别样式不够突出——你在想 “突出焦点” ;需要给予用户更多自主选择——去看看 “位置指示”
加载优化(重要)我们会在页面载入后看到轮播图从第一张转到焦点 —— 非常有损体验。可把一部分放到里或轮播图前,阻塞渲染。最好是提前计算 translateX 。
然后删去多余初始移动代码。
突出焦点焦点 { 放大到110% }
其他 { 半透明;正常大小 }
.focusing { opacity: 1;transform: scale3d(1.1, 1.1, 1) }
.father > div { opacity: 0.4;background: #bbb;transition: inherit; }
为Lunbo.load(newId)及backMove(newId)添加‘焦点样式更改’行
class Lunbo {
...(前后文省略)
load(newId) {
...
this.photos[showingId].classList.remove("focusing");
this.photos[newId].classList.add("focusing");
...
}
...
backMove(newId) {
this.father.classList.add("moving");
this.photos[newId].classList.add("focusing");
this.father.style.transform = `translate3d(${this.countX(newId)}px, 0, 0)`;
this.father.clientWidth;
this.father.classList.remove("moving");
this.photos[showingId].classList.remove("focusing");
this.showingId = newId;
}
...
}
位置指示 & 切换........
(在更新 ES6 之前,)这里的代码经过了测试。
1. 显示
.seter {
width: 400px;height: 20px;
position: absolute;bottom: 0;left: calc(50% - 200px);
cursor: pointer;
}
.seter > div {
width: 80px;height: 28px;
background: orange;
float: left;
} .seter > .on { margin-top: -8px;transition: margin 0.5s ease-in-out; }
函数 toSeterId 通过给予的图片 Id 计算对应的 seterId;
class Lunbo {
constructor(element) {
...
this.seters = element.children[3].children;
...
// 注册移动事件
...
element.children[3].addEventListener("click", function (event) {
if (!event.target.hasAttribute("data-seter-id")) return;
this.load(Number(event.target.getAttribute("data-seter-id")));
}.bind(this))
}
...
load(newId) {
...
this.seters[this.toSeterId(showingId)].className = "";
this.seters[this.toSeterId(newId)].className = "on";
...
}
...
toSeterId(id) {
let seterId;
if(id >= this.photosQuantity * 2) {
seterId = id - 2 * this.photosQuantity;
} else if(id >= this.photosQuantity) {
seterId = id - this.photosQuantity;
}
return seterId;
}
}
2. 可切换
每次通过指示切换时先backMove至中间块,后再进行移动;
避免从第一张晃过中间数张至最后一张(最短路径)。
// 继上文 “显示” 进一步更改
class Lunbo {
constructor(element) {
...
this.magicNumber = parseInt(this.photosQuantity / 2);
...
// 注册移动事件
...
element.children[3].addEventListener("click", function (event) {
if (!event.target.hasAttribute("data-seter-id")) return;
const newId = Number(event.target.getAttribute("data-seter-id")) + this.photosQuantity;
// 切换至中间块
this.backMove(toSeterId(showingId) + this.photosQuantity);
// 最短路径选择
if (newId > this.showingId + this.magicNumber) {
// XXXX则移至左块
this.load(newId - this.photosQuantity);
} else if (newId < this.showingId - this.magicNumber) {
// XXXX则移至右块
this.load(newId + this.photosQuantity);
} else {
// 中间块不变
this.load(newId);
}
}.bind(this))
}
...
}
(°_°ノ)
我突然知道为什么越牛的大牛会越越来越牛了 !!!∑(゚Д゚ノ)ノ
其实他们本来是想写一个文档来说明,写一个动态图演示给新手的!("▽"〃)
但是……
做完后他们一定会腰酸背痛……(;`O´)o
// 本文不再更新,除非作者开心
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/116454.html
摘要:你的网站真的需要一个轮播图吗轻轻问自己三声,谷歌一下对轮播图效果的相关调查和建议,再决定是否要着手制作你的轮播图。在接近块间距时关闭动画移至另一块相应位置。表示接近边缘的图片。可把一部分放到里或轮播图前,阻塞渲染。 showImg(https://segmentfault.com/img/bVIHHG?w=1800&h=770); 轮播图千种万种,怎样才能做出符合要求的轮播图?原理上天...
摘要:前言年月日,微信小程序发布。这也标志着的,阿里的,的小程序这三架马车在年并驱骑行。传送门试驾小程序开发工具微信开发者工具方便我们在编译时能够实时的看到界面变化,我们并不用此来进行小程序的开发,只充当一个模仪器来使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序发布。这也标志...
摘要:前言年月日,微信小程序发布。这也标志着的,阿里的,的小程序这三架马车在年并驱骑行。传送门试驾小程序开发工具微信开发者工具方便我们在编译时能够实时的看到界面变化,我们并不用此来进行小程序的开发,只充当一个模仪器来使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序发布。这也标志...
摘要:前言年月日,微信小程序发布。这也标志着的,阿里的,的小程序这三架马车在年并驱骑行。传送门试驾小程序开发工具微信开发者工具方便我们在编译时能够实时的看到界面变化,我们并不用此来进行小程序的开发,只充当一个模仪器来使用。 showImg(https://segmentfault.com/img/bVbaqpO?w=558&h=1002); 前言 2017年1月9日,微信小程序发布。这也标志...
摘要:绑定轮播事件然后是鼠标移入移出事件的绑定鼠标移入移出事件移入时停止轮播播放的定时器,移出后自动开始下一张的播放。 通过上一篇文章的学习,我们基本掌握了一个轮子的封装和开发流程。那么这次将带大家开发一个更有难度的项目——轮播图,希望能进一步加深大家对于面向对象插件开发的理解和认识。 So, Lets begin! 目前项目使用 ES5及UMD 规范封装,所以在前端暂时只支持标签的引入方式...
阅读 4170·2021-11-24 11:14
阅读 3785·2021-11-22 13:53
阅读 4244·2021-11-11 16:54
阅读 2286·2021-10-13 09:49
阅读 1564·2021-10-08 10:05
阅读 3659·2021-09-22 15:57
阅读 2057·2021-08-16 11:01
阅读 1316·2019-08-30 15:55