UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

117 lines 5.67 kB
// ==================== 通用工具函数 ==================== import { __awaiter } from "tslib"; import { get } from 'lodash'; import { CellType, S2Event, S2_PREFIX_CLS } from '../../../common/constant'; import { CellRendererType } from '../../../common/constant/renderer'; import { BaseEvent } from '../../../interaction/base-event'; import { asyncDrawImage, getPreparedText, } from '../../../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 = `${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) => __awaiter(void 0, void 0, void 0, function* () { const { src, mediaContainerStyle, config } = options; const img = yield 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; }; // ==================== 主逻辑 ==================== export const bindMediaClick = (cell) => __awaiter(void 0, void 0, void 0, function* () { const renderer = cell.getRenderer(); const { type, prepareText } = renderer; const src = yield getPreparedText(prepareText, cell.getFieldValue().toString()); if (renderer.clickToPreview === false || ![CellRendererType.IMAGE, 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 === 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); }); export class PreviewClick extends BaseEvent { bindEvents() { const events = [ S2Event.DATA_CELL_CLICK, S2Event.ROW_CELL_CLICK, 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 === CellRendererType.IMAGE && 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 !== CellType.COL_CELL)) { this.spreadsheet.emit(S2Event.GLOBAL_PREVIEW_CLICK, event); bindMediaClick(cell); } } } //# sourceMappingURL=preview-click.js.map