<template>
<div class="goods-swiper-box" :style="{ width: boxWidth + 'px' }">
<div
class="image-box"
:style="{
width: boxWidth + 'px',
height: boxHeight + 'px',
}"
>
<van-swipe
class="swiper"
:autoplay="autoPlayFlag ? '' : 3000"
@change="bigImgChange"
:show-indicators="false"
ref="topImageSwiper"
>
<van-swipe-item
class="inner-image-box"
:style="{
width: boxWidth + 'px',
height: boxHeight + 'px',
}"
v-for="(item, index) in imageList || ['', '']"
:key="item.picID"
>
<div
class="image-box-inner"
:class="'box-image' + index"
:key="item.picID"
:style="{
height: boxHeight + 'px',
'line-height': boxHeight + 'px',
}"
>
<img
:src="item.picUrl"
:class="'image' + index"
alt=""
:ref="'midelImg' + index"
@mouseover="handOver"
@mouseout="handOut"
/>
</div>
</van-swipe-item>
</van-swipe>
<div
v-show="showMoveBox"
class="swiper-shadow"
:style="{
width: boxWidth + 'px',
height: boxHeight + 'px',
}"
>
<div
class="swiper-img-box"
:style="bigBoxStyle"
@mousemove="handMove"
@mouseover="handOver"
@mouseout="handOut"
>
<img :src="activeImgUrl" alt="" :style="bigBoxStyle" />
<div
class="shadow"
:style="shandowStyle"
@click="showImagePrivew"
></div>
<div class="top-btn top-prev">
<img src="@/assets/image/back.png" alt="" @click="topChange(-1)" />
</div>
<div class="top-btn top-next">
<img src="@/assets/image/next.png" alt="" @click="topChange(1)" />
</div>
</div>
</div>
<div
v-show="showMoveBox"
class="big-image-box"
:style="{
width: boxWidth + 'px',
height: boxHeight + 'px',
}"
>
<div class="inner-big-box" :style="bigBoxStyle">
<img
:src="activeImgUrl"
alt=""
:style="{ ...bigImgStyle, ...moveBigStyle }"
class=""
/>
</div>
</div>
</div>
<div class="imgTip" :style="{ width: boxWidth + 'px' }">
{{
showMoveBox
? $t("detailPage.afterMoveTip")
: $t("detailPage.beforeMoveTip")
}}
</div>
<div class="small-image-box">
<a-icon
class="bottom-btn bottom-prev"
type="left"
:style="{
height: boxHeight / smallMultiple + 'px',
lineHeight: boxHeight / smallMultiple + 'px',
}"
@click="smallImgChange(-1)"
/>
<swiper
class="swiper"
:options="swiperOption"
ref="bottomImageSwiper"
:style="{
height: boxHeight / smallMultiple + 'px',
width: boxWidth - 100 + 'px',
}"
>
<swiper-slide
v-for="(item, index) in imageList || ['', '']"
:key="item.picID"
:class="activeIndex == index ? 'small-img-active' : ''"
>
<img alt="" :src="item.picUrl" @click="jumpImage(index)" />
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
<a-icon
class="bottom-btn bottom-next"
@click="smallImgChange(1)"
:style="{
height: boxHeight / smallMultiple + 'px',
lineHeight: boxHeight / smallMultiple + 'px',
}"
type="right"
/>
</div>
</div>
</template>
<script>
import { Carousel } from "ant-design-vue";
import swiperMixins from "./swiper-mixin";
export default {
mixins: [swiperMixins],
components: {
"a-carousel": Carousel,
},
};
</script>
<style lang="scss" scoped>
.goods-swiper-box {
.image-box {
background-color: #fff;
position: relative;
.swiper-shadow {
background-color: #fff;
position: absolute;
top: 0;
left: 0;
z-index: 90;
&:hover .top-btn {
display: block;
}
.top-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
display: none;
z-index: 91;
}
.top-next {
right: 0;
}
.swiper-img-box {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
.shadow {
position: absolute;
background-color: gray;
opacity: 0.4;
z-index: 91;
top: 0;
left: 0;
width: 100px;
height: 100px;
}
img {
height: 100%;
width: 100%;
}
}
}
.inner-image-box {
display: flex;
border-radius: 8px;
overflow: hidden;
justify-content: center;
align-content: center;
background-color: #fff;
.image-box-inner {
position: absolute;
height: auto;
img {
width: auto;
height: auto;
max-height: 100%;
max-width: 100%;
}
}
}
.big-image-box {
position: absolute;
left: 105%;
top: 0;
display: flex;
z-index: 999;
justify-content: center;
align-content: center;
overflow: hidden;
.inner-big-box {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
overflow: hidden;
img {
position: absolute;
}
}
}
}
.imgTip {
line-height: 32px;
margin: 10px 0;
text-align: center;
width: 566px;
}
.small-image-box {
width: 100%;
display: flex;
justify-content: space-between;
align-content: center;
.bottom-btn {
width: 50px;
text-align: center;
}
.small-img-active {
border: 1px solid #333;
border-radius: 4px;
}
::v-deep .swiper-slide {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
img {
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
}
}
}
</style>
export default {
props: {
boxWidth: {
type: Number,
default:566
},
boxHeight: {
type: Number,
default:566
},
imageList: {
type: Array,
default: () => {
return [
{
altPmt: "",
picID: "vueTest/1/produce-image_69f8c9a6-61c1-43e7-9456-234a2c6b2839_173031x.png",
picUrl: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202002%2F09%2F20200209191658_jmu8V.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1653210861&t=d6141f92fa3f93e6baeab3372266389f",
thnUrl: "",
},
{
altPmt: "",
picID: "vueTest/1/produce-image_69f8c9a6-61",
picUrl: "https://sqbucket-us.oss-us-west-1.aliyuncs.com/vueTest/1/produce-image_116b3911-0f27-4894-821f-940088ba0ea7_173031x.png",
thnUrl: "",
},
{
altPmt: '',
picUrl: 'https://w.wallhaven.cc/full/j3/wallhaven-j379gy.png',
thnUrl: "",
picID: 2
},
{
altPmt: '',
picUrl: 'http://sqbucket-us.oss-us-west-1.aliyuncs.com/vueTest/1/produce-image_dd9c2786-459e-4904-bb12-f9f5507665b4_139686x.png',
thnUrl: "",
picID: 3
}, {
altPmt: '',
picUrl: 'http://sqbucket-us.oss-us-west-1.aliyuncs.com/vueTest/1/produce-image_73293336-fca8-4b67-9dee-253bd189a087_121645x.png',
thnUrl: "",
picID: 4
}
]
}
},
multiple: {
type: Number,
default:2
},
smallMultiple: {
type: Number,
default:5
},
smallPosition: {
type: String,
default:'bottom'
},
swiperOption: {
type: Object,
default: () => {
return {
slidesPerView: 4,
loop: false,
spaceBetween: 16,
prevButton: ".swiper-button-prev",
nextButton: ".swiper-button-next",
on: {
click: function (index) {
}
}
}
}
},
},
data() {
return {
swiperOptionTop: {
spaceBetween: 30,
centeredSlides: true,
autoplay: {
delay: 2500,
disableOnInteraction: false
},
pagination: {
el: '.swiper-pagination',
clickable: true
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
},
loop:true
},
activeIndex: 0,
autoPlayFlag: false,
activeImgUrl: "",
showMoveBox: false,
shandowStyle: {
width: '283px',
height: '283px',
transform: null,
x: 283,
y:283,
},
bigBoxStyle: {
width: '566px',
height:'566px',
},
bigImgStyle: {
width: '1132px',
height:'1132px',
},
initPlace: null,
outPlace:null,
moveBigStyle: {
top: 0,
left: 0,
},
timer: null,
imageLeftPosition: 0,
imageEndPosition: 0,
ratio: 1,
l:0,
}
},
watch: {
},
created () {
this.activeImgUrl = this.imageList[this.activeIndex].picUrl;
},
methods: {
handMove(e) {
this.initPlace = this.$el.getElementsByClassName('swiper-img-box')[0].getBoundingClientRect();
let objX = e.clientX - this.initPlace.left;
let objY = e.clientY - this.initPlace.top;
let maskX = objX - this.shandowStyle.x/this.multiple;
let maskY = objY - this.shandowStyle.y/this.multiple;
maskY = maskY < 0 ? 0 : maskY;
maskX = maskX <0 ? 0 : maskX;
if (maskY + this.shandowStyle.y >= this.initPlace.height) {
maskY = this.initPlace.height - this.shandowStyle.y;
}
if (maskX + this.shandowStyle.x >= this.initPlace.width) {
maskX = this.initPlace.width - this.shandowStyle.x
}
this.shandowStyle.transform = `translate(${maskX}px, ${maskY}px)`;
this.moveBigStyle.left = - maskX * this.multiple + "px";
this.moveBigStyle.top = - maskY * this.multiple +"px";
},
handOut() {
this.showMoveBox = false;
this.autoPlayFlag = false;
},
handOver() {
this.getWidthAndHeight();
this.showMoveBox = true;
this.autoPlayFlag = true;
},
bigImgChange(index) {
this.activeIndex = index;
this.activeImgUrl = this.imageList[this.activeIndex].picUrl;
},
getWidthAndHeight() {
this.ratio = this.$refs['midelImg' + this.activeIndex][0].naturalWidth / this.$refs['midelImg' + this.activeIndex][0].naturalHeight;
let width = 0, height = 0;
if (this.ratio == this.boxWidth/this.boxHeight) {
height = this.boxHeight;
width = this.boxWidth;
} else if (this.ratio < this.boxWidth/this.boxHeight) {
height = this.boxHeight;
width = this.boxHeight * this.ratio;
} else {
height = this.boxWidth / this.ratio;
width = this.boxWidth;
}
this.bigBoxStyle = {
width:width+'px',
height:height+"px"
}
this.shandowStyle = {
width:width/this.multiple+'px',
height:height/this.multiple + "px",
transform: null,
x: width/this.multiple,
y:height/this.multiple
},
this.bigImgStyle = {
width: width * this.multiple + 'px',
height:height*this.multiple+'px'
}
},
topChange(val) {
if (val == -1) {
this.$refs.topImageSwiper.prev()
} else {
this.$refs.topImageSwiper.next()
}
},
smallImgChange(val) {
if (val == -1) {
this.$refs.bottomImageSwiper.$swiper.slidePrev()
} else {
this.$refs.bottomImageSwiper.$swiper.slideNext()
}
},
jumpImage(index) {
this.activeIndex = index;
this.$refs.topImageSwiper.swipeTo(index)
},
showImagePrivew() {
this.$emit('showImagePrivew', this.activeIndex)
}
}
}