UNPKG

tanyupeng

Version:

通过自定义指令实现一些有趣的操作,图片放大 , 字符串转图片验证码

109 lines (105 loc) 4.2 kB
//用来判断一个dom元素在可视范围内是否显示完整,不完整放大镜就和img底部对齐 function isElementPartiallyInViewport(element) { let rect = element.getBoundingClientRect(); let windowHeight = (window.innerHeight || document.documentElement.clientHeight); let vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0) && (rect.bottom > windowHeight); return vertInView; } const enterHandler = (e) => { const el = e.target //得到父盒子并加上相对定位,为什么?因为我的放大镜是通过父亲相对定位覆盖图片的 const father = el.parentNode father.style.position = 'relative' //寻找放大镜div, 没有的话就创建 let show = document.querySelector('.show') if (!show) { //如果没有放大镜蒙版就创建一个 show = document.createElement('div') //宽高等于图片大小, 因为要覆盖,如果不等于的话就计算大小 let width = el.width let height = el.height //给放大镜的宽高设置为原图大小,如果传入倍数就放大倍数 show.style.width = width * el.zoom + 'px' show.style.height = height * el.zoom + 'px' //一定要把放大镜的优先级提高 show.style.zIndex = 99 //计算出img距离顶部和左边多少,从而div覆盖原图实现放大效果 let top = el.offsetTop; let left = el.offsetLeft; //做一下放大倍数蒙版的适配,让放大镜和原图中心线对齐 // console.log(top + height); // console.log(window.innerHeight); if (el.zoom != 1) { left = left - (width * el.zoom - width) / 2 show.style.left = `${left}px` show.style.top = `${top}px` //如果超出左边就右靠 if (left < 0) { left = el.offsetLeft; show.style.left = `${left}px` // show.style.top = `${top}px` } //如果超出右边就让他左靠 else if ((left + width * el.zoom) > document.body.offsetWidth) { show.style.left = el.offsetLeft - (width * el.zoom - width) + 'px' // show.style.top = `${top}px` } //适配top //如果dom元素在y轴方向显示不完整, 也就是显示一半,那放大镜和原题img以底部对齐 if (isElementPartiallyInViewport(el)) { show.style.top = top - (height * el.zoom - height) + 'px' // console.log('不完整'); } else { // console.log("元素在y轴方向显示完整"); } } else { //正常情况下,也就是不放大的情况 show.style.left = `${left}px` show.style.top = `${top}px` } //把img的src取出来给放大镜div做背景 show.style.backgroundImage = `url(${el.src})` show.style.backgroundRepeat = 'no-repeat' // show.style.backgroundColor = 'red' //稍微设置一下圆角 show.style.borderRadius = '3%'; //绝对定位 show.style.position = 'absolute' // show.style.border = "1px solid rgba(44,163,221,.6)"; //把放大镜添加到father里面 father.appendChild(show) //放大镜出现就把原来的隐藏掉,主要是放大镜有一个圆角, 不隐藏会不美观 el.style.visibility = 'hidden' //放大镜移动 show.addEventListener('mousemove', (e) => { //核心代码 let rect = e.target.getBoundingClientRect() let x = e.offsetX / rect.width let y = e.offsetY / rect.height show.style.backgroundPosition = `calc(${x}*100%) calc(${y}*100%)` }) show.addEventListener('mouseleave', (e) => { //让原图又出现 el.style.visibility = 'visible' if (show) { //销毁dom, 事件也就不存在了 father.removeChild(show); } }) } } export default { mounted(el, bindings) { //如果有传入放大蒙版配置的话 if (bindings.value && bindings.value.zoom) { el.zoom = bindings.value.zoom } else { //默认是原图放大 el.zoom = 1 } el.addEventListener('mouseenter', enterHandler) }, beforeUnmount(el) { el.removeEventListener('mouseenter', enterHandler) } }