UNPKG

@opentiny/fluent-editor

Version:

A rich text editor based on Quill 2.0, which extends rich modules and formats on the basis of Quill. It's powerful and out-of-the-box.

242 lines (241 loc) 7.09 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); class ImagePreviewModal { constructor() { __publicField(this, "modal", null); __publicField(this, "overlay", null); __publicField(this, "previewImage", null); __publicField(this, "scaleTooltip", null); __publicField(this, "closeBtn", null); __publicField(this, "currentScale", 1); __publicField(this, "minScale", 0.5); __publicField(this, "maxScale", 3); __publicField(this, "scaleStep", 0.1); __publicField(this, "tooltipHideTimer", null); /** * 处理鼠标滚轮事件 - 缩放图片 */ __publicField(this, "onMouseWheel", (event) => { if (!this.modal || this.modal.style.display === "none") { return; } event.preventDefault(); const delta = event.deltaY > 0 ? -this.scaleStep : this.scaleStep; this.setScale(this.currentScale + delta); this.showScaleTooltip(); }); this.initModal(); } initModal() { this.overlay = document.createElement("div"); this.overlay.className = "image-preview-overlay"; this.overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: none; z-index: 9999; cursor: pointer; `; this.modal = document.createElement("div"); this.modal.className = "image-preview-modal"; this.modal.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: transparent; display: none; z-index: 10000; max-width: 90vw; max-height: 90vh; cursor: auto; `; this.previewImage = document.createElement("img"); this.previewImage.className = "image-preview-img"; this.previewImage.style.cssText = ` max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); transition: transform 0.2s ease-out; cursor: grab; `; this.closeBtn = document.createElement("button"); this.closeBtn.className = "tiny-editor-image-preview-close"; this.closeBtn.innerHTML = "×"; this.closeBtn.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 40px; height: 40px; border: none; background-color: transparent; color: white; font-size: 32px; cursor: pointer; z-index: 10001; line-height: 1; padding: 0; `; this.closeBtn.addEventListener("click", () => this.hide()); this.modal.appendChild(this.previewImage); document.body.appendChild(this.closeBtn); this.scaleTooltip = document.createElement("div"); this.scaleTooltip.className = "image-preview-scale-tooltip"; this.scaleTooltip.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgba(0, 0, 0, 0.7); color: white; padding: 12px 20px; border-radius: 6px; font-size: 14px; z-index: 10002; display: none; pointer-events: none; white-space: nowrap; font-weight: 500; `; document.body.appendChild(this.scaleTooltip); this.overlay.addEventListener("click", () => this.hide()); document.addEventListener("keydown", (e) => { if (e.key === "Escape") { this.hide(); } }); document.addEventListener("wheel", (e) => this.onMouseWheel(e), { passive: false }); this.modal.addEventListener("click", (e) => { e.stopPropagation(); }); document.body.appendChild(this.overlay); document.body.appendChild(this.modal); } /** * 设置缩放比例 */ setScale(scale) { this.currentScale = Math.max(this.minScale, Math.min(scale, this.maxScale)); if (this.previewImage) { this.previewImage.style.transform = `scale(${this.currentScale})`; } } /** * 显示缩放百分比提示 */ showScaleTooltip() { if (!this.scaleTooltip) { return; } if (this.tooltipHideTimer !== null) { clearTimeout(this.tooltipHideTimer); } const percentage = Math.round(this.currentScale * 100); this.scaleTooltip.textContent = `${percentage}%`; this.scaleTooltip.style.display = "block"; this.tooltipHideTimer = window.setTimeout(() => { if (this.scaleTooltip) { this.scaleTooltip.style.display = "none"; } this.tooltipHideTimer = null; }, 1500); } /** * 隐藏缩放提示 */ hideScaleTooltip() { if (this.tooltipHideTimer !== null) { clearTimeout(this.tooltipHideTimer); this.tooltipHideTimer = null; } if (this.scaleTooltip) { this.scaleTooltip.style.display = "none"; } } /** * 重置缩放比例 */ resetScale() { this.currentScale = 1; if (this.previewImage) { this.previewImage.style.transform = "scale(1)"; } this.hideScaleTooltip(); } /** * 显示预览 * @param imageUrl 图片URL */ show(imageUrl) { if (!this.previewImage || !this.modal || !this.overlay) { return; } this.resetScale(); this.previewImage.src = imageUrl; this.modal.style.display = "flex"; this.modal.style.alignItems = "center"; this.modal.style.justifyContent = "center"; this.overlay.style.display = "block"; if (this.closeBtn) { this.closeBtn.style.display = "block"; } document.body.style.overflow = "hidden"; } /** * 隐藏预览 */ hide() { if (this.modal && this.overlay) { this.modal.style.display = "none"; this.overlay.style.display = "none"; document.body.style.overflow = ""; this.resetScale(); if (this.closeBtn) { this.closeBtn.style.display = "none"; } } } /** * 销毁预览模态框 */ destroy() { this.hideScaleTooltip(); if (this.overlay && this.overlay.parentNode) { this.overlay.parentNode.removeChild(this.overlay); } if (this.modal && this.modal.parentNode) { this.modal.parentNode.removeChild(this.modal); } if (this.closeBtn && this.closeBtn.parentNode) { this.closeBtn.parentNode.removeChild(this.closeBtn); } if (this.scaleTooltip && this.scaleTooltip.parentNode) { this.scaleTooltip.parentNode.removeChild(this.scaleTooltip); } this.modal = null; this.overlay = null; this.previewImage = null; this.closeBtn = null; this.scaleTooltip = null; } } let globalPreviewModal = null; function getImagePreviewModal() { if (!globalPreviewModal) { globalPreviewModal = new ImagePreviewModal(); } return globalPreviewModal; } export { ImagePreviewModal, getImagePreviewModal }; //# sourceMappingURL=preview-modal.es.js.map