UNPKG

@v2x-three/core

Version:

V2X Three.js 核心库 - 开放式的Three.js工具集,支持React和Vue项目

2,287 lines (2,086 loc) 2.57 MB
import proj4 from 'proj4'; /** * 🎨 智能气泡管理器 * * 功能特性: * - 科技感毛玻璃蓝色半透明气泡 * - 智能避障定位算法 * - 内容自适应布局 * - 设备关联和状态同步 */ /** * 智能气泡管理器 */ class BubbleManager { constructor(camera, container) { this.bubbles = new Map(); // 样式配置 this.BUBBLE_STYLES = { background: 'rgba(0, 123, 255, 0.15)', backdropFilter: 'blur(20px)', border: '1px solid rgba(0, 123, 255, 0.3)', borderRadius: '12px', boxShadow: '0 8px 32px rgba(0, 123, 255, 0.1)', color: '#ffffff', fontSize: '14px', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', padding: '16px', maxWidth: '300px', minWidth: '200px', zIndex: '10000', }; this.camera = camera; this.container = container; this.initializeEventListeners(); this.createBubbleContainer(); } /** * 初始化事件监听器 */ initializeEventListeners() { // 窗口大小变化时重新计算位置 window.addEventListener('resize', () => { this.updateAllBubblePositions(); }); // 相机移动时更新位置 this.container.addEventListener('mousemove', () => { requestAnimationFrame(() => { this.updateAllBubblePositions(); }); }); } /** * 创建气泡容器 */ createBubbleContainer() { let bubbleContainer = document.getElementById('v2x-bubble-container'); if (!bubbleContainer) { bubbleContainer = document.createElement('div'); bubbleContainer.id = 'v2x-bubble-container'; bubbleContainer.style.cssText = ` position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9999; `; this.container.appendChild(bubbleContainer); } } /** * 添加气泡 */ addBubble(config) { if (this.bubbles.has(config.id)) { console.warn(`气泡 ${config.id} 已存在,将被替换`); this.removeBubble(config.id); } const element = this.createBubbleElement(config); const position = this.calculateOptimalPosition(config); const instance = { config, element, position, visible: false, }; this.bubbles.set(config.id, instance); this.updateBubblePosition(instance); return config.id; } /** * 移除气泡 */ removeBubble(id) { const instance = this.bubbles.get(id); if (!instance) return false; instance.element.remove(); this.bubbles.delete(id); return true; } /** * 显示气泡 */ showBubble(id) { const instance = this.bubbles.get(id); if (!instance) return false; instance.visible = true; instance.element.style.display = 'block'; instance.element.style.opacity = '0'; // 动画显示 requestAnimationFrame(() => { instance.element.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; instance.element.style.opacity = '1'; instance.element.style.transform = 'translateY(0) scale(1)'; }); this.updateBubblePosition(instance); return true; } /** * 隐藏气泡 */ hideBubble(id) { const instance = this.bubbles.get(id); if (!instance) return false; instance.visible = false; instance.element.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; instance.element.style.opacity = '0'; instance.element.style.transform = 'translateY(-10px) scale(0.95)'; setTimeout(() => { if (!instance.visible) { instance.element.style.display = 'none'; } }, 300); return true; } /** * 更新气泡内容 */ updateBubbleContent(id, content) { const instance = this.bubbles.get(id); if (!instance) return false; instance.config.content = { ...instance.config.content, ...content }; const contentElement = instance.element.querySelector('.bubble-content'); if (contentElement) { contentElement.innerHTML = this.generateContentHTML(instance.config.content); } return true; } /** * 创建气泡元素 */ createBubbleElement(config) { const bubble = document.createElement('div'); bubble.className = `v2x-bubble bubble-${config.type || 'info'}`; bubble.style.cssText = ` position: absolute; background: ${this.BUBBLE_STYLES.background}; backdrop-filter: ${this.BUBBLE_STYLES.backdropFilter}; -webkit-backdrop-filter: ${this.BUBBLE_STYLES.backdropFilter}; border: ${this.BUBBLE_STYLES.border}; border-radius: ${this.BUBBLE_STYLES.borderRadius}; box-shadow: ${this.BUBBLE_STYLES.boxShadow}; color: ${this.BUBBLE_STYLES.color}; font-size: ${this.BUBBLE_STYLES.fontSize}; font-family: ${this.BUBBLE_STYLES.fontFamily}; padding: ${this.BUBBLE_STYLES.padding}; max-width: ${config.maxWidth ? config.maxWidth + 'px' : this.BUBBLE_STYLES.maxWidth}; min-width: ${this.BUBBLE_STYLES.minWidth}; z-index: ${this.BUBBLE_STYLES.zIndex}; pointer-events: auto; display: none; opacity: 0; transform: translateY(-10px) scale(0.95); transition: opacity 0.3s ease, transform 0.3s ease; `; // 添加类型特定样式 if (config.type === 'warning') { bubble.style.borderColor = 'rgba(255, 193, 7, 0.5)'; bubble.style.background = 'rgba(255, 193, 7, 0.15)'; bubble.style.boxShadow = '0 8px 32px rgba(255, 193, 7, 0.1)'; } else if (config.type === 'error') { bubble.style.borderColor = 'rgba(220, 53, 69, 0.5)'; bubble.style.background = 'rgba(220, 53, 69, 0.15)'; bubble.style.boxShadow = '0 8px 32px rgba(220, 53, 69, 0.1)'; } else if (config.type === 'success') { bubble.style.borderColor = 'rgba(40, 167, 69, 0.5)'; bubble.style.background = 'rgba(40, 167, 69, 0.15)'; bubble.style.boxShadow = '0 8px 32px rgba(40, 167, 69, 0.1)'; } bubble.innerHTML = ` <div class="bubble-header" style=" display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; font-weight: 600; "> <span class="bubble-title">${config.title}</span> <span class="bubble-close" style=" cursor: pointer; opacity: 0.7; font-size: 16px; line-height: 1; padding: 4px; border-radius: 4px; transition: opacity 0.2s; " data-bubble-id="${config.id}" data-action="close">✕</span> </div> <div class="bubble-content" style="line-height: 1.5;"> ${this.generateContentHTML(config.content)} </div> `; // 添加悬停效果 bubble.addEventListener('mouseenter', () => { bubble.style.transform = 'translateY(0) scale(1.02)'; bubble.style.boxShadow = bubble.style.boxShadow.replace('0.1)', '0.2)'); }); bubble.addEventListener('mouseleave', () => { bubble.style.transform = 'translateY(0) scale(1)'; bubble.style.boxShadow = bubble.style.boxShadow.replace('0.2)', '0.1)'); }); // 添加关闭按钮事件监听器 const closeButton = bubble.querySelector('[data-action="close"]'); if (closeButton) { closeButton.addEventListener('click', e => { e.stopPropagation(); this.hideBubble(config.id); // 触发关闭回调 if (config.onClose) { config.onClose(config.id); } }); } const container = document.getElementById('v2x-bubble-container'); if (container) { container.appendChild(bubble); } // 初始化视频播放器 if (config.content.videoUrl) { this.initializeHLS(); // 延迟执行,确保DOM元素已渲染 setTimeout(() => { this.setupVideoPlayer(bubble); }, 100); } return bubble; } /** * 生成内容HTML */ generateContentHTML(content) { let html = ''; // 状态显示 if (content.status) { const statusColors = { online: '#28a745', offline: '#dc3545', warning: '#ffc107', maintenance: '#6c757d', error: '#dc3545', moving: '#17a2b8', }; const statusLabels = { online: '在线', offline: '离线', warning: '警告', maintenance: '维护中', error: '错误', moving: '移动中', }; html += ` <div style=" display: flex; align-items: center; gap: 8px; margin-bottom: 12px; padding: 8px; background: rgba(255, 255, 255, 0.1); border-radius: 6px; "> <div style=" width: 8px; height: 8px; border-radius: 50%; background: ${statusColors[content.status]}; "></div> <span style="font-weight: 500;">${statusLabels[content.status]}</span> </div> `; } // 视频播放器 if (content.videoUrl) { html += this.createVideoPlayer(content.videoUrl, content.videoType); } // 数据显示 if (content.data) { html += '<div class="bubble-data">'; Object.entries(content.data).forEach(([key, value]) => { html += ` <div style=" display: flex; justify-content: space-between; margin-bottom: 6px; padding: 4px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.1); "> <span style="opacity: 0.8;">${key}:</span> <span style="font-weight: 500;">${value}</span> </div> `; }); html += '</div>'; } // 自定义HTML内容 if (content.html) { html += content.html; } // 操作按钮 if (content.actions && content.actions.length > 0) { html += '<div class="bubble-actions" style="margin-top: 12px; display: flex; gap: 8px;">'; content.actions.forEach(action => { const buttonStyles = { primary: 'background: rgba(0, 123, 255, 0.8); color: white;', secondary: 'background: rgba(255, 255, 255, 0.2); color: white;', danger: 'background: rgba(220, 53, 69, 0.8); color: white;', }; html += ` <button style=" ${buttonStyles[action.type || 'secondary']} border: none; padding: 6px 12px; border-radius: 4px; font-size: 12px; cursor: pointer; transition: all 0.2s; " onclick="${action.onClick}"> ${action.icon ? action.icon + ' ' : ''}${action.label} </button> `; }); html += '</div>'; } return html; } /** * 计算最佳位置(优先显示在下方) */ calculateOptimalPosition(config) { // 如果有手动偏移,直接使用 if (config.offset) { return { x: config.offset.x, y: config.offset.y, anchor: 'top', offset: { x: 0, y: 0 }, }; } // 获取目标在屏幕上的投影位置 const targetPosition = config.targetPosition || config.target.position; const screenPosition = this.worldToScreen(targetPosition); // 获取容器尺寸 const containerRect = this.container.getBoundingClientRect(); // 计算最佳锚点和偏移 const bubbleWidth = config.maxWidth || 320; // 估算气泡宽度 const bubbleHeight = config.content.videoUrl ? 300 : 200; // 有视频时增加高度 const margin = 20; // 边距 let anchor = 'top'; let x = screenPosition.x; let y = screenPosition.y; // 位置偏好逻辑(优先下方) const preference = config.positionPreference || 'bottom'; if (preference === 'bottom') { // 优先显示在下方 if (screenPosition.y + bubbleHeight + margin < containerRect.height) { anchor = 'top'; y = screenPosition.y + margin; } else { // 下方空间不足,显示在上方 anchor = 'bottom'; y = screenPosition.y - bubbleHeight - margin; } } else if (preference === 'top') { // 优先显示在上方 if (screenPosition.y - bubbleHeight - margin > 0) { anchor = 'bottom'; y = screenPosition.y - bubbleHeight - margin; } else { // 上方空间不足,显示在下方 anchor = 'top'; y = screenPosition.y + margin; } } else { // 自动选择(旧逻辑) if (screenPosition.y > containerRect.height / 2) { anchor = 'bottom'; y = screenPosition.y - bubbleHeight - margin; } else { anchor = 'top'; y = screenPosition.y + margin; } } // 水平位置调整(居中对齐设备) x = screenPosition.x - bubbleWidth / 2; // 确保不超出容器边界 if (x + bubbleWidth > containerRect.width - margin) { x = containerRect.width - bubbleWidth - margin; } if (x < margin) { x = margin; } // 确保垂直位置不超出边界 if (y < margin) { y = margin; } if (y + bubbleHeight > containerRect.height - margin) { y = containerRect.height - bubbleHeight - margin; } return { x, y, anchor, offset: { x: 0, y: 0 }, }; } /** * 世界坐标转屏幕坐标 */ worldToScreen(worldPosition) { const vector = worldPosition.clone(); vector.project(this.camera); const containerRect = this.container.getBoundingClientRect(); const x = (vector.x * 0.5 + 0.5) * containerRect.width; const y = (vector.y * -0.5 + 0.5) * containerRect.height; return { x, y }; } /** * 更新气泡位置 */ updateBubblePosition(instance) { if (!instance.visible) return; const position = this.calculateOptimalPosition(instance.config); instance.position = position; instance.element.style.left = position.x + 'px'; instance.element.style.top = position.y + 'px'; } /** * 更新所有气泡位置 */ updateAllBubblePositions() { this.bubbles.forEach(instance => { if (instance.visible) { this.updateBubblePosition(instance); } }); } /** * 初始化HLS.js用于视频播放 */ initializeHLS() { // 动态加载HLS.js if (typeof window !== 'undefined' && !window.Hls) { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest'; script.onload = () => { console.log('HLS.js 加载完成'); }; document.head.appendChild(script); } } /** * 创建视频播放器元素 */ createVideoPlayer(videoUrl, videoType = 'hls') { const videoId = `video-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; return ` <div class="bubble-video-container" style=" margin: 8px 0; border-radius: 8px; overflow: hidden; background: rgba(0, 0, 0, 0.8); "> <video id="${videoId}" controls muted preload="metadata" style=" width: 100%; height: 180px; object-fit: cover; display: block; " data-video-url="${videoUrl}" data-video-type="${videoType}" > <source src="${videoUrl}" type="application/x-mpegURL"> 您的浏览器不支持视频播放 </video> <div class="video-controls" style=" padding: 8px; background: rgba(0, 0, 0, 0.9); font-size: 12px; color: #fff; "> <div style="display: flex; justify-content: space-between; align-items: center;"> <span>🎥 ${videoType.toUpperCase()} 视频流</span> <button onclick="this.closest('.bubble-video-container').querySelector('video').load()" style=" background: rgba(255, 255, 255, 0.2); border: none; color: #fff; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 11px; ">重连</button> </div> </div> </div> `; } /** * 设置视频播放(支持HLS) */ setupVideoPlayer(container) { const videos = container.querySelectorAll('video[data-video-url]'); videos.forEach(element => { const video = element; const videoUrl = video.dataset.videoUrl; const videoType = video.dataset.videoType || 'hls'; if (videoType === 'hls' && videoUrl) { // 检查是否支持原生HLS if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = videoUrl; } // 使用HLS.js else if (window.Hls && window.Hls.isSupported()) { const HlsClass = window.Hls; const hls = new HlsClass({ enableWorker: true, lowLatencyMode: true, backBufferLength: 90, }); hls.loadSource(videoUrl); hls.attachMedia(video); hls.on(HlsClass.Events.MANIFEST_PARSED, () => { console.log('HLS 清单解析完成'); }); hls.on(HlsClass.Events.ERROR, (_event, data) => { console.warn('HLS 错误:', data); if (data.fatal) { switch (data.type) { case HlsClass.ErrorTypes.NETWORK_ERROR: console.log('网络错误,尝试恢复...'); hls.startLoad(); break; case HlsClass.ErrorTypes.MEDIA_ERROR: console.log('媒体错误,尝试恢复...'); hls.recoverMediaError(); break; default: console.log('致命错误,销毁HLS实例'); hls.destroy(); break; } } }); // 保存hls实例以便后续清理 video.hlsInstance = hls; } else { console.warn('不支持HLS播放'); video.style.display = 'none'; } } }); } /** * 启用/禁用气泡管理器 */ setEnabled(enabled) { this.bubbles.forEach(instance => { instance.element.style.display = enabled && instance.visible ? 'block' : 'none'; }); } /** * 获取所有气泡信息 */ getAllBubbles() { return Array.from(this.bubbles.entries()).map(([id, instance]) => ({ id, config: instance.config, visible: instance.visible, })); } /** * 清理所有气泡 */ dispose() { this.bubbles.forEach(instance => { // 清理视频播放器实例 const videos = instance.element.querySelectorAll('video[data-video-url]'); videos.forEach((video) => { if (video.hlsInstance) { video.hlsInstance.destroy(); } }); instance.element.remove(); }); this.bubbles.clear(); const container = document.getElementById('v2x-bubble-container'); if (container) { container.remove(); } } } // 导出工厂函数 function createBubbleManager(camera, container) { return new BubbleManager(camera, container); } var BubbleManager$1 = /*#__PURE__*/Object.freeze({ __proto__: null, BubbleManager: BubbleManager, createBubbleManager: createBubbleManager }); /** * @license * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ const REVISION = '177'; /** * Represents mouse buttons and interaction types in context of controls. * * @type {ConstantsMouse} * @constant */ const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; /** * Represents touch interaction types in context of controls. * * @type {ConstantsTouch} * @constant */ const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; /** * Disables face culling. * * @type {number} * @constant */ const CullFaceNone = 0; /** * Culls back faces. * * @type {number} * @constant */ const CullFaceBack = 1; /** * Culls front faces. * * @type {number} * @constant */ const CullFaceFront = 2; /** * Culls both front and back faces. * * @type {number} * @constant */ const CullFaceFrontBack = 3; /** * Gives unfiltered shadow maps - fastest, but lowest quality. * * @type {number} * @constant */ const BasicShadowMap = 0; /** * Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm. * * @type {number} * @constant */ const PCFShadowMap = 1; /** * Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with * better soft shadows especially when using low-resolution shadow maps. * * @type {number} * @constant */ const PCFSoftShadowMap = 2; /** * Filters shadow maps using the Variance Shadow Map (VSM) algorithm. * When using VSMShadowMap all shadow receivers will also cast shadows. * * @type {number} * @constant */ const VSMShadowMap = 3; /** * Only front faces are rendered. * * @type {number} * @constant */ const FrontSide = 0; /** * Only back faces are rendered. * * @type {number} * @constant */ const BackSide = 1; /** * Both front and back faces are rendered. * * @type {number} * @constant */ const DoubleSide = 2; /** * No blending is performed which effectively disables * alpha transparency. * * @type {number} * @constant */ const NoBlending = 0; /** * The default blending. * * @type {number} * @constant */ const NormalBlending = 1; /** * Represents additive blending. * * @type {number} * @constant */ const AdditiveBlending = 2; /** * Represents subtractive blending. * * @type {number} * @constant */ const SubtractiveBlending = 3; /** * Represents multiply blending. * * @type {number} * @constant */ const MultiplyBlending = 4; /** * Represents custom blending. * * @type {number} * @constant */ const CustomBlending = 5; /** * A `source + destination` blending equation. * * @type {number} * @constant */ const AddEquation = 100; /** * A `source - destination` blending equation. * * @type {number} * @constant */ const SubtractEquation = 101; /** * A `destination - source` blending equation. * * @type {number} * @constant */ const ReverseSubtractEquation = 102; /** * A blend equation that uses the minimum of source and destination. * * @type {number} * @constant */ const MinEquation = 103; /** * A blend equation that uses the maximum of source and destination. * * @type {number} * @constant */ const MaxEquation = 104; /** * Multiplies all colors by `0`. * * @type {number} * @constant */ const ZeroFactor = 200; /** * Multiplies all colors by `1`. * * @type {number} * @constant */ const OneFactor = 201; /** * Multiplies all colors by the source colors. * * @type {number} * @constant */ const SrcColorFactor = 202; /** * Multiplies all colors by `1` minus each source color. * * @type {number} * @constant */ const OneMinusSrcColorFactor = 203; /** * Multiplies all colors by the source alpha value. * * @type {number} * @constant */ const SrcAlphaFactor = 204; /** * Multiplies all colors by 1 minus the source alpha value. * * @type {number} * @constant */ const OneMinusSrcAlphaFactor = 205; /** * Multiplies all colors by the destination alpha value. * * @type {number} * @constant */ const DstAlphaFactor = 206; /** * Multiplies all colors by `1` minus the destination alpha value. * * @type {number} * @constant */ const OneMinusDstAlphaFactor = 207; /** * Multiplies all colors by the destination color. * * @type {number} * @constant */ const DstColorFactor = 208; /** * Multiplies all colors by `1` minus each destination color. * * @type {number} * @constant */ const OneMinusDstColorFactor = 209; /** * Multiplies the RGB colors by the smaller of either the source alpha * value or the value of `1` minus the destination alpha value. The alpha * value is multiplied by `1`. * * @type {number} * @constant */ const SrcAlphaSaturateFactor = 210; /** * Multiplies all colors by a constant color. * * @type {number} * @constant */ const ConstantColorFactor = 211; /** * Multiplies all colors by `1` minus a constant color. * * @type {number} * @constant */ const OneMinusConstantColorFactor = 212; /** * Multiplies all colors by a constant alpha value. * * @type {number} * @constant */ const ConstantAlphaFactor = 213; /** * Multiplies all colors by 1 minus a constant alpha value. * * @type {number} * @constant */ const OneMinusConstantAlphaFactor = 214; /** * Never pass. * * @type {number} * @constant */ const NeverDepth = 0; /** * Always pass. * * @type {number} * @constant */ const AlwaysDepth = 1; /** * Pass if the incoming value is less than the depth buffer value. * * @type {number} * @constant */ const LessDepth = 2; /** * Pass if the incoming value is less than or equal to the depth buffer value. * * @type {number} * @constant */ const LessEqualDepth = 3; /** * Pass if the incoming value equals the depth buffer value. * * @type {number} * @constant */ const EqualDepth = 4; /** * Pass if the incoming value is greater than or equal to the depth buffer value. * * @type {number} * @constant */ const GreaterEqualDepth = 5; /** * Pass if the incoming value is greater than the depth buffer value. * * @type {number} * @constant */ const GreaterDepth = 6; /** * Pass if the incoming value is not equal to the depth buffer value. * * @type {number} * @constant */ const NotEqualDepth = 7; /** * Multiplies the environment map color with the surface color. * * @type {number} * @constant */ const MultiplyOperation = 0; /** * Uses reflectivity to blend between the two colors. * * @type {number} * @constant */ const MixOperation = 1; /** * Adds the two colors. * * @type {number} * @constant */ const AddOperation = 2; /** * No tone mapping is applied. * * @type {number} * @constant */ const NoToneMapping = 0; /** * Linear tone mapping. * * @type {number} * @constant */ const LinearToneMapping = 1; /** * Reinhard tone mapping. * * @type {number} * @constant */ const ReinhardToneMapping = 2; /** * Cineon tone mapping. * * @type {number} * @constant */ const CineonToneMapping = 3; /** * ACES Filmic tone mapping. * * @type {number} * @constant */ const ACESFilmicToneMapping = 4; /** * Custom tone mapping. * * Expects a custom implementation by modifying shader code of the material's fragment shader. * * @type {number} * @constant */ const CustomToneMapping = 5; /** * AgX tone mapping. * * @type {number} * @constant */ const AgXToneMapping = 6; /** * Neutral tone mapping. * * Implementation based on the Khronos 3D Commerce Group standard tone mapping. * * @type {number} * @constant */ const NeutralToneMapping = 7; /** * The skinned mesh shares the same world space as the skeleton. * * @type {string} * @constant */ const AttachedBindMode = 'attached'; /** * The skinned mesh does not share the same world space as the skeleton. * This is useful when a skeleton is shared across multiple skinned meshes. * * @type {string} * @constant */ const DetachedBindMode = 'detached'; /** * Maps textures using the geometry's UV coordinates. * * @type {number} * @constant */ const UVMapping = 300; /** * Reflection mapping for cube textures. * * @type {number} * @constant */ const CubeReflectionMapping = 301; /** * Refraction mapping for cube textures. * * @type {number} * @constant */ const CubeRefractionMapping = 302; /** * Reflection mapping for equirectangular textures. * * @type {number} * @constant */ const EquirectangularReflectionMapping = 303; /** * Refraction mapping for equirectangular textures. * * @type {number} * @constant */ const EquirectangularRefractionMapping = 304; /** * Reflection mapping for PMREM textures. * * @type {number} * @constant */ const CubeUVReflectionMapping = 306; /** * The texture will simply repeat to infinity. * * @type {number} * @constant */ const RepeatWrapping = 1000; /** * The last pixel of the texture stretches to the edge of the mesh. * * @type {number} * @constant */ const ClampToEdgeWrapping = 1001; /** * The texture will repeats to infinity, mirroring on each repeat. * * @type {number} * @constant */ const MirroredRepeatWrapping = 1002; /** * Returns the value of the texture element that is nearest (in Manhattan distance) * to the specified texture coordinates. * * @type {number} * @constant */ const NearestFilter = 1003; /** * Chooses the mipmap that most closely matches the size of the pixel being textured * and uses the `NearestFilter` criterion (the texel nearest to the center of the pixel) * to produce a texture value. * * @type {number} * @constant */ const NearestMipmapNearestFilter = 1004; const NearestMipMapNearestFilter = 1004; // legacy /** * Chooses the two mipmaps that most closely match the size of the pixel being textured and * uses the `NearestFilter` criterion to produce a texture value from each mipmap. * The final texture value is a weighted average of those two values. * * @type {number} * @constant */ const NearestMipmapLinearFilter = 1005; const NearestMipMapLinearFilter = 1005; // legacy /** * Returns the weighted average of the four texture elements that are closest to the specified * texture coordinates, and can include items wrapped or repeated from other parts of a texture, * depending on the values of `wrapS` and `wrapT`, and on the exact mapping. * * @type {number} * @constant */ const LinearFilter = 1006; /** * Chooses the mipmap that most closely matches the size of the pixel being textured and uses * the `LinearFilter` criterion (a weighted average of the four texels that are closest to the * center of the pixel) to produce a texture value. * * @type {number} * @constant */ const LinearMipmapNearestFilter = 1007; const LinearMipMapNearestFilter = 1007; // legacy /** * Chooses the two mipmaps that most closely match the size of the pixel being textured and uses * the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value * is a weighted average of those two values. * * @type {number} * @constant */ const LinearMipmapLinearFilter = 1008; const LinearMipMapLinearFilter = 1008; // legacy /** * An unsigned byte data type for textures. * * @type {number} * @constant */ const UnsignedByteType = 1009; /** * A byte data type for textures. * * @type {number} * @constant */ const ByteType = 1010; /** * A short data type for textures. * * @type {number} * @constant */ const ShortType = 1011; /** * An unsigned short data type for textures. * * @type {number} * @constant */ const UnsignedShortType = 1012; /** * An int data type for textures. * * @type {number} * @constant */ const IntType = 1013; /** * An unsigned int data type for textures. * * @type {number} * @constant */ const UnsignedIntType = 1014; /** * A float data type for textures. * * @type {number} * @constant */ const FloatType = 1015; /** * A half float data type for textures. * * @type {number} * @constant */ const HalfFloatType = 1016; /** * An unsigned short 4_4_4_4 (packed) data type for textures. * * @type {number} * @constant */ const UnsignedShort4444Type = 1017; /** * An unsigned short 5_5_5_1 (packed) data type for textures. * * @type {number} * @constant */ const UnsignedShort5551Type = 1018; /** * An unsigned int 24_8 data type for textures. * * @type {number} * @constant */ const UnsignedInt248Type = 1020; /** * An unsigned int 5_9_9_9 (packed) data type for textures. * * @type {number} * @constant */ const UnsignedInt5999Type = 35902; /** * Discards the red, green and blue components and reads just the alpha component. * * @type {number} * @constant */ const AlphaFormat = 1021; /** * Discards the alpha component and reads the red, green and blue component. * * @type {number} * @constant */ const RGBFormat = 1022; /** * Reads the red, green, blue and alpha components. * * @type {number} * @constant */ const RGBAFormat = 1023; /** * Reads each element as a single depth value, converts it to floating point, and clamps to the range `[0,1]`. * * @type {number} * @constant */ const DepthFormat = 1026; /** * Reads each element is a pair of depth and stencil values. The depth component of the pair is interpreted as * in `DepthFormat`. The stencil component is interpreted based on the depth + stencil internal format. * * @type {number} * @constant */ const DepthStencilFormat = 1027; /** * Discards the green, blue and alpha components and reads just the red component. * * @type {number} * @constant */ const RedFormat = 1028; /** * Discards the green, blue and alpha components and reads just the red component. The texels are read as integers instead of floating point. * * @type {number} * @constant */ const RedIntegerFormat = 1029; /** * Discards the alpha, and blue components and reads the red, and green components. * * @type {number} * @constant */ const RGFormat = 1030; /** * Discards the alpha, and blue components and reads the red, and green components. The texels are read as integers instead of floating point. * * @type {number} * @constant */ const RGIntegerFormat = 1031; /** * Discards the alpha component and reads the red, green and blue component. The texels are read as integers instead of floating point. * * @type {number} * @constant */ const RGBIntegerFormat = 1032; /** * Reads the red, green, blue and alpha components. The texels are read as integers instead of floating point. * * @type {number} * @constant */ const RGBAIntegerFormat = 1033; /** * A DXT1-compressed image in an RGB image format. * * @type {number} * @constant */ const RGB_S3TC_DXT1_Format = 33776; /** * A DXT1-compressed image in an RGB image format with a simple on/off alpha value. * * @type {number} * @constant */ const RGBA_S3TC_DXT1_Format = 33777; /** * A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression. * * @type {number} * @constant */ const RGBA_S3TC_DXT3_Format = 33778; /** * A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3 * compression in how the alpha compression is done. * * @type {number} * @constant */ const RGBA_S3TC_DXT5_Format = 33779; /** * PVRTC RGB compression in 4-bit mode. One block for each 4×4 pixels. * * @type {number} * @constant */ const RGB_PVRTC_4BPPV1_Format = 35840; /** * PVRTC RGB compression in 2-bit mode. One block for each 8×4 pixels. * * @type {number} * @constant */ const RGB_PVRTC_2BPPV1_Format = 35841; /** * PVRTC RGBA compression in 4-bit mode. One block for each 4×4 pixels. * * @type {number} * @constant */ const RGBA_PVRTC_4BPPV1_Format = 35842; /** * PVRTC RGBA compression in 2-bit mode. One block for each 8×4 pixels. * * @type {number} * @constant */ const RGBA_PVRTC_2BPPV1_Format = 35843; /** * ETC1 RGB format. * * @type {number} * @constant */ const RGB_ETC1_Format = 36196; /** * ETC2 RGB format. * * @type {number} * @constant */ const RGB_ETC2_Format = 37492; /** * ETC2 RGBA format. * * @type {number} * @constant */ const RGBA_ETC2_EAC_Format = 37496; /** * ASTC RGBA 4x4 format. * * @type {number} * @constant */ const RGBA_ASTC_4x4_Format = 37808; /** * ASTC RGBA 5x4 format. * * @type {number} * @constant */ const RGBA_ASTC_5x4_Format = 37809; /** * ASTC RGBA 5x5 format. * * @type {number} * @constant */ const RGBA_ASTC_5x5_Format = 37810; /** * ASTC RGBA 6x5 format. * * @type {number} * @constant */ const RGBA_ASTC_6x5_Format = 37811; /** * ASTC RGBA 6x6 format. * * @type {number} * @constant */ const RGBA_ASTC_6x6_Format = 37812; /** * ASTC RGBA 8x5 format. * * @type {number} * @constant */ const RGBA_ASTC_8x5_Format = 37813; /** * ASTC RGBA 8x6 format. * * @type {number} * @constant */ const RGBA_ASTC_8x6_Format = 37814; /** * ASTC RGBA 8x8 format. * * @type {number} * @constant */ const RGBA_ASTC_8x8_Format = 37815; /** * ASTC RGBA 10x5 format. * * @type {number} * @constant */ const RGBA_ASTC_10x5_Format = 37816; /** * ASTC RGBA 10x6 format. * * @type {number} * @constant */ const RGBA_ASTC_10x6_Format = 37817; /** * ASTC RGBA 10x8 format. * * @type {number} * @constant */ const RGBA_ASTC_10x8_Format = 37818; /** * ASTC RGBA 10x10 format. * * @type {number} * @constant */ const RGBA_ASTC_10x10_Format = 37819; /** * ASTC RGBA 12x10 format. * * @type {number} * @constant */ const RGBA_ASTC_12x10_Format = 37820; /** * ASTC RGBA 12x12 format. * * @type {number} * @constant */ const RGBA_ASTC_12x12_Format = 37821; /** * BPTC RGBA format. * * @type {number} * @constant */ const RGBA_BPTC_Format = 36492; /** * BPTC Signed RGB format. * * @type {number} * @constant */ const RGB_BPTC_SIGNED_Format = 36494; /** * BPTC Unsigned RGB format. * * @type {number} * @constant */ const RGB_BPTC_UNSIGNED_Format = 36495; /** * RGTC1 Red format. * * @type {number} * @constant */ const RED_RGTC1_Format = 36283; /** * RGTC1 Signed Red format. * * @type {number} * @constant */ const SIGNED_RED_RGTC1_Format = 36284; /** * RGTC2 Red Green format. * * @type {number} * @constant */ const RED_GREEN_RGTC2_Format = 36285; /** * RGTC2 Signed Red Green format. * * @type {number} * @constant */ const SIGNED_RED_GREEN_RGTC2_Format = 36286; /** * Animations are played once. * * @type {number} * @constant */ const LoopOnce = 2200; /** * Animations are played with a chosen number of repetitions, each time jumping from * the end of the clip directly to its beginning. * * @type {number} * @constant */ const LoopRepeat = 2201; /** * Animations are played with a chosen number of repetitions, alternately playing forward * and backward. * * @type {number} * @constant */ const LoopPingPong = 2202; /** * Discrete interpolation mode for keyframe tracks. * * @type {number} * @constant */ const InterpolateDiscrete = 2300; /** * Linear interpolation mode for keyframe tracks. * * @type {number} * @constant */ const InterpolateLinear = 2301; /** * Smooth interpolation mode for keyframe tracks. * * @type {number} * @constant */ const InterpolateSmooth = 2302; /** * Zero curvature ending for animations. * * @type {number} * @constant */ const ZeroCurvatureEnding = 2400; /** * Zero slope ending for animations. * * @type {number} * @constant */ const ZeroSlopeEnding = 2401; /** * Wrap around ending for animations. * * @type {number} * @constant */ const WrapAroundEnding = 2402; /** * Default animation blend mode. * * @type {number} * @constant */ const NormalAnimationBlendMode = 2500; /** * Additive animation blend mode. Can be used to layer motions on top of * each other to build complex performances from smaller re-usable assets. * * @type {number} * @constant */ const AdditiveAnimationBlendMode = 2501; /** * For every three vertices draw a single triangle. * * @type {number} * @constant */ const TrianglesDrawMode = 0; /** * For each vertex draw a triangle from the last three vertices. * * @type {number} * @constant */ const TriangleStripDrawMode = 1; /** * For each vertex draw a triangle from the first vertex and the last two vertices. * * @type {number} * @constant */ const TriangleFanDrawMode = 2; /** * Basic depth packing. * * @type {number} * @constant */ const BasicDepthPacking = 3200; /** * A depth value is packed into 32 bit RGBA. * * @type {number} * @constant */ const RGBADepthPacking = 3201; /** * A depth value is packed into 24 bit RGB. * * @type {number} * @constant */ const RGBDepthPacking = 3202; /** * A depth value is packed into 16 bit RG. * * @type {number} * @constant */ const RGDepthPacking = 3203; /** * Normal information is relative to the underlying surface. * * @type {number} * @constant */ const TangentSpaceNormalMap = 0; /** * Normal information is relative to the object orientation. * * @type {number} * @constant */ const ObjectSpaceNormalMap = 1; // Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. /** * No color space. * * @type {string} * @constant */ const NoColorSpace = ''; /** * sRGB color space. * * @type {string} * @constant */ const SRGBColorSpace = 'srgb'; /** * sRGB-linear color space. * * @type {string} * @constant */ const LinearSRGBColorSpace = 'srgb-linear'; /** * Linear transfer function. * * @type {string} * @constant */ const LinearTransfer = 'linear'; /** * sRGB transfer function. * * @type {string} * @constant */ const SRGBTransfer = 'srgb'; /** * Sets the stencil buffer value to `0`. * * @type {number} * @constant */ const ZeroStencilOp = 0; /** * Keeps the current value. * * @type {number} * @constant */ const KeepStencilOp = 7680; /** * Sets the stencil buffer value to the specified reference value. * * @type {number} * @constant */ const ReplaceStencilOp = 7681; /** * Increments the current stencil buffer value. Clamps to the maximum representable unsigned value. * * @type {number} * @constant */ const IncrementStencilOp = 7682; /** * Decrements the current stencil buffer value. Clamps to `0`. * * @type {number} * @constant */ const DecrementStencilOp = 7683; /** * Increments the current stencil buffer value. Wraps stencil buffer value to zero when incrementing * the maximum representable unsigned value. * * @type {number} * @constant */ const IncrementWrapStencilOp = 34055; /** * Decrements the current stencil buffer value. Wraps stencil buffer value to the maximum representable * unsigned value when decrementing a stencil buffer value of `0`. * * @type {number} * @constant */ const DecrementWrapStencilOp = 34056; /** * Inverts the current stencil buffer value bitwise. * * @type {number} * @constant */ const InvertStencilOp = 5386; /** * Will never return true. * * @type {number} * @constant */ const NeverStencilFunc = 512; /** * Will return true if the stencil reference value is less than the current stencil value. * * @type {number} * @constant */ const LessStencilFunc = 513; /** * Will return true if the stencil reference value is equal to the current stencil value. * * @type {number} * @constant */ const EqualStencilFunc = 514; /** * Will return true if the stencil reference value is less than or equal to the current stencil value. * * @type {number} * @constant */ const LessEqualStencilFunc = 515; /** * Will return true if the stencil reference value is greater than the current stencil value. * * @type {number} * @constant */ const GreaterStencilFunc = 516; /** * Will return true if the stencil reference value is not equal to the current stencil value. * * @type {number} * @constant */ const NotEqualStencilFunc = 517; /** * Will return true if the stencil reference value is greater than or equal to the current stencil value. * * @type {number} * @constant */ const GreaterEqualStencilFunc = 518; /** * Will always return true. * * @type {number} * @constant */ const AlwaysStencilFunc = 519; /** * Never pass. * * @type {number} * @constant */ const NeverCompare = 512; /** * Pass if the incoming value is less than the texture value. * * @type {number} * @constant */ const LessCompare = 513; /** * Pass if the incoming value equals the texture value. * * @type {number} * @constant */ const EqualCompare = 514; /** * Pass if the incoming value is less than or equal to the texture value. * * @type {number} * @constant */ const LessEqualCompare = 515; /** * Pass if the incoming value is greater than the texture value. * * @type {number} * @constant */ const GreaterCompare = 516; /** * Pass if the incoming value is not equal to the texture value. * * @type {number} * @constant */ const NotEqualCompare = 517; /** * Pass if the incoming value is greater than or equal to the texture value. * * @type {number} * @constant */ const GreaterEqualCompare = 518; /** * Always pass. * * @type {number} * @constant */ const AlwaysCompare = 519; /** * The contents are intended to be specified once by the application, and used many * times as the source for drawing and image specification commands. * * @type {number} * @constant */ const StaticDrawUsage = 35044; /** * The contents are intended to be respecified repeatedly by the application, and * used many times as the source for drawing and image specification commands. * * @type {number} * @constant */ const DynamicDrawUsage = 35048; /** * The contents are intended to be specified once by the application, and used at most * a few times as the source for drawing and image specification commands. * * @type {number} * @constant */ const StreamDrawUsage = 35040; /** * The contents are intended to be specified once by reading data from the 3D API, and queried * many times by the application. * * @type {number} * @constant */ const StaticReadUsage = 35045; /** * The contents are intended to be respecified repeatedly by reading data from the 3D API, and queried * many times by the application. * * @type {number} * @constant */ const DynamicReadUsage = 35049; /** * The contents are intended to be specified once by reading data from the 3D API, and queried at most * a few times by the application * * @type {number} * @constant */ const StreamReadUsage = 35041; /** * The contents are intended to be specified once by reading data from the 3D API, and used many times as * the source for WebGL drawing and image specification commands. * * @type {number} * @constant */ const StaticCopyUsage = 35046; /** * The contents are intended to be respecified repeatedly by reading data from the 3D API, and used many times * as the source for WebGL drawing and image specification commands. * * @type {number} * @constant */ const DynamicCopyUsage = 35050; /** * The contents are intended to be specified once by reading data from the 3D API, and used at most a few times * as the source for WebGL drawing and image specification commands. * * @type {number} * @constant */ const StreamCopyUsage = 35042; /** * GLSL 1 shader code. * * @type {string} * @constant */ const GLSL1 = '100'; /** * GLSL 3 shader code. * * @type {string} * @constant */ const GLSL3 = '300 es'; /** * WebGL coordinate system. * * @type {number} * @constant */ const WebGLCoordinateSystem = 2000; /** * WebGPU coordinate system. * * @type {number} * @constant */ const WebGPUCoordinateSystem = 2001; /** * Represents the different timestamp query types. * * @type {ConstantsTimestampQuery} * @constant */ const TimestampQuery = { COMPUTE: 'compute', RENDER: 'render' }; /** * Represents mouse buttons and interaction types in context of controls. * * @type {ConstantsInterpolationSamplingType} * @constant */ const InterpolationSamplingType = { PERSPECTIVE: 'perspective', LINEAR: 'linear', FLAT: 'flat' }; /** * Represents the different interpolation sampling modes. * * @type {ConstantsInterpolationSamplingMode} * @constant */ const InterpolationSamplingMode = { NORMAL: 'normal', CENTROID: 'centroid', SAMPLE: 'sample', FLAT_FIRST: 'flat first', FLAT_EITHER: 'flat either' }; /** * This type represents mouse buttons and interaction types in context of controls. * * @typedef {Object} ConstantsMouse * @property {number} MIDDLE - The left mouse button. * @property {number} LEFT - The middle mouse button. * @property {number} RIGHT - The right mouse button. * @property {number} ROTATE - A rotate interaction. * @property {number} DOLLY - A dolly interaction. * @property {number} PAN - A pan interaction. **/ /** * This type represents touch interaction types in context of controls. * * @typedef {Object} ConstantsTouch * @property {number} ROTATE - A rotate interaction. * @property {number} PAN - A pan interaction. * @property {number} DOLLY_PAN - The dolly-pan interaction. * @property {number} DOLLY_ROTATE