<div ref="imgBoxRef" class="image-box" v-else-if="imageTypes.includes(fileType)"
style="width:100%;height:100%;position: relative;">
<img class="no-transition" ref="imgRef" @load="handleImageLoad" v-drag v-zoom:[initWheelScale] :src="fileUrl"
alt="" style="position: absolute;" />
</div>
import dragDirective from '@/util/vDrag';
import zoomDirective from '@/util/zoomImage';
dleImageLoad() {
this.$nextTick(() => {
this.getComputedStyle()
})
},
getComputedStyle() {
let container = this.$refs.imgBoxRef
let img = this.$refs.imgRef
console.log(container, img)
// let container = document.querySelector('.image-box');
// let img = container.querySelector('img');
let containerWidth = container.offsetWidth;
let containerHeight = container.offsetHeight;
let imgWidth = img.offsetWidth;
let imgHeight = img.offsetHeight;
let scale = Math.min(containerWidth / imgWidth, containerHeight / imgHeight); // 计算最小比例
this.initWheelScale.minScale = scale
img.style.transform = 'scale(' + scale + ')'; // 设置缩放比例
img.style.left = (containerWidth - imgWidth) / 2 + "px"
img.style.top = (containerHeight - imgHeight) / 2 + "px"
// img.style.display = "block"
},
vdrag.js
// zoomDirective.js
export default {
bind(el, binding) {
const oDiv = el; // 当前元素
const minTop = oDiv.getAttribute("drag-min-top");
const ifMoveSizeArea = 20;
oDiv.onmousedown = (e) => {
let target = oDiv;
while (
window.getComputedStyle(target).position !== "absolute" &&
target !== document.body
) {
target = target.parentElement;
}
document.onselectstart = () => {
return false;
};
if (!target.getAttribute("init_x")) {
target.setAttribute("init_x", target.offsetLeft);
target.setAttribute("init_y", target.offsetTop);
}
const initX = parseInt(target.getAttribute("init_x"));
const initY = parseInt(target.getAttribute("init_y"));
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - target.offsetLeft;
const disY = e.clientY - target.offsetTop;
document.onmousemove = (e) => {
// 通过事件委托,计算移动的距离
// 因为浏览器里并不能直接取到并且使用clientX、clientY,所以使用事件委托在内部做完赋值
const l = e.clientX - disX;
const t = e.clientY - disY;
// 计算移动当前元素的位置,并且给该元素样式中的left和top值赋值
target.style.left = l + "px";
// target.style.top = (t < minTop ? minTop : t) + "px"
target.style.top = t + "px";
if (
Math.abs(l - initX) > ifMoveSizeArea ||
Math.abs(t - initY) > ifMoveSizeArea
) {
target.setAttribute("dragged", "");
} else {
target.removeAttribute("dragged");
}
};
document.onmouseup = (e) => {
document.onmousemove = null;
document.onmouseup = null;
document.onselectstart = null;
};
// return false不加的话可能导致黏连,拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
return false;
};
},
};
zoomImage.js
// zoomDirective.js
export default {
bind(el, binding) {
if (el) {
el.onwheel = (e) => {
const { maxScale = 5, minScale = 0.1 } = binding.arg || {};
const cssVarName = "--scale";
let _scale = el.style.getPropertyValue(cssVarName) || 1;
if (e.wheelDelta > 0) {
_scale = _scale * 1 + 0.1;
} else {
_scale = _scale * 1 - 0.1;
}
// 现在缩放范围
if (_scale > maxScale) {
_scale = maxScale;
} else if (_scale < minScale) {
_scale = minScale;
}
// 设置 --scale 变量 缩放比例
const setVarScale = (el, cssVarName) => {
let cssText = el.style.cssText;
let cssTextList = cssText.split(";");
let isExist = false;
let isExistIndex = -1;
for (let index = 0; index < cssTextList.length; index++) {
const element = cssTextList[index];
if (element.includes(cssVarName + ":")) {
isExist = true;
isExistIndex = index;
break;
}
}
if (isExist) {
cssTextList[isExistIndex] = `--scale: ${_scale}`;
} else {
cssTextList.push(`--scale: ${_scale}`);
// el.setAttribute("style", `--scale: ${_scale}`)
}
cssText = cssTextList.join(";");
el.style.cssText = cssText;
};
// 设置 style.transform
const setTransformCss = (el, cssVarName) => {
let transformCssString = el.style.transform;
let regScaleGlobal = /scale\(.*?[ )]*[)]+[ ]*/g; //匹配 Scale属性 全局
if (regScaleGlobal.test(transformCssString)) {
transformCssString = transformCssString.replace(
regScaleGlobal,
` scale(var(${cssVarName})) `
);
} else {
transformCssString += " " + `scale(var(${cssVarName}))`;
}
el.style.transform = transformCssString;
};
setVarScale(el, cssVarName);
setTransformCss(el, cssVarName);
// 缩放改变回调函数
const wheelScaleChange = binding.value || null;
if (wheelScaleChange instanceof Function && _scale != oldScale) {
oldScale = _scale;
wheelScaleChange({
cssVarName,
currentScale: _scale,
maxScale,
minScale,
});
}
};
}
},
};
效果: