如何为Sweet Alert嵌入HTML添加图片悬停放大功能
实现Sweet Alert中嵌入式图片的悬停放大功能
问题描述
现有如下Sweet Alert代码,需要为其中的嵌入式<embed>元素添加鼠标悬停放大细节的功能(鼠标移到图片上显示局部放大效果),此前尝试在Swal内部添加相关JS和CSS未成功,求可行实现方案:
Swal.fire({ type: 'success', title: 'Please verify document', html: ` <div style="display: flex; flex-direction: column; justify-content: center; align-items: center"> <embed src="${reader.result}" width="250"/> &nbsp; <div class="my-2"> The NIC is:&nbsp; <input type="text" class="form-style form-control" id="nic" placeholder="NIC No" style="text-align: center; width:170px; font-weight: bold;" maxlength="12"> </div> </div>`, confirmButtonText: 'OK', focusConfirm: false, allowOutsideClick: false, width: 800, onOpen: function () { (<HTMLInputElement>Swal.getPopup().querySelector('#nic')).value = NICDATA; }, preConfirm: () => { const nic = (<HTMLInputElement>Swal.getPopup().querySelector('#nic')).value; if (!nic) { Swal.showValidationMessage(`Please enter NIC no`) } return { nic: nic } } }).then((result) => { if (result.value) { this.nicNo = `${result.value.nic}`; sessionStorage.removeItem("NICNO"); sessionStorage.setItem("NICNO", `${result.value.nic}`); this.upload(); } else if (result.dismiss == Swal.DismissReason.cancel) { this.fileUploadEvent.target.value = null; } });
解决方案
Swal弹窗是动态生成的DOM元素,静态CSS/JS无法直接绑定生效,需结合动态DOM操作和事件绑定实现,具体步骤如下:
1. 调整Swal的HTML结构
将原<embed>包裹在容器内,新增一个用于显示放大区域的<div>,修改后的html内容:
<div style="display: flex; flex-direction: column; justify-content: center; align-items: center"> <div class="nic-zoom-container" style="position: relative;"> <embed id="nic-document" src="${reader.result}" width="250" style="cursor: zoom-in;"/> <div id="nic-zoom-preview" style="position: absolute; border: 1px solid #ccc; width: 300px; height: 300px; overflow: hidden; display: none; z-index: 9999;"></div> </div> <div class="my-2"> The NIC is:&nbsp; <input type="text" class="form-style form-control" id="nic" placeholder="NIC No" style="text-align: center; width:170px; font-weight: bold;" maxlength="12"> </div> </div>
2. 在onOpen钩子中绑定放大逻辑
利用Swal的onOpen回调获取动态DOM元素,绑定鼠标事件实现跟随放大效果:
onOpen: function () { // 原有NIC赋值逻辑 (<HTMLInputElement>Swal.getPopup().querySelector('#nic')).value = NICDATA; // 获取放大相关元素 const embed = Swal.getPopup().querySelector('#nic-document'); const preview = Swal.getPopup().querySelector('#nic-zoom-preview'); // 等待embed资源加载完成后计算缩放比例 embed.addEventListener('load', () => { preview.style.backgroundImage = `url(${embed.src})`; const scale = embed.naturalWidth / embed.clientWidth; preview.style.backgroundSize = `${embed.naturalWidth}px ${embed.naturalHeight}px`; }); // 鼠标移入显示预览区 embed.addEventListener('mouseover', () => { preview.style.display = 'block'; }); // 鼠标移出隐藏预览区 embed.addEventListener('mouseout', () => { preview.style.display = 'none'; }); // 鼠标移动时同步预览区位置与背景偏移 embed.addEventListener('mousemove', (e) => { const rect = embed.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const scale = embed.naturalWidth / embed.clientWidth; // 计算背景偏移量,实现局部放大跟随 const bgX = -(x * scale - preview.clientWidth / 2); const bgY = -(y * scale - preview.clientHeight / 2); preview.style.left = `${x + 10}px`; preview.style.top = `${y + 10}px`; preview.style.backgroundPosition = `${bgX}px ${bgY}px`; }); }
3. 完整修改后的代码
Swal.fire({ type: 'success', title: 'Please verify document', html: ` <div style="display: flex; flex-direction: column; justify-content: center; align-items: center"> <div class="nic-zoom-container" style="position: relative;"> <embed id="nic-document" src="${reader.result}" width="250" style="cursor: zoom-in;"/> <div id="nic-zoom-preview" style="position: absolute; border: 1px solid #ccc; width: 300px; height: 300px; overflow: hidden; display: none; z-index: 9999;"></div> </div> <div class="my-2"> The NIC is:&nbsp; <input type="text" class="form-style form-control" id="nic" placeholder="NIC No" style="text-align: center; width:170px; font-weight: bold;" maxlength="12"> </div> </div>`, confirmButtonText: 'OK', focusConfirm: false, allowOutsideClick: false, width: 800, onOpen: function () { (<HTMLInputElement>Swal.getPopup().querySelector('#nic')).value = NICDATA; // 图片放大逻辑 const embed = Swal.getPopup().querySelector('#nic-document'); const preview = Swal.getPopup().querySelector('#nic-zoom-preview'); embed.addEventListener('load', () => { preview.style.backgroundImage = `url(${embed.src})`; const scale = embed.naturalWidth / embed.clientWidth; preview.style.backgroundSize = `${embed.naturalWidth}px ${embed.naturalHeight}px`; }); embed.addEventListener('mouseover', () => { preview.style.display = 'block'; }); embed.addEventListener('mouseout', () => { preview.style.display = 'none'; }); embed.addEventListener('mousemove', (e) => { const rect = embed.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const scale = embed.naturalWidth / embed.clientWidth; const bgX = -(x * scale - preview.clientWidth / 2); const bgY = -(y * scale - preview.clientHeight / 2); preview.style.left = `${x + 10}px`; preview.style.top = `${y + 10}px`; preview.style.backgroundPosition = `${bgX}px ${bgY}px`; }); }, preConfirm: () => { const nic = (<HTMLInputElement>Swal.getPopup().querySelector('#nic')).value; if (!nic) { Swal.showValidationMessage(`Please enter NIC no`) } return { nic: nic } } }).then((result) => { if (result.value) { this.nicNo = `${result.value.nic}`; sessionStorage.removeItem("NICNO"); sessionStorage.setItem("NICNO", `${result.value.nic}`); this.upload(); } else if (result.dismiss == Swal.DismissReason.cancel) { this.fileUploadEvent.target.value = null; } });
关键说明
- 绑定
embed的load事件确保资源加载完成后再计算尺寸,避免缩放比例错误。 - 预览区的尺寸(300x300)、偏移量(+10px)可根据需求自行调整。
内容的提问来源于stack exchange,提问作者chmodk
相关产品推荐
相关产品推荐

