商城图片放大效果

商城图片放大效果

在这里插入图片描述

引入组件

组件pictureZoom外需要设置宽度,高度

import pictureZoom from '@/components/picture-zoom/picture-zoom.vue';
<div style="width: 100%;height: 100%;"><pictureZoom :url="baseUlr + bigImage"></pictureZoom></div>

创建组件picture-zoom

<template>
	<div class="pictureZoom-wrap" :ref="id" @mousemove="mousemove" @mouseover="mouseover" @mouseleave="mouseleave">
		<img class="pictureZoom-img" :src="imgUrl" />
		<div class="mouse-cover"></div>
	</div>
</template>

<script>
export default {
	props: {
		/**
		 * 图片放大倍数,数字越大移动的阴影部分越小
		 */
		scale: {
			type: Number,
			default: 2.5
		},
		/**
		 * 主图片
		 */
		url: {
			type: String,
			required: true
		},
		/**
		 * 放大镜特定图片,如果没有设置bigUrl图,直接使用url图片
		 */
		bigUrl: {
			type: String,
			default: null
		}
	},
	data() {
		return {
			id: null,
			cover: null,
			imgbox: null,
			imgwrap: null,
			bigImgUrl: null,
			imgUrl: null,
			img: null,
			canvas: null,
			ctx: null,
			rectTimesX: 0,
			rectTimesY: 0,
			imgTimesX: 0,
			imgTimesY: 0,
			init: false
		};
	},
	created() {
		var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
		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.bigImgUrl = this.bigUrl;
	},
	watch: {
		url: function(val) {
			this.imgUrl = val;
			this.initTime();
		},
		bigUrl: function(bigUrl) {
			this.bigImgUrl = bigUrl;
			this.initTime();
		}
	},
	mounted() {
		this.$nextTick(() => {
			this.initTime();
		});
	},
	methods: {
		initTime() {
			this.init = false;
			const 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.init = true;
			};
			if (this.canvas) {
				this.canvas.parentNode.removeChild(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.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);
		},
		mousemove(e) {
			if (!this.init) {
				return false;
			}
			const _this = this;
			// 获取实际的offset
			function offset(curEle) {
				var totalLeft = null;
				var totalTop = null;
				var 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
				};
			}
			const oEvent = e || event;
			const pos = getXY(oEvent);
			const imgwrap = offset(this.imgwrap);
			const 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);
			const startX = pos.x - (imgwrap.left - document.documentElement.scrollLeft);
			const 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
			);
		},
		mouseover(e) {
			if (!this.init) {
				return false;
			}
			e = e || event;
			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';
		},
		mouseleave() {
			if (!this.init) {
				return false;
			}
			this.cover.style.display = 'none';
			this.canvas.style.display = 'none';
		}
	}
};
</script>

<style lang="scss" scoped>
.pictureZoom-wrap {
	width: 100%;
	height: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	overflow: hidden;
	position: relative;
	.pictureZoom-img {
		width: 100%;
	}
	.mouse-cover {
		position: fixed;
		background-color: rgba(0, 0, 0, 0.5);
		cursor: move;
	}
	.mouse-cover-canvas {
		position: fixed;
		left: 100%;
		top: 0;
		width: 100%;
		height: 100%;
	}
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值