UNPKG

avansel

Version:

Free OpenSource ThreeJS Javascript Virtual Tours viewer

169 lines (146 loc) 5.35 kB
import { BoxGeometry, CanvasTexture, Mesh, MeshBasicMaterial, BackSide, ImageLoader } from 'three'; import { pano } from '../../../config.json' enum ImageType { Sphere, Cylinder, Cubestrip } enum StripType { Type1x6, Type2x3, Type3x2, Type6x1 } interface PreviewSettings { type?: ImageType, stripType?: StripType url?: string, striporder?: string, size: number } const striporderDefault = 'rludfb' let preview: Mesh let settings: PreviewSettings let contexts: Array<CanvasRenderingContext2D> = [] let materials: Array<MeshBasicMaterial> = [] /* let size, sides = {} let positions const format = 'udlrfb' */ const colorSide = (side: string) => { return { u: '#8888aa', d: '#88aa88', l: '#aa8888', r: '#88aaaa', f: '#aaaa88', b: '#aaaaaa', }[side] } const getSides = () => { const striporder = settings.striporder ?? striporderDefault return Array.from(striporder) } const getCanvas = (side: string) => { const canvas = document.createElement( 'canvas' ) const size = settings.size ?? 1024 canvas.width = size canvas.height = size const context = canvas.getContext("2d") context.fillStyle = colorSide(side) context.fillRect(0, 0, size, size) context.rect(20, 20, size - 40, size - 40) context.strokeStyle = "#ffffff"; context.stroke(); context.fillStyle = "#ffffff" context.font = "48px Arial"; context.textAlign = "center" context.fillText('side: ' + side, size / 2, size / 2) return canvas } const getMaterial = (canvas: HTMLCanvasElement) => { const texture = new CanvasTexture(canvas) const material = new MeshBasicMaterial( { map: texture, depthWrite: true } ) material.side = BackSide material.opacity = 1 material.transparent = true return material } const materialsEmpty = () => { const materials = [] const sides = getSides() for(var i = 0; i < sides.length; i ++){ const side = sides[i] const canvas = getCanvas(side) contexts.push(canvas.getContext('2d')) materials.push(getMaterial(canvas)) } return materials } const settingsBy = (img: HTMLImageElement): PreviewSettings => { const width = img.width const height = img.height if(height / width == 6){ if(!settings.type) settings.type = ImageType.Cubestrip if(!settings.stripType) settings.stripType = StripType.Type1x6 if(!settings.size) settings.size = width }else if(height / width == 1.5){ if(!settings.type) settings.type = ImageType.Cubestrip if(!settings.stripType) settings.stripType = StripType.Type2x3 if(!settings.size) settings.size = width / 2 }else if(width / height == 1.5){ if(!settings.type) settings.type = ImageType.Cubestrip if(!settings.stripType) settings.stripType = StripType.Type3x2 if(!settings.size) settings.size = height / 2 }else if(width / height == 6){ if(!settings.type) settings.type = ImageType.Cubestrip if(!settings.stripType) settings.stripType = StripType.Type6x1 if(!settings.size) settings.size = height }else if(width / height == 2){ if(!settings.type) settings.type = ImageType.Sphere } if(!settings.type) settings.type = ImageType.Cylinder if(!settings.size) settings.size = pano.tileBase return settings } const onImageLoad = (img: HTMLImageElement) => { const sides = Array.from(striporderDefault) const materials = [] const size = settings.size settings = settingsBy(img) for(var i = 0; i < sides.length; i ++){ const side = sides[i] const index = settings.striporder.indexOf(sides[i]) const canvas = getCanvas(side) const context = canvas.getContext('2d') context.drawImage( img, 0, size * index, size, size, 0, 0, size, size ) materials.push(getMaterial(canvas)) } return materials } const onError = (e: ErrorEvent) => { console.log(e) } const load = async (src: string): Promise<HTMLImageElement> => { const loader = new ImageLoader() return new Promise<HTMLImageElement>((resolve, reject) => { loader.load(src, img => resolve(img), undefined, e => reject(e)) }) } async function createPreview(data: PreviewSettings): Promise<Mesh> { settings = data return new Promise<Mesh>((resolve, reject) => { const boxSize = pano.tileBase + pano.maxLevels + 1 const geometry = new BoxGeometry(boxSize, boxSize, boxSize) if(settings.url || settings.type){ if(!settings.type){ load('/tiles/preview.jpg').then(img => { materials = onImageLoad(img) preview = new Mesh(geometry, materials); preview.scale.x = -1 preview.renderOrder = 1 resolve(preview) }) } }else{ materials = materialsEmpty() preview = new Mesh(geometry, materials); preview.scale.x = -1 preview.renderOrder = 1 resolve(preview) } }) } export { createPreview };