Vue轮播缩略图(element ui)+鼠标悬浮放大图片(PicZoom)商城详情页图片展示
效果:PicZoom.vue(图片放大组件)<template><divclass="magnifier-box":class="vertical?'vertical':''":ref="id"@mousemove="mousemove"@mouseover="mouseover"@mouseleave="mouseleave"><img v-show="showIm
·
效果:
PicZoom.vue(图片放大组件)
<template>
<div
class="magnifier-box"
:class="vertical?'vertical':''"
:ref="id"
@mousemove="mousemove"
@mouseover="mouseover"
@mouseleave="mouseleave"
>
<img v-show="showImg" :src="imgUrl" alt />
<div class="mouse-cover"></div>
<img :src="bigImage" class="big-image" v-show="showImage" />
</div>
</template>
<script>
export default {
props: {
scale: {
type: Number,
default: 2.5
},
url: {
type: String,
required: true
},
bigUrl: {
type: String,
default: null
},
scroll: {
type: Boolean,
default: false
},
showEidt: {
type: Boolean,
default: false
}
},
data() {
return {
bigImage: null,
showImage: null,
id: null,
cover: null,
imgbox: null,
imgwrap: null,
orginUrl: null,
bigImgUrl: null,
bigOrginUrl: null,
imgUrl: null,
img: null,
canvas: null,
ctx: null,
rectTimesX: 0,
rectTimesY: 0,
imgTimesX: 0,
imgTimesY: 0,
init: false,
step: 0,
bigStep: 0,
vertical: false,
showImg: true
};
},
created() {
var $chars =
"ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
var maxPos = $chars.length;
var str = "";
for (let i = 0; i < 10; i++) {
str += $chars.charAt(Math.floor(Math.random() * maxPos));
}
this.id = str;
this.imgUrl = this.url;
this.orginUrl = this.url;
this.bigImgUrl = this.bigUrl;
this.bigOrginUrl = this.bigUrl;
},
watch: {
url: function(val) {
this.imgUrl = val;
this.orginUrl = val;
this.initTime();
},
bigUrl: function() {
this.bigImgUrl = bigUrl;
this.bigOrginUrl = bigUrl;
this.initTime();
}
},
mounted() {
this.$nextTick(() => {
this.initTime();
});
},
methods: {
initTime() {
this.init = false;
let box = this.$refs[this.id];
this.imgbox = box;
this.cover = box.querySelector(".mouse-cover");
this.cover.style.width = this.imgbox.offsetWidth / this.scale + "px";
this.cover.style.height = this.imgbox.offsetHeight / this.scale + "px";
this.cover.style.left = "-100%";
this.cover.style.top = "-100%";
this.imgwrap = box.querySelector("img");
let imgsrc;
if (this.bigImgUrl) {
imgsrc = this.bigImgUrl;
} else {
imgsrc = this.imgUrl;
}
this.img = new Image();
this.img.src = imgsrc;
this.img.onload = () => {
(this.rectTimesX =
this.imgbox.offsetWidth / this.scale / this.imgwrap.offsetWidth),
(this.rectTimesY =
this.imgbox.offsetHeight / this.scale / this.imgwrap.offsetHeight);
(this.imgTimesX = this.img.width / this.imgwrap.offsetWidth),
(this.imgTimesY = this.img.height / this.imgwrap.offsetHeight);
this.vertical = this.img.width < this.img.height;
this.init = true;
};
if (this.canvas) {
this.canvas = null;
}
this.canvas = document.createElement("canvas");
this.canvas.className = "mouse-cover-canvas";
this.canvas.style.position = "absolute";
this.canvas.style.left = this.imgbox.offsetLeft + this.imgbox.offsetWidth + 10 + "px";
this.imgbox.offsetLeft + this.imgbox.offsetWidth + 10 + "px";
this.canvas.style.top = this.imgbox.offsetTop + "px";
this.canvas.style.border = "1px solid #eee";
this.canvas.style.zIndex = "99999";
this.canvas.height = this.imgbox.offsetHeight;
this.canvas.width = this.imgbox.offsetWidth;
this.canvas.style.display = "none";
// document.body.append(this.canvas);
this.ctx = this.canvas.getContext("2d");
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
initBox() {
this.showImg = false;
this.canvas.style.display = "none";
let box = this.$refs[this.id];
let imgsrc;
if (this.bigImgUrl) {
imgsrc = this.bigImgUrl;
} else {
imgsrc = this.imgUrl;
}
this.img = new Image();
this.img.src = imgsrc;
this.img.onload = () => {
this.vertical = this.img.width < this.img.height;
this.showImg = true;
let thumb = box.querySelector("img");
setTimeout(() => {
(this.rectTimesX =
this.imgbox.offsetWidth /
this.scale /
box.querySelector("img").offsetWidth),
(this.rectTimesY =
this.imgbox.offsetHeight /
this.scale /
box.querySelector("img").offsetHeight);
}, 20);
};
},
mousemove(e) {
if (!this.init) {
return false;
}
let _this = this;
//获取实际的offset
function offset(curEle) {
var totalLeft = null,
totalTop = null,
par = curEle.offsetParent;
//首先加自己本身的左偏移和上偏移
totalLeft += curEle.offsetLeft;
totalTop += curEle.offsetTop;
//只要没有找到body,我们就把父级参照物的边框和偏移也进行累加
while (par) {
if (navigator.userAgent.indexOf("MSIE 8.0") === -1) {
//累加父级参照物的边框
totalLeft += par.clientLeft;
totalTop += par.clientTop;
}
//累加父级参照物本身的偏移
totalLeft += par.offsetLeft;
totalTop += par.offsetTop;
par = par.offsetParent;
}
return {
left: totalLeft,
top: totalTop
};
}
function getXY(eve) {
return {
x: eve.clientX - _this.cover.offsetWidth / 2,
y: eve.clientY - _this.cover.offsetHeight / 2
};
}
let oEvent = e || event;
let pos = getXY(oEvent);
let imgwrap = offset(this.imgwrap);
let range = {
minX: imgwrap.left,
maxX: imgwrap.left + this.imgwrap.offsetWidth - this.cover.offsetWidth,
minY: imgwrap.top - document.documentElement.scrollTop,
maxY:
imgwrap.top -
document.documentElement.scrollTop +
this.imgwrap.offsetHeight -
this.cover.offsetHeight
};
if (pos.x > range.maxX) {
pos.x = range.maxX;
}
if (pos.x < range.minX) {
pos.x = range.minX;
}
if (pos.y > range.maxY) {
pos.y = range.maxY;
}
if (pos.y < range.minY) {
pos.y = range.minY;
}
this.cover.style.left = pos.x + "px";
this.cover.style.top = pos.y + "px";
this.ctx.clearRect(
0,
0,
this.imgwrap.offsetWidth,
this.imgwrap.offsetHeight
);
let startX = pos.x - (imgwrap.left - document.documentElement.scrollLeft),
startY = pos.y - (imgwrap.top - document.documentElement.scrollTop);
this.ctx.drawImage(
this.img,
startX * this.imgTimesX,
startY * this.imgTimesY,
this.img.width * this.rectTimesX,
this.img.height * this.rectTimesY,
0,
0,
this.imgbox.offsetWidth,
this.imgbox.offsetHeight
);
this.bigImage = this.canvas.toDataURL("image/png");
},
mouseover(e) {
if (!this.init) {
return false;
}
e = e || event;
if (!this.scroll) {
e.currentTarget.addEventListener(
"mousewheel",
function(ev) {
ev.preventDefault();
},
false
);
e.currentTarget.addEventListener(
"DOMMouseScroll",
function(ev) {
ev.preventDefault();
},
false
);
}
this.cover.style.display = "block";
this.canvas.style.display = "block";
this.showImage = true;
},
mouseleave() {
if (!this.init) {
return false;
}
this.cover.style.display = "none";
this.canvas.style.display = "none";
this.showImage = false;
},
rotate(direction) {
var orginImg = new Image();
orginImg.crossOrigin = "Anonymous";
orginImg.src = this.orginUrl;
orginImg.onload = () => {
this.rotateImg(orginImg, direction, this.step);
};
if (this.bigOrginUrl) {
var bigOrginImg = new Image();
orginImg.crossOrigin = "Anonymous";
bigOrginImg.src = this.bigOrginUrl;
bigOrginImg.onload = () => {
this.rotateImg(bigOrginImg, direction, this.bigStep, true);
};
}
},
rotateImg(img, direction, step, isBig = false) {
var min_step = 0;
var max_step = 3;
if (img == null) return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
var height = img.height;
var width = img.width;
if (step == null) {
step = min_step;
}
if (direction == "right") {
step++;
//旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
var canvas = document.createElement("canvas");
//旋转角度以弧度值为参数
var degree = (step * 90 * Math.PI) / 180;
var ctx = canvas.getContext("2d");
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
var newImg = canvas.toDataURL();
if (isBig) {
this.bigImgUrl = newImg;
this.bigStep = step;
this.initBox();
} else {
this.imgUrl = newImg;
this.step = step;
this.$nextTick(() => {
this.initBox();
});
}
}
}
};
</script>
<style lang="scss" scoped>
.magnifier-box {
width: 100%;
height: 100%;
text-align: center;
overflow: hidden;
.edit-wrap {
top: 5px;
right: 0;
z-index: 9999999;
background: rgba(0, 0, 0, 0.4);
padding: 5px 15px 0 15px;
border-radius: 15px;
.rotate-left {
display: inline-block;
cursor: pointer;
width: 16px;
height: 16px;
/*background: url(../rotate.png);*/
background-size: 100% 100%;
-moz-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
-o-transform: scaleX(-1);
transform: scaleX(-1);
/*IE*/
filter: FlipH;
}
.rotate-right {
margin-left: 10px;
cursor: pointer;
display: inline-block;
width: 16px;
height: 16px;
/*background: url(../rotate.png);*/
background-size: 100% 100%;
}
}
img {
width: 100%;
}
.mouse-cover {
position: fixed;
background-color: rgba(0, 0, 0, 0.5);
cursor: move;
}
/deep/.mouse-cover-canvas {
position: fixed;
left: 100%;
top: 200px !important;
width: 100%;
height: 100%;
}
&.vertical {
img {
height: 100%;
width: auto;
}
}
}
.big-image {
border: 1px solid #eee;
display: block;
width: 498px;
height: 498px;
top: -1px;
position: absolute;
left: 498px;
z-index: 99;
}
</style>
Carousel.vue(缩略图组件)
<template>
<div>
<div class="pic-box">
<pic-zoom :url="pImgSrc" :scale="3"></pic-zoom>
</div>
<div class="box">
<el-carousel height="96px" indicator-position="none" :interval="0">
<el-carousel-item v-for="(item,i) in imagesList" :key="i">
<div
v-for="(img,index) in item.imgUrl"
:key="index"
@click="getIndex(img.url)"
class="img-url"
>
<img :src="img.url" />
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</template>
<script>
import PicZoom from "./PicZoom";
export default {
name: "Carousel",
components: {
PicZoom
},
data() {
return {
pImgSrc: ""
};
},
props: {
imgSrc: {
type: String,
default: ""
},
imagesList: {
type: Array,
default: function() {
return [];
}
}
},
methods: {
getIndex(imgSrc) {
this.pImgSrc = imgSrc;
}
},
watch: {
imgSrc: {
handler(aImgSrc, pImgSrc) {
this.pImgSrc = aImgSrc;
},
immediate: true
}
}
};
</script>
<style lang="scss" scoped>
.box {
width: 500px;
height: 100px;
overflow: hidden;
margin-top: 10px;
ul {
position: absolute;
width: 2000px;
li {
display: inline-block;
list-style: none;
width: 90px;
height: 90px;
background-color: white;
margin-top: 15px;
border: 1px solid #eee;
overflow: hidden;
margin-right: 10px;
img {
width: 100%;
}
}
}
}
.pic-box {
position:relative;
width: 498px;
height: 498px;
border: 1px solid #eee;
}
/deep/ .mouse-cover-canvas {
top: 200px !important;
margin-top: 200px;
}
.img-url {
display: inline-block;
border: 1px solid #eee;
margin-right: 10px;
&:nth-child(5) {
margin-right: 0;
}
img {
width: 90px;
}
}
</style>
index.vue
页面引用代码:
<Carousel :imgSrc="imgSrc" :imagesList="imagesList" />
js部分:
import Carousel from "@/components/main/Carousel.vue";
export default {
components: {
Carousel,
},
data() {
return {
imgSrc: require("../../../assets/images/bp002-1.jpg"), //默认显示大图
imagesList: [
//缩略图:
{
imgUrl: [
{ url: require("../../../assets/images/bp002-1.jpg") },
{ url: require("../../../assets/images/bp002-2.jpg") },
{ url: require("../../../assets/images/bp002-3.jpg") },
{ url: require("../../../assets/images/bp002-4.jpg") },
{ url: require("../../../assets/images/bp002-5.jpg") }
]
}
],
};
},
};
更多推荐
已为社区贡献2条内容
所有评论(0)