UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

122 lines 6.04 kB
"use strict"; // ==================== 通用工具函数 ==================== Object.defineProperty(exports, "__esModule", { value: true }); exports.PreviewClick = exports.bindMediaClick = void 0; const tslib_1 = require("tslib"); const lodash_1 = require("lodash"); const constant_1 = require("../../../common/constant"); const renderer_1 = require("../../../common/constant/renderer"); const base_event_1 = require("../../../interaction/base-event"); const customRenderer_1 = require("../../../utils/cell/customRenderer"); // 1. 创建蒙版层 const createPreviewOverlay = (overlayStyle) => { const overlay = document.createElement('div'); Object.assign(overlay.style, Object.assign({ width: '100vw', height: '100vh', position: 'fixed', top: '0', left: '0', backgroundColor: 'rgba(30, 30, 30, 0.5)', display: 'flex', justifyContent: 'center', alignItems: 'center', overflow: 'hidden', zIndex: '9999', cursor: 'pointer', touchAction: 'none', backdropFilter: 'blur(2px)', pointerEvents: 'auto' }, overlayStyle)); overlay.className = `${constant_1.S2_PREFIX_CLS}-preview-overlay`; return overlay; }; // 2. 通用媒体容器样式 const applyMediaContainerStyle = (element, mediaContainerStyle) => { const isPortrait = window.matchMedia('(orientation: portrait)').matches; // 根据横竖屏切换 const maxSize = isPortrait ? '90vw' : '90vh'; const minSize = isPortrait ? '60vw' : '60vh'; Object.assign(element.style, Object.assign({ maxWidth: maxSize, maxHeight: maxSize, minHeight: minSize, minWidth: minSize, objectFit: 'contain' }, mediaContainerStyle)); }; // ==================== 工厂函数 ==================== const createImageElement = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const { src, mediaContainerStyle, config } = options; const img = yield (0, customRenderer_1.asyncDrawImage)({ src, fallback: config === null || config === void 0 ? void 0 : config.fallback, timeout: config === null || config === void 0 ? void 0 : config.timeout, }); applyMediaContainerStyle(img, mediaContainerStyle); img.alt = 'preview'; return img; }); const createVideoElement = (src, mediaContainerStyle) => { const video = document.createElement('video'); video.src = src; video.controls = true; video.preload = 'auto'; video.playsInline = true; // iOS 兼容 video.setAttribute('webkit-playsinline', 'true'); video.setAttribute('playsinline', 'true'); applyMediaContainerStyle(video, mediaContainerStyle); return video; }; // ==================== 主逻辑 ==================== const bindMediaClick = (cell) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const renderer = cell.getRenderer(); const { type, prepareText } = renderer; const src = yield (0, customRenderer_1.getPreparedText)(prepareText, cell.getFieldValue().toString()); if (renderer.clickToPreview === false || ![renderer_1.CellRendererType.IMAGE, renderer_1.CellRendererType.VIDEO].includes(renderer.type)) { return; } // 创建蒙版和媒体元素 const previewTheme = cell.getStyle('preview'); const overlay = createPreviewOverlay(previewTheme === null || previewTheme === void 0 ? void 0 : previewTheme.overlay); const mediaElement = type === renderer_1.CellRendererType.IMAGE ? yield createImageElement({ src, mediaContainerStyle: previewTheme === null || previewTheme === void 0 ? void 0 : previewTheme.mediaContainer, config: renderer, }) : createVideoElement(src, previewTheme === null || previewTheme === void 0 ? void 0 : previewTheme.mediaContainer); // 统一事件处理(支持触控) const handleClose = (e) => { // 关键:阻止所有事件传播和默认行为 e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); if (e.target === overlay) { document.body.removeChild(overlay); mediaElement.remove(); // 恢复滚动 document.body.style.overflow = 'auto'; } }; // 避免移动端误触 setTimeout(() => { ['click', 'touchstart', 'touchend'].forEach((eventType) => { overlay.addEventListener(eventType, handleClose, { passive: false }); }); }, 500); // 禁止背景滚动 document.body.style.overflow = 'hidden'; overlay.appendChild(mediaElement); document.body.appendChild(overlay); }); exports.bindMediaClick = bindMediaClick; class PreviewClick extends base_event_1.BaseEvent { bindEvents() { const events = [ constant_1.S2Event.DATA_CELL_CLICK, constant_1.S2Event.ROW_CELL_CLICK, constant_1.S2Event.COL_CELL_CLICK, ]; events.forEach((eventType) => { this.spreadsheet.on(eventType, (event) => this.bindMediaCellClick(event)); }); } bindMediaCellClick(event) { var _a, _b, _c, _d; const cell = this.spreadsheet.getCell(event.target); const cellRendererType = (_b = (_a = cell === null || cell === void 0 ? void 0 : cell.getRenderer) === null || _a === void 0 ? void 0 : _a.call(cell)) === null || _b === void 0 ? void 0 : _b.type; if (cellRendererType === renderer_1.CellRendererType.IMAGE && (0, lodash_1.get)(event.target, 'nodeName') !== 'image') { // 如果点击的位置并不是图片,则不预览 return; } if (((_d = (_c = cell === null || cell === void 0 ? void 0 : cell.getRenderer) === null || _c === void 0 ? void 0 : _c.call(cell)) === null || _d === void 0 ? void 0 : _d.type) && (this.spreadsheet.isPivotMode() || cell.cellType !== constant_1.CellType.COL_CELL)) { this.spreadsheet.emit(constant_1.S2Event.GLOBAL_PREVIEW_CLICK, event); (0, exports.bindMediaClick)(cell); } } } exports.PreviewClick = PreviewClick; //# sourceMappingURL=preview-click.js.map