鼠标over的时候局部放大,点击时弹出放大的图片
piczoom插件传值,是否开启点击放大:isExpanImg="true"
<PicZoom v-if="cltz" :url="cltz" class="picImg" :isExpanImg="true" :scale="4"></PicZoom>
<template>
<div v-viewer class="magnifier-box" :class="[vertical?'vertical':'',cname]" :ref="id" @mousemove="mousemove" @mouseover="mouseover" @mouseleave="mouseleave">
<img v-show="showImg" :src="imgUrl" ref="picImg" alt="">
<div class="mouse-cover" @click="isExpanImg?hhh():$event.stopPropagation()" v-show="!isExpanImg&&ismouseCovershow"></div>
<div class="edit-wrap" v-if="showEidt">
<span class="rotate-left" @click="rotate('left')"></span>
<span class="rotate-right" @click="rotate('right')"></span>
</div>
</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
},
cname:{
type:String,
default:''
},
ispizoom:{
type:Boolean,
default:false
},
isExpanImg:{
type:Boolean,
default:false
},//是否开启点击图片放大的功能
},
data () {
return {
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,
ismouseCovershow: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()
},
vertical:function(){
this.initTime()
},
},
mounted(){
this.$nextTick(()=>{
this.initTime()
})
},
methods: {
hhh(){
this.ismouseCovershow=false;
this.$nextTick(()=>{
this.$refs.picImg.click()
})
this.initTime()
},
initTime(){
this.init=false
// console.log(this.id,"this.id红红火火恍恍惚惚")
let box=this.$refs[this.id]
this.imgbox=box
// this.imgbox=box.querySelector('img')
// console.log(this.imgbox,"this.imgbox")
this.cover=box.querySelector('.mouse-cover')
// console.log(this.cover,"this.cover")
// console.log(this.imgbox.offsetHeight,"this.imgbox.offsetHeight")
// console.log(this.imgbox.offsetWidth,"this.imgbox.offsetWidth")
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%'
// console.log(this.cover.style.width,"this.cover.style.width")
// console.log(this.cover.style.height,"this.cover.style.height")
this.imgwrap=box.querySelector('img')
let imgsrc;
if(this.bigImgUrl){
imgsrc=this.bigImgUrl
}else{
imgsrc=this.imgUrl
}
this.img=new Image()
this.img.crossOrigin = "Anonymous";
this.img.src=imgsrc
this.img.οnlοad=()=>{
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
// this.img.width*=2;
// this.img.height*=2;
// console.log(this.img,"this.img")
// console.log(this.img.width,"this.img")
// console.log(this.img.height,"this.img")
}
if(this.canvas){
this.canvas.parentNode.removeChild(this.canvas);
this.canvas=null
}
this.canvas=document.createElement('canvas')
this.canvas.className='mouse-cover-canvas '+this.cname
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.height=this.imgbox.offsetHeight/4;
// this.canvas.style.width=this.imgbox.offsetWidth/4;
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.οnlοad=()=>{
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.img.width*=2;
// this.img.height*=2;
// console.log(this.img,"this.img")
// console.log(this.img.width,"this.img")
// console.log(this.img.height,"this.img")
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);
// console.log(this.img,"this.img")
// console.log(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.applySharpenEffect(this.ctx); // 应用锐化效果
// this.applyBlurEffect(this.ctx); // 应用模糊效果
// this.canvas.style.left=this.imgbox.offsetLeft+this.imgbox.offsetWidth+10+pos.x+'px'
// this.canvas.style.top=this.imgbox.offsetTop+pos.y+'px'
this.canvas.style.left=this.imgbox.offsetLeft+this.imgbox.offsetWidth+10+pos.x+'px'
this.canvas.style.top=this.imgbox.offsetTop+pos.y+'px'
// console.log(pos.x+'px',"离左边的距离");
// console.log(pos.y+'px',"离上边的距离");
// console.log(this.canvas,"this.canvas");
// console.log(this.canvas.style.left,"this.canvas离左边的距离");
// console.log(this.canvas.style.top,"this.canvas离上边的距离");
},
applySharpenEffect(context) {
const imageData = context.getImageData(0, 0, this.img.width*this.rectTimesX,this.img.height*this.rectTimesY);
// const imageData = context.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
console.log(imageData,"imageData")
const data = imageData.data;
const weights = [
0, -1, 0,
-1, 5, -1,
0, -1, 0,
];
for (let i = 0; i < data.length; i += 4) {
const red = data[i];
const green = data[i + 1];
const blue = data[i + 2];
const alpha = data[i + 3];
let blurRed = 0;
let blurGreen = 0;
let blurBlue = 0;
for (let j = -1; j <= 1; j++) {
for (let k = -1; k <= 1; k++) {
const index = i + (j * this.img.width*this.rectTimesX * 4) + (k * 4);
const weight = weights[(j + 1) * 3 + (k + 1)];
blurRed += data[index] * weight;
blurGreen += data[index + 1] * weight;
blurBlue += data[index + 2] * weight;
}
}
data[i] = red + blurRed;
data[i + 1] = green + blurGreen;
data[i + 2] = blue + blurBlue;
}
context.putImageData(imageData, 0, 0);
},
applyBlurEffect(context) {
const imageData = context.getImageData(0, 0, this.imgbox.offsetWidth,this.imgbox.offsetHeight);
// const imageData = context.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const red = data[i];
const green = data[i + 1];
const blue = data[i + 2];
const alpha = data[i + 3];
// 简单的模糊算法,取上下左右四个像素的平均值
const blurRed = (data[i - 4] + data[i + 4] + data[i - this.img.width*this.rectTimesX * 4] + data[i + this.img.width*this.rectTimesX * 4]) / 4;
const blurGreen = (data[i - 3] + data[i + 5] + data[i - this.img.width*this.rectTimesX * 4 + 1] + data[i + this.img.width*this.rectTimesX * 4 + 1]) / 4;
const blurBlue = (data[i - 2] + data[i + 6] + data[i - this.img.width*this.rectTimesX * 4 + 2] + data[i + this.img.width*this.rectTimesX * 4 + 2]) / 4;
data[i] = blurRed;
data[i + 1] = blurGreen;
data[i + 2] = blurBlue;
}
context.putImageData(imageData, 0, 0);
},
// getPixelRatio(context) {
// const backingStore =
// context.backingStorePixelRatio ||
// context.webkitBackingStorePixelRatio ||
// context.mozBackingStorePixelRatio ||
// context.msBackingStorePixelRatio ||
// context.oBackingStorePixelRatio ||
// context.backingStorePixelRatio || 1;
// return (window.devicePixelRatio || 1) / backingStore;
// },
mouseover(e){
// 模版出现
this.ismouseCovershow=true;
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'
},
mouseleave(){
if(!this.init){
return false
}
this.cover.style.display='none'
this.canvas.style.display='none'
},
rotate(direction){
var orginImg=new Image()
orginImg.crossOrigin = "Anonymous";
orginImg.src=this.orginUrl
orginImg.οnlοad=()=>{
this.rotateImg(orginImg,direction,this.step)
}
if(this.bigOrginUrl){
var bigOrginImg=new Image()
orginImg.crossOrigin = "Anonymous";
bigOrginImg.src=this.bigOrginUrl
bigOrginImg.οnlοad=()=>{
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%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
position: relative;
.edit-wrap{
position: absolute;
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
};
.mouse-cover-canvas{
position:fixed;
left:100%;
top:0;
width:100%;
height:100%;
}
&.vertical{
img{
height: 100%;
width: auto
}
}
}
</style>