UNPKG

@damienmortini/three

Version:
96 lines (73 loc) 3.01 kB
import { Color, DoubleSide, LinearFilter, Mesh, Object3D, PlaneGeometry, Texture } from '../../../three/src/Three.js'; import THREEShaderMaterial from './THREEShaderMaterial.js'; const CACHED_IMAGES = new Map(); export default class Sprite extends Object3D { constructor(image, { data, frame, scale = 1 } = {}) { super(); this._data = data; this._image = image; this._scale = scale; // Optimise images decoding let canvas = CACHED_IMAGES.get(this.image); if (!canvas) { canvas = document.createElement('canvas'); canvas.width = this.image.width; canvas.height = this.image.height; const context = canvas.getContext('2d'); context.drawImage(this.image, 0, 0); CACHED_IMAGES.set(this.image, canvas); } this.mesh = new Mesh(new PlaneGeometry(1, 1), new THREEShaderMaterial({ type: 'basic', transparent: true, side: DoubleSide, uniforms: { diffuse: new Color(0xffffff), map: new Texture(canvas), }, })); this.mesh.scale.x = canvas.width * this._scale; this.mesh.scale.y = canvas.height * this._scale; this.mesh.material.map.minFilter = LinearFilter; this.mesh.material.map.generateMipmaps = false; this.mesh.material.map.needsUpdate = true; this.add(this.mesh); if (frame) { this.frame = frame; } } get image() { return this._image; } get data() { return this._data; } set material(value) { this.mesh.material = value; this.frame = this.frame; } get material() { return this.mesh.material; } set frame(value) { if (!this.data) { return; } this._frame = value; const offsetRepeat = this.mesh.material.offsetRepeat; const frameData = this.data.frames[this._frame]; offsetRepeat.z = (frameData.rotated ? frameData.frame.h : frameData.frame.w) / this.image.width; offsetRepeat.w = (frameData.rotated ? frameData.frame.w : frameData.frame.h) / this.image.height; offsetRepeat.x = frameData.frame.x / this.image.width; offsetRepeat.y = 1.0 - frameData.frame.y / this.image.height - offsetRepeat.w; const scale = 1 / parseFloat(this.data.meta.scale); this.mesh.scale.x = (frameData.rotated ? frameData.frame.h : frameData.frame.w) * scale * this._scale; this.mesh.scale.y = (frameData.rotated ? frameData.frame.w : frameData.frame.h) * scale * this._scale; this.mesh.position.x = (-(frameData.sourceSize.w - frameData.frame.w) * 0.5 + frameData.spriteSourceSize.x + frameData.sourceSize.w * (0.5 - frameData.pivot.x)) * scale * this._scale; this.mesh.position.y = ((frameData.sourceSize.h - frameData.frame.h) * 0.5 - frameData.spriteSourceSize.y - frameData.sourceSize.h * (0.5 - frameData.pivot.y)) * scale * this._scale; this.mesh.rotation.z = frameData.rotated ? Math.PI * 0.5 : 0; } get frame() { return this._frame; } }