<!--
|
/**
|
* @description 自定义轮播组件
|
* @author huangpan
|
*/
|
-->
|
<template>
|
<div class="customCarouselModalStyle" :style="{
|
width:$setVw(carouselObj.width),
|
height:$setVw(carouselObj.height),
|
position: carouselObj.fixedPosition ? 'fixed' : 'absolute',
|
top: $setVw(carouselObj.codeY),
|
left: this.$setVw(carouselObj.codeX),
|
}">
|
<!-- 背景图片区域 -->
|
<div class="bg-pic-box" v-if="carouselObj.maxPicData.length" :style="{
|
width:$setVw(carouselObj.width * carouselObj.minPicData.length),
|
marginLeft:$setVw(-carouselObj.width * (CurrentImg))
|
}">
|
<div :style="{
|
width:$setVw(carouselObj.width),
|
height:$setVw(carouselObj.height)}" class="inner-bg-pic-box"
|
v-for="(item,index) in carouselObj.maxPicData" :key="index">
|
<img :src="item.img | ossProcess" />
|
</div>
|
</div>
|
<!-- 背景颜色区域 -->
|
<div class="bg-c-box" :style="{
|
width:$setVw(carouselObj.bgWidth),
|
height:$setVw(carouselObj.bgHight),
|
'background-image': `url(${carouselObj.bgImg}?x-oss-process=image/resize,w_750/format,jpg/quality,q_90/interlace,1)`,
|
}">
|
<div class="con-box" v-if="carouselObj.minPicData.length" :style="{
|
width:$setVw(carouselObj.bgWidth)}">
|
<div :style="{
|
width:$setVw(carouselObj.bgWidth / 3 * carouselObj.minPicData.length)}" class="bg-c-box-children"
|
ref="innerbgCBox" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd">
|
<div :style="{
|
width:$setVw(carouselObj.bgWidth / 3)}" class="inner-bg-c-box"
|
v-for="(item,index) in carouselObj.minPicData" :key="index"
|
:class="{activeImg:CurrentImg === index}">
|
<img :src="item.img | ossProcess" />
|
<div v-if="CurrentImg === index">
|
<p class="title-box">{{item.title}}</p>
|
<p class="describe-box">{{item.describe}}</p>
|
</div>
|
</div>
|
</div>
|
<div class="oper-area-style">
|
<div class="arrow-left-style" :class="{disableBtn:loop ? false : CurrentImg === 1}">
|
<van-icon name="arrow-left" @click="pre" />
|
</div>
|
<div class="center-btn-style">
|
<div>立即购买</div>
|
</div>
|
<div class="arrow-right-style"
|
:class="{disableBtn:loop ? false : CurrentImg === carouselObj.minPicData.length - 2}">
|
<van-icon name="arrow" @click="next" />
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "CustomCarouselModal",
|
props: {
|
//无限循环
|
loop: {
|
type: Boolean,
|
default: true
|
},
|
//自动播放
|
autoPlay: {
|
type: Boolean,
|
default: false
|
},
|
//自动切换的时间间隔
|
delay: {
|
type: Number,
|
default: 3000
|
},
|
//DIY配置数据源
|
infoData: {
|
type: Object,
|
required: true
|
},
|
},
|
data() {
|
return {
|
carouselObj: {},
|
CurrentImg: 1,//默认进入页面显示放大轮播图的索引
|
MoveLength: 0, //StartPoint与EndPoint的差值
|
StartPoint: 0, //触摸开始的点的横坐标
|
EndPoint: 0, //触摸结束的点的横坐标
|
timer: null,
|
}
|
},
|
watch: {
|
infoData: {
|
handler(newVal) {
|
let [minPicData, maxPicData, _data] = [[], [], {}];
|
if (newVal && Object.keys(newVal).length) {
|
minPicData = [...newVal.minPicData]
|
maxPicData = [...newVal.maxPicData]
|
}
|
if (this.loop) {
|
let [arr1, arr2] = [[], []];
|
if (minPicData.length >= 3 && maxPicData.length >= 3) {
|
const beginkThreeData1 = minPicData.slice(0, 3);
|
const endkThreeData1 = minPicData.slice(minPicData.length - 3, minPicData.length);
|
const beginkThreeData2 = maxPicData.slice(0, 3);
|
const endkThreeData2 = maxPicData.slice(maxPicData.length - 3, maxPicData.length);
|
arr1 = [...endkThreeData1, ...[...minPicData, ...beginkThreeData1]];
|
arr2 = [...endkThreeData2, ...[...maxPicData, ...beginkThreeData2]];
|
}
|
_data = Object.assign({}, newVal)
|
_data.minPicData = arr1;
|
_data.maxPicData = arr2;
|
this.CurrentImg = 4;
|
this.$nextTick(() => {
|
this.setConOffset();
|
})
|
} else {
|
_data = Object.assign({}, newVal)
|
}
|
this.carouselObj = Object.assign({}, _data);
|
},
|
deep: true,
|
immediate: true
|
},
|
},
|
created() {
|
this.toggleTimer();
|
},
|
methods: {
|
/**
|
* 开启计时器
|
*/
|
toggleTimer() {
|
let _this = this;
|
if (_this.autoPlay) {
|
_this.timer = setInterval(() => {
|
_this.next();
|
}, this.delay)
|
}
|
},
|
/**
|
* 关闭计时器
|
*/
|
clearTimer() {
|
if (this.autoPlay) {
|
clearInterval(this.timer);
|
}
|
},
|
touchStart(event) {
|
this.clearTimer();
|
//获取触摸的开始点
|
this.StartPoint = event.changedTouches[0].pageX;
|
},
|
touchMove(event) {
|
//获取触摸的结束点
|
this.EndPoint = event.changedTouches[0].pageX
|
this.MoveLength = this.StartPoint - this.EndPoint
|
},
|
touchEnd() {
|
this.jump()
|
},
|
/**
|
* 用于处理滑动到一定程度后松手自动跳转到下一张图片或上一张图片
|
*/
|
jump() {
|
this.openTransition();
|
//判断是点击还是滑动
|
if (this.StartPoint === this.EndPoint) { return }
|
//滑动超过轮播图宽度的百分之40,则跳转下一张,否则不跳转
|
if (this.MoveLength > 0) {
|
if (!this.loop && this.CurrentImg >= this.carouselObj.minPicData.length - 2) {
|
return;
|
}
|
if (this.MoveLength > this.getChildNode() * 0.4) {
|
this.nextMoveLoop();
|
this.CurrentImg++
|
this.setConOffset();
|
}
|
} else if (this.MoveLength < 0) {
|
if (!this.loop && this.CurrentImg <= 1) {
|
return;
|
}
|
if (-this.MoveLength > this.getChildNode() * 0.4) {
|
this.prevMoveLoop();
|
this.CurrentImg--
|
this.setConOffset();
|
}
|
}
|
this.toggleTimer();
|
},
|
/**
|
* 点击切换上一张
|
*/
|
pre() {
|
this.openTransition();
|
if (this.CurrentImg > 1) {
|
this.clearTimer();
|
this.prevMoveLoop();
|
this.CurrentImg--
|
this.setConOffset();
|
this.toggleTimer();
|
}
|
},
|
/**
|
* 点击切换下一张
|
*/
|
next() {
|
this.openTransition();
|
if (this.CurrentImg < this.carouselObj.minPicData.length - 2) {
|
this.clearTimer();
|
this.nextMoveLoop();
|
this.CurrentImg++
|
this.setConOffset();
|
this.toggleTimer();
|
}
|
},
|
/**
|
* 图片右滑/点击上一张箭头操作图片循环显示
|
*/
|
prevMoveLoop() {
|
let _this = this;
|
if (_this.CurrentImg === 2) {
|
setTimeout(function () {
|
_this.closeTransition()
|
_this.CurrentImg = _this.carouselObj.minPicData.length - 5;
|
_this.setConOffset();
|
}, 400)
|
}
|
},
|
/**
|
* 图片左滑/点击下一张箭头操作图片循环显示
|
*/
|
nextMoveLoop() {
|
let _this = this;
|
if (_this.CurrentImg === _this.carouselObj.minPicData.length - 3) {
|
setTimeout(function () {
|
_this.closeTransition()
|
_this.CurrentImg = 4;
|
_this.setConOffset();
|
}, 400)
|
}
|
},
|
/**
|
* 获取图片宽度
|
*/
|
getChildNode() {
|
// let _w = 0;
|
// if (this.$refs.innerbgCBox && this.$refs.innerbgCBox.children) {
|
// _w = this.$refs.innerbgCBox.children[0].offsetWidth;
|
// }
|
return this.carouselObj.bgWidth / 3;
|
},
|
/**
|
* 设置主容器偏移距离
|
*/
|
setConOffset() {
|
this.$refs.innerbgCBox.style.marginLeft = this.$setVw(-(this.CurrentImg - 1) * this.getChildNode())
|
},
|
/**
|
* 开启过渡效果
|
*/
|
openTransition() {
|
this.$refs.innerbgCBox.style.transition = "all .6s ease";
|
},
|
/**
|
* 关闭过渡效果
|
*/
|
closeTransition() {
|
this.$refs.innerbgCBox.style.transition = "none";
|
},
|
},
|
destroyed() {
|
this.clearTimer();
|
},
|
}
|
</script>
|
|
<style lang="less">
|
.customCarouselModalStyle {
|
overflow: hidden;
|
.bg-pic-box {
|
height: 100%;
|
top: 0;
|
.inner-bg-pic-box {
|
float: left;
|
> img {
|
width: 100%;
|
height: 100%;
|
object-fit: cover;
|
}
|
}
|
}
|
.bg-c-box {
|
bottom: 0;
|
background-repeat: no-repeat;
|
//对图片进行等比缩放,如有溢出部分则会被裁剪隐藏/最短边完全显示
|
background-size: cover;
|
.con-box {
|
margin: 0 auto;
|
overflow: hidden;
|
height: 440px;
|
.bg-c-box-children {
|
overflow: hidden;
|
height: 382px;
|
.inner-bg-c-box {
|
float: left;
|
margin-top: 90px;
|
> img {
|
width: 212px;
|
height: 100%;
|
object-fit: contain;
|
}
|
.title-box,
|
.describe-box {
|
color: #fff;
|
text-align: center;
|
overflow: hidden;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
-o-text-overflow: ellipsis;
|
font-size: 24px;
|
}
|
.describe-box {
|
transform: scale(0.8);
|
}
|
}
|
.activeImg {
|
transform: scale(1.2);
|
margin-top: 50px;
|
}
|
}
|
}
|
.oper-area-style {
|
overflow: hidden;
|
> div {
|
width: 33%;
|
float: left;
|
margin: 0 auto;
|
text-align: center;
|
color: #fff;
|
}
|
.center-btn-style {
|
font-size: 12px;
|
> div {
|
border: 1px solid #fff;
|
width: 150px;
|
height: 35px;
|
line-height: 35px;
|
margin: 0 auto;
|
}
|
}
|
.arrow-left-style > i,
|
.arrow-right-style > i {
|
font-size: 36px;
|
}
|
.disableBtn > i {
|
opacity: 0.35;
|
}
|
}
|
}
|
.bg-pic-box,
|
.bg-c-box {
|
position: absolute;
|
left: 0;
|
}
|
}
|
</style>
|