切割轮播图,详解
今天写一个 切割轮播图,我这里是基于vue.js的。
首先,新建一个vue.js的项目,我这里就不多说了。因为我们用的是jQuery,这里我们第一步需要实现的是在vue项目中使用jQuery。(完整代码在最后)
效果图如下:
1> 在控制台输入 cnpm i jquery --save
或者 npm i jquery --save
,添加相应的依赖。
2>这时我们就要修改配置文件了
- webpack.base.conf.js 文件
在文件头部添加const webpack = require('webpack')
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
// 添加 1
'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery')
}
},
// 添加 2
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery'
})
],
3> 如果你的项目使用了严格模式,在 .eslintrc.js 文件添加jquery: true
,如果没有启用严格模式,就不需要了。
env: {
browser: true,
// 添加
jquery: true
},
4>在 main.js 文件中 引用jQuery,就可以全局使用jQuery了,添加代码 import 'jquery'
我们现在使用一下jQuery,看看有效果没。
启动项目,F12 检查元素,成功。
现在我们构建切割轮播图的页面结构。
先看看要实现的效果
代码实现如下:
/* 设置宽度为400px,高度为300px */
.view {
width: 400px;
height: 300px;
}
.view li {
width: 20%;/* 让每个li 继承父节点的 20% */
height: 100%;
list-style: none; /* 去掉li前面的小圆点样式 */
float: left; /* 因为li是块级元素,要让每个li在一行显示才能拼成一张完整的图片 */
}
.view li span {
/* 让每个li下面的span继承父亲的宽高,并且使用绝对定位 */
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
因为 span中使用了绝对定位,所以要在父亲节点(.view li
),加上 position: relative;
这时,我们就可以加图片了,对新手来说,比较难理解的是每个图片的位置该怎么放。
.view li span:nth-child(1) {
background: url("../assets/1.jpg") no-repeat;
}
.view li span:nth-child(2) {
background: url("../assets/2.jpg") no-repeat;
}
.view li span:nth-child(3) {
background: url("../assets/3.jpg") no-repeat;
}
.view li span:nth-child(4) {
background: url("../assets/4.jpg") no-repeat;
}
上面这段代码写完,四张图片是重贴在一起的,先看看此时的效果图。
而且我们还发现,每个图片只显示了前面的20%,重复显示了5次。
我们先解决上面这个问题,先让图片显示完整再说。
为啥会出现上面的这种情况呢?
结合我们上面写好的代码,每个 li 的宽度,占了整个父节点(view)宽度的 20%,每个 span 的宽高继承了父节点(li)的100%,所以每个 span 的背景图片也只能显示前面的 20%。
怎么解决
分析一下,既然每个图片只显示前面的20%,那我们让第二个 li 中的 span 的背景图片 往前移动 20%的距离,让第三个 li 中的 span 的背景图片往前移动40%的距离,以此类推,后面的几个同理。这样刚刚可以拼出一张完整的图片。
.view li:nth-child(1) span {
background-position: 0 0;
}
.view li:nth-child(2) span {
background-position: -80px 0;
}
.view li:nth-child(3) span {
background-position: -160px 0;
}
.view li:nth-child(4) span {
background-position: -240px 0;
}
.view li:nth-child(5) span {
background-position: -320px 0;
}
这时,一张完整的图片就可以显示了。
下面我们要让每张图片放在该放的位置。这是想要的效果
.view li span:nth-child(1) {
background: url("../assets/1.jpg") no-repeat;
/* 第一张图往前走(Z轴正方向)图片高度的一半 */
transform: translateZ(150px);
}
.view li span:nth-child(2) {
background: url("../assets/2.jpg") no-repeat;
/* 第二张图片往下走(Y轴正方向)150px,沿着x轴逆时针转90度 */
transform: translateY(150px) rotateX(-90deg);
}
.view li span:nth-child(3) {
background: url("../assets/3.jpg") no-repeat;
/* 第三张图片往后走(Z轴负方向)150px,并且让图片反转180度,为的是,当这张图片翻到前面时,图片是正的 */
transform: translateZ(-150px) rotateX(180deg);
}
.view li span:nth-child(4) {
background: url("../assets/4.jpg") no-repeat;
/* 第四张图往上走(Y轴负方向)150px,沿x轴顺时针转90度 */
transform: translateY(-150px) rotateX(90deg);
}
为了 实现3D效果,我们要在 .view li 中 添加 transform-style: preserve-3d;
这句话的意思是让其子元素按照3d效果显示。
我们在 .view中添加 transform-style: preserve-3d; transform: rotate3d(1,1,0,-30deg);
打开页面我们可以看到这个效果。看完之后就可以删了。
图片比较花哨,有点看不清。。。不过还是可以看出来,是一个长方体。四张图片在前、下、后、上四个面,左右两边是空的。下面开始做按钮操作:
在 li 下面添加:
.pre,
.next{
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 30px;
line-height: 30px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
.pre {
left: 0;
}
.next {
right: 0;
}
因为在 a 标签中加了 position: absolute; 所以要在父节点(view)中 添加 position: relative;
到此,样式全部写完了。
下面重头戏开始了。
$(function () {
/* 点击左边按钮 */
$('.pre').on('click', function () {
/* 遍历每一个li,让其逆时针按X轴旋转90度 */
$('li').each(function (key, value) { // key: 0 1 2 3 4
$(this).css({
'transform': 'rotateX(-90deg)'
})
})
})
})
这时点击左边的切换按钮,就可以实现切换图片了,但是发现,图片一闪而过,并没有有一个过渡效果。因为我们还没加啊。
这时我们给 li 添加过渡。在 .view li 中 添加 transition: all 0.6s
再去点击,就有过渡效果,但是还不是我们想要的。
我们要的是每个 li 一个接一个旋转90度。
添加代码:
让每个 li 延迟0…1s
这时点击就会有每个 看到了我们的 要的效果。但此时,只能点击一次,点击第二次就没有作用了。因为我们把,li 的旋转角度给写死了。把旋转角度改成动态的就OK了。修改代码如下:
这时左边的按钮就已经完成了。大功告成,。。。错了,不知道你们有没有发现一个bug,当你快速点击时,轮播图就出现紊乱,我们想要的效果是,当前这次轮播图还没有播放完成,点击按钮不生效。这时,我们要给它加个节流阀。也就是一个开关。
如果 flag 为 true,则进入到 if 条件语句中,执行轮播图播放效果,并把 flag 设置为 false 。那什么时候让 flag 又变回 true 呢??我们给个定时器,因为 每个 li 我们给它延时了 100ms,所以我们给定时器的时间设置为 500ms,只有 500ms过了之后,点击才会有效。
这回,你再去点击,就正常了。那么,右边按钮,和左边同理,只需要把 index-- 改成 index++。
最后,附上完整代码。
<template>
<div class="view">
<li>
<span></span>
<span></span>
<span></span>
<span></span>
</li>
<li>
<span></span>
<span></span>
<span></span>
<span></span>
</li>
<li>
<span></span>
<span></span>
<span></span>
<span></span>
</li>
<li>
<span></span>
<span></span>
<span></span>
<span></span>
</li>
<li>
<span></span>
<span></span>
<span></span>
<span></span>
</li>
<a class="pre">《 </a>
<a class="next"> 》</a>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {}
},
mounted () {
$(function () {
let index = 0
/* 设置节流阀 */
let flag = true
/* 点击左边按钮 */
$('.pre').on('click', function () {
if (flag) {
flag = false
index--
/* 遍历每一个li,让其逆时针按X轴旋转90度 */
$('li').each(function (key, value) { // key: 0 1 2 3 4
$(this).css({
'transform': 'rotateX(' + (index * 90) + 'deg)',
'transition-delay': key * 0.1 + 's'
})
})
setTimeout(function () {
flag = true
}, 500)
}
})
/* 点击右边按钮 */
$('.next').on('click', function () {
if (flag) {
flag = false
index++
/* 遍历每一个li,让其顺时针按X轴旋转90度 */
$('li').each(function (key, value) { // key: 0 1 2 3 4
$(this).css({
'transform': 'rotateX(' + (index * 90) + 'deg)',
'transition-delay': key * 0.1 + 's'
})
})
setTimeout(function () {
flag = true
}, 500)
}
})
})
}
}
</script>
<style scoped>
/* 设置宽度为400px,高度为300px */
.view {
margin: 100px auto;
width: 400px;
height: 280px;
/*transform-style: preserve-3d;*/
/*transform: rotate3d(1,1,0,-30deg);*/
position: relative;
}
/* 让每个li 继承父节点的 20% */
.view li {
width: 20%;
height: 100%;
list-style: none;
float: left;
position: relative;
transform-style: preserve-3d;
transition: all 0.6s;
}
.view li span {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.view li span:nth-child(1) {
background: url("../assets/1.jpg") no-repeat;
transform: translateZ(140px);
}
.view li span:nth-child(2) {
background: url("../assets/2.jpg") no-repeat;
transform: translateY(140px) rotateX(-90deg);
}
.view li span:nth-child(3) {
background: url("../assets/3.jpg") no-repeat;
transform: translateZ(-140px) rotateX(180deg);
}
.view li span:nth-child(4) {
background: url("../assets/4.jpg") no-repeat;
transform: translateY(-140px) rotateX(90deg);
}
.view li:nth-child(1) span {
background-position: 0 0;
}
.view li:nth-child(2) span {
background-position: -80px 0;
}
.view li:nth-child(3) span {
background-position: -160px 0;
}
.view li:nth-child(4) span {
background-position: -240px 0;
}
.view li:nth-child(5) span {
background-position: -320px 0;
}
.pre,
.next{
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 30px;
line-height: 30px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
.pre {
left: 0;
}
.next {
right: 0;
}
</style>
最最后,给一个项目链接,美滋滋!