<template>
<div class="imgCarouselWrap" ref="imgCarouselWrap" :style="{height: height + ‘px‘, width: width + ‘px‘}">
<div class="bigImgWrap">
<el-carousel ref="elCarousel" @change="cardChange" indicator-position="none" :autoplay="false" :height="wrapHeight">
<div class="disableSelectLeft" v-show="!toSelectLeft"></div>
<div class="disableSelectRight" v-show="!toSelectRight"></div>
<el-carousel-item v-for="(item, index) in imgUrls" :key="index+‘img‘">
<div class="imgItemWrap">
<img class="imgItem" :src="item" alt="alt">
</div>
</el-carousel-item>
</el-carousel>
</div>
<div class="smallImgWrap">
<div class="viewWidth">
<div class="smallImgGroup" :style="{width: smallImgGroupWidth,transition: ‘all 0.4s ease‘,transform:smallImgTranslateX}">
<div
@click="selectImg(index)"
class="smallImg" :class="{isSelected: index === currentIndex}"
v-for="(item, index) in imgUrls" :key="index + ‘smallimg‘">
<img class="smallImgItem" :src="item" alt="alt">
</div>
</div>
</div>
<button
v-if="imgUrls.length > Math.floor(maxViewImgNum)"
@click="toLeftImg()"
class="smallArrow el-carousel__arrow" style="left:0"
:class="{noDrop: noDropLeft}"><i class="el-icon-arrow-left"></i></button>
<button
v-if="imgUrls.length > Math.floor(maxViewImgNum)"
@click="toRightImg()"
class="smallArrow el-carousel__arrow" style="right:0"
:class="{noDrop: noDropRight}"><i class="el-icon-arrow-right"></i></button>
</div>
</div>
</template>
<script>
export default {
data () {
return {
// 主图右箭头
rightArrow: null,
// 主图左箭头
leftArrow: null,
// 主图左侧是否可以选择移动
toSelectLeft: true,
// 主图右侧是否可以选择移动
toSelectRight: true,
// 选择图组当前图索引
currentIndex: 0,
// 选择图组的可视区域宽度
imgViewWidth: 0,
// 选择图片的宽度
smallImgWidth: 75,
// 选择图片的宽度
smallImgheight: 75,
// margin
marginVal: 5,
// 选择图组 左偏移量
moveLeftNum: 0,
// 选择图组 右偏移量
moveRightNum: 0,
// 选择图组的样式
smallImgTranslateX: ‘translateX(0)‘,
// 选择图组的左是否可移动
noDropLeft: false,
// 选择图组的右是否可移动
noDropRight: false
}
},
props: {
// 图片加载失败的提示
alt: {
type: String
},
// 点击图片左右箭头是否首位循环
isLoops: {
type: Boolean,
default: false
},
// 图片url,必须先使用require或import加载
imgUrls: {
type: Array,
required: true
},
// 组件高度
height: {
type: String,
required: true
},
// 组件宽度
width: {
type: String,
required: true
}
},
computed: {
/**
* @author lizhiwei8
* @date 2019/01/25
* @desc 主图高度
* 80 为选择图的固定高度 75 加marginTop 5
*/
wrapHeight: function () {
return (this.height - this.smallImgheight - this.marginVal) + ‘px‘
},
// 主图宽度
wrapWidth: function () {
return this.width + ‘px‘
},
// 选择图group宽度计算
smallImgGroupWidth: function () {
return this.imgUrls.length * this.smallImgWidth + ‘px‘
},
// 可视区域显示选择图数量
maxViewImgNum: function () {
return this.imgViewWidth / this.smallImgWidth
}
},
methods: {
/**
* @author lizhiwei8
* @date 2019/01/25
* @desc 监听主图切换
*/
cardChange (cur, pre) {
// 控制滑动箭头是否显示
if (!this.isLoops) {
if (this.imgUrls.length <= 1) {
this.toSelectLeft = false
this.toSelectRight = false
// this.rightArrow.style.visibility = ‘hidden‘
// this.leftArrow.style.visibility = ‘hidden‘
} else {
if (cur === this.imgUrls.length - 1) {
this.toSelectRight = false
// this.rightArrow.style.visibility = ‘hidden‘
} else if (cur === 0) {
this.toSelectLeft = false
// this.leftArrow.style.visibility = ‘hidden‘
} else {
this.toSelectLeft = true
this.toSelectRight = true
// this.rightArrow.style.visibility = ‘visible‘
// this.leftArrow.style.visibility = ‘visible‘
}
}
// 选择小图和主图对应
this.currentIndex = cur
this.autoChangeGroup(cur, pre)
}
},
/**
* @author lizhiwei8
* @date 2019/01/24
* @desc 自动切换
* 联动:通过主图左右切换带动小图左右移动
* 手动:通过小图选择带动小图和主图移动
* 中间小图可选区域为可视区域
* 可视区域有左右边界
* 可是区域左右两侧不可见小图为不可见区域
* index:当前索引
* pre:上一个图片索引
*/
autoChangeGroup (index, pre) {
let smallImgWidth = this.smallImgWidth
// 当切换时控制选择图组,如果是右侧最后一个则自动移动选择图组到下一组
let leftImgNum = Math.abs(this.moveLeftNum) / smallImgWidth // 左侧已经移动的数量
let maxViewImg = Math.ceil(this.maxViewImgNum) // 当前可视区域显示的最大数量
let lastViewImg = leftImgNum + maxViewImg - 1 // 可视区域最后一个的索引
// 右侧边界向右移动(手动/联动),切换到下一组
// 若果是最右侧手动点击或则最右侧从左向右切图的项则自动向左移动一组
if ((index === lastViewImg && pre === undefined) || (index === lastViewImg && pre < index)) {
this.toLeftImg((maxViewImg - 1) * smallImgWidth)
}
// 右侧边界向左移动-联动,切换到上一组,向左移动一个单位
if (index === lastViewImg && pre > index) {
this.toLeftImg()
}
// 右侧不可见向左移动-联动
if (index > lastViewImg && pre > index) {
this.toLeftImg((index - lastViewImg) * smallImgWidth)
}
// 右侧不可见向右移动-联动
if (index > lastViewImg && pre < index) {
this.toLeftImg((index - leftImgNum) * smallImgWidth)
}
// 左侧边界向左移动
if (index === leftImgNum - 1 && pre > index) {
if (leftImgNum < maxViewImg) {
this.toRightImg(leftImgNum * smallImgWidth)
} else {
this.toRightImg((maxViewImg - 1) * smallImgWidth)
}
}
// 左侧不可见向左移动-联动
if (index < leftImgNum && pre > index) {
if (index < maxViewImg) {
this.toRightImg((lastViewImg - (maxViewImg - 1)) * smallImgWidth)
} else {
this.toRightImg((lastViewImg - index) * smallImgWidth)
}
}
// 左侧不可见向右移动-联动
if (index < leftImgNum && pre < index) {
if (leftImgNum < maxViewImg) {
this.toRightImg((lastViewImg - (maxViewImg - 1)) * smallImgWidth)
} else {
this.toRightImg((leftImgNum - index) * smallImgWidth)
}
}
},
// 禁止移动选择图条
forbidMove () {
if (this.moveLeftNum === 0) {
this.noDropRight = true
} else {
this.noDropRight = false
}
// 可视图数量,小数
let maxViewImg = Math.floor(this.maxViewImgNum)
let imgUrlsLen = this.imgUrls.length
if (imgUrlsLen <= maxViewImg) {
this.noDropLeft = true
} else {
let residue = imgUrlsLen - Math.abs(this.moveLeftNum) / this.smallImgWidth
if (residue <= maxViewImg) {
this.noDropLeft = true
} else {
this.noDropLeft = false
}
}
},
// 选择图左移
// moveWidth 在已有位置上待移动量
toLeftImg (moveWidth = this.smallImgWidth) {
// 禁止移动
if (this.noDropLeft) return
if (this.moveRightNum > 0) {
this.moveRightNum -= moveWidth
this.moveLeftNum = this.moveRightNum
} else {
this.moveLeftNum -= moveWidth
}
this.smallImgTranslateX = ‘translateX(‘ + this.moveLeftNum + ‘px)‘
this.forbidMove()
},
// 选择图右移
// moveWidth 在已有位置上待移动量
toRightImg (moveWidth = this.smallImgWidth) {
// 禁止移动
if (this.noDropRight) return
if (this.moveLeftNum < 0) {
this.moveLeftNum += moveWidth
this.moveRightNum = this.moveLeftNum
} else {
this.moveRightNum += moveWidth
}
this.smallImgTranslateX = ‘translateX(‘ + this.moveRightNum + ‘px)‘
this.forbidMove()
},
// 手动选择图片
selectImg (index) {
this.autoChangeGroup(index)
this.$refs.elCarousel.setActiveItem(index)
},
// 获取dom节点信息
getDomInfo () {
// 主图的左右切换箭头
this.rightArrow = this.$refs.imgCarouselWrap.getElementsByClassName(‘el-carousel__arrow--right‘)[0]
this.leftArrow = this.$refs.imgCarouselWrap.getElementsByClassName(‘el-carousel__arrow--left‘)[0]
// 获取选择图组的可视区域宽度
this.imgViewWidth = this.$refs.imgCarouselWrap.getElementsByClassName(‘viewWidth‘)[0].clientWidth
}
},
mounted () {
this.forbidMove()
this.getDomInfo()
}
}
</script>
<style lang="less">
.imgCarouselWrap{
width: 100%;
height: 100%;
.bigImgWrap{
overflow: hidden;
}
.smallImgWrap {
height:70px;
margin-top:10px;
position: relative;
padding: 0 20px;
.viewWidth{
overflow: hidden;
margin-right: 5px;
}
.smallImgGroup{
height: 70px;
width: 1000px;
}
.smallImg{
height: 70px;
width: 70px;
margin-left: 5px;
overflow: hidden;
text-align: center;
float: left;
position: relative;
cursor: pointer;
&.isSelected{
border: 3px solid #FFCD00;
}
.smallImgItem{
height: 100%;
position: absolute;
left: 50%;
transform: translateX(-50%);
// &:hover{
// transform: translateX(-50%) scale(1.2);
// }
}
}
.smallArrow{
width: 20px;
}
.smallArrow.noDrop i{
cursor: no-drop;
}
.smallArrow.noDrop{
cursor: no-drop;
}
}
.el-carousel__arrow--right {
right: 0;
}
.el-carousel__arrow--left {
left: 0;
}
.el-carousel__arrow{
border-radius: 0;
height: 70px;
width: 30px;
font-size: 20px;
}
.imgItemWrap{
height:100%;
text-align:center;
.imgItem{
height:100%;
}
}
.disableSelectLeft,.disableSelectRight{
height: 70px;
width: 30px;
position: absolute;
top: 50%;
z-index: 20;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
cursor: no-drop;
}
.disableSelectRight{
right:0;
}
.disableSelectLeft{
left:0;
}
}
</style>
/// 调用
<template>
<page-container :breadcrumb="i18nBreadcrumb" :headerNonShadow="true" :nonSpacing="true">
<page-card>
<img-carousel width="600" height="500" :imgUrls="imgUrls"></img-carousel>
</page-card>
</page-container>
</template>
<script>
// import imgCar1 from ‘./imgCarouseldiv1‘
import imgCarousel from ‘./imgCarouseldiv2‘
export default({
props: {
breadcrumbObj: {
type: Object,
debufult: {}
}
},
components: {
imgCar1,
imgCarousel
},
data () {
return {
imgUrls: [
require(‘./image/1.jpg‘),
require(‘./image/2.jpg‘),
require(‘./image/3.jpg‘),
require(‘./image/4.jpg‘),
require(‘./image/5.jpg‘),
require(‘./image/6.jpg‘),
require(‘./image/7.jpg‘),
require(‘./image/8.jpg‘),
require(‘./image/9.jpg‘),
require(‘./image/10.jpg‘),
require(‘./image/11.jpg‘),
require(‘./image/12.jpg‘),
require(‘./image/13.jpg‘),
require(‘./image/14.jpg‘),
require(‘./image/15.jpg‘),
require(‘./image/16.jpg‘),
require(‘./image/17.jpg‘),
require(‘./image/18.jpg‘),
require(‘./image/19.jpg‘),
require(‘./image/20.jpg‘),
require(‘./image/21.jpg‘),
require(‘./image/22.jpg‘),
require(‘./image/23.jpg‘),
require(‘./image/24.jpg‘),
require(‘./image/25.jpg‘),
require(‘./image/26.jpg‘),
require(‘./image/27.jpg‘)
]
}
}
})
</script>
<style scoped>
</style>