该篇为前一篇“Element-UI - 解决el-table中图片悬浮被遮挡问题”的优化升级部分,解决当图片位于页面底部时,显示不全问题优化。
Vue.directive钩子函数已在上一篇中详细介绍,不清楚的朋友可以翻看上一篇, “Element-UI - 解决el-table中图片悬浮被遮挡问题”的地址:Element-UI - 解决el-table中图片悬浮被遮挡问题_el-badge el-table 被遮挡-CSDN博客
一、浏览器窗口
浏览器窗口的宽和高分别通过window.innerWidth和window.innerHeight获取,如最底部图片,可以通过获取弹框中图片高度,进行对比是否超出window.innerHeight; 如果超出,则减于图片高度,进行底部对齐显示。
二、弹框中图片高度获取
在上一篇中,在弹框封装类中定义了imgBox属性,用于记录弹框中图片DOM节点对象,所以可以在执行resetPosition(boundingClientRect)函数时,可以通过this.imgBox.height获取弹框中图片的高度。
控制台中显示弹框中图片高度,如下图:
三、实现图片上移
通过上述了解后,知道了如何判断图片是否超出底位置,如果超出了,则需要将位置top减掉弹框实际高度(图片高度 + 弹框内填充),进行上移即可。
修改后的resetPosition函数代码如下:
/*** 重新指定弹框位置* @param {Object} boundingClientRect*/resetPosition(boundingClientRect){// 弹框实际高度const height = this.imgBox.height + this.dialogPadding * 2;// 判断图片是否超出底部可见范围if( boundingClientRect.top + height >= window.innerHeight){// top减于弹框实际高度this.sDialog.style.top = (boundingClientRect.top - height) + "px";}// 未超出else{this.sDialog.style.top = (boundingClientRect.top - this.dialogPadding) + "px";}this.sDialog.style.left = (boundingClientRect.width + boundingClientRect.left) + "px";}
此时底部图片则已被修正,可以底部对齐显示了,如下图:
四、完整代码
1.页面代码
import sDialog from './suspendedDialog.js'
export default {data(){return {tableData: [{name: "Angular", thumb: require("@/assets/angular.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},{name: "VueJs", thumb: require("@/assets/logo.png"), createtime: "2024/6/15", updatetime: "2024/6/15"},{name: "NuxtJs", thumb: require("@/assets/nuxtjs.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},{name: "React", thumb: require("@/assets/react.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"},{name: "Dog", thumb: require("@/assets/dog.jpg"), createtime: "2024/6/15", updatetime: "2024/6/15"}]}},directives: {// 自定义悬浮v-suspendedsuspended: {bind: (el) => {// 初始化悬浮框sDialog.initialDom();// 鼠标经过图片并未移出时执行回调函数el.addEventListener('mouseenter', function(e) {// 显示悬浮弹框,显示后获取相应的参数信息sDialog.toggle(true, () => {sDialog.setImgUrl(el.src); // 修改新的图片地址sDialog.resetPosition(el.getBoundingClientRect()); // 修正弹框位置});});// 鼠标移出图片区域时,隐藏悬浮弹框el.addEventListener('mouseleave', () => sDialog.toggle(false));}}},// end
}
2.封装类(suspendedDialog.js)
/** 定义弹框类*/
class SuspendedDialog{constructor(){this.idName = "suspended-dialog"; // 定义容器ID选择器名称this.innerClassName = "inner"; // 内容器类选择器名称this.imgClassName = "imgs"; // 图片节点类选择器名称this.dialogWidth = 240; // 外容器宽度this.dialogPadding = 12; // 外容器内填充this.sDialog = document.createElement('div'); // 外层容器this.innerBox = document.createElement('div'); // 内容器对象this.imgBox = document.createElement('img'); // 图片节点对象}/*** 初始化DOM,并添加到body中*/initialDom(){const sDialog = document.getElementById(this.idName); // 查询节点// 如果节点存在,则结束后续操作if(sDialog) return;// 初始经属性this.sDialog.id = this.idName;this.innerBox.classList.add(this.innerClassName);this.imgBox.classList.add(this.imgClassName);// 将DOM追加到对应容器中this.innerBox.append(this.imgBox);this.sDialog.append(this.innerBox);document.body.append(this.sDialog);// 追加事件this.addEvent();}/*** 修改图片路径* @param {Object} _url*/setImgUrl(_url){this.imgBox.src = _url;}/*** 添加监听事件*/addEvent(){this.sDialog.addEventListener('mouseenter', e => this.toggle(true)); // 鼠标移入悬浮框区域时保持显示this.sDialog.addEventListener('mouseleave', e => this.toggle(false)); // 鼠标移出悬浮框区域时隐藏}/*** 显示与隐藏* @param {Object} flag* @param {Object} callback 回调函数*/toggle(flag, callback = () => {}){if(flag && 'block'!=this.sDialog.style.display){this.sDialog.style.display = 'block';callback();} else if(!flag && 'none'!=this.sDialog.style.display){this.sDialog.style.display = 'none';callback();}}/*** 重新指定弹框位置* @param {Object} boundingClientRect*/resetPosition(boundingClientRect){// 弹框实际高度const height = this.imgBox.height + this.dialogPadding * 2;// 判断图片是否超出底部可见范围if(boundingClientRect.top + height >= window.innerHeight){// top减于弹框实际高度this.sDialog.style.top = (boundingClientRect.top - height) + "px";}// 未超出else{this.sDialog.style.top = (boundingClientRect.top - this.dialogPadding) + "px";}this.sDialog.style.left = (boundingClientRect.width + boundingClientRect.left) + "px";}
}
export default new SuspendedDialog();
另外,图片除了底部超出可见范围,也会出现左侧或右侧超出可见范围,则可以通过window.innerWidth进行判断处理,计算方式差不多,这里就不再阐述。