1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00
This commit is contained in:
Kevin Levron 2021-04-21 18:20:34 +02:00
parent c82430eb39
commit 7cab6b5a79
5 changed files with 147 additions and 140 deletions

View File

@ -1,69 +0,0 @@
import { defineComponent, watch } from 'vue';
import { DoubleSide, MeshBasicMaterial, PlaneGeometry, TextureLoader } from 'three';
import Mesh from './Mesh.js';
export default defineComponent({
emits: ['loaded'],
extends: Mesh,
props: {
src: String,
width: Number,
height: Number,
keepSize: Boolean,
},
created() {
this.createGeometry();
this.createMaterial();
this.initMesh();
watch(() => this.src, this.refreshTexture);
['width', 'height'].forEach(p => {
watch(() => this[p], this.resize);
});
if (this.keepSize) this.three.onAfterResize(this.resize);
},
methods: {
createGeometry() {
this.geometry = new PlaneGeometry(1, 1, 1, 1);
},
createMaterial() {
this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() });
},
loadTexture() {
return new TextureLoader().load(this.src, this.onLoaded);
},
refreshTexture() {
if (this.texture) this.texture.dispose();
this.material.map = this.loadTexture();
this.material.needsUpdate = true;
},
onLoaded(texture) {
this.texture = texture;
this.resize();
this.$emit('loaded');
},
resize() {
if (!this.texture) return;
const screen = this.three.size;
const iW = this.texture.image.width;
const iH = this.texture.image.height;
const iRatio = iW / iH;
let w, h;
if (this.width && this.height) {
w = this.width * screen.wWidth / screen.width;
h = this.height * screen.wHeight / screen.height;
} else if (this.width) {
w = this.width * screen.wWidth / screen.width;
h = w / iRatio;
} else if (this.height) {
h = this.height * screen.wHeight / screen.height;
w = h * iRatio;
}
this.mesh.scale.x = w;
this.mesh.scale.y = h;
},
},
__hmrId: 'Image',
});

80
src/meshes/Image.ts Normal file
View File

@ -0,0 +1,80 @@
import { defineComponent, watch } from 'vue'
import { DoubleSide, MeshBasicMaterial, PlaneGeometry, Texture, TextureLoader } from 'three'
import Mesh, { MeshSetupInterface } from './Mesh'
import { object3DSetup } from '../core/Object3D'
interface ImageInterface extends MeshSetupInterface {
material?: MeshBasicMaterial
texture?: Texture
}
export default defineComponent({
emits: ['loaded'],
extends: Mesh,
props: {
src: { type: String, required: true },
width: Number,
height: Number,
keepSize: Boolean,
},
setup(): ImageInterface {
return object3DSetup()
},
created() {
this.geometry = new PlaneGeometry(1, 1, 1, 1)
this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() })
watch(() => this.src, this.refreshTexture);
['width', 'height'].forEach(p => {
// @ts-ignore
watch(() => this[p], this.resize)
})
this.resize()
if (this.keepSize) this.renderer.onResize(this.resize)
},
methods: {
loadTexture() {
return new TextureLoader().load(this.src, this.onLoaded)
},
refreshTexture() {
this.texture?.dispose()
if (this.material) {
this.material.map = this.loadTexture()
this.material.needsUpdate = true
}
},
onLoaded(texture: Texture) {
this.texture = texture
this.resize()
this.$emit('loaded', texture)
},
resize() {
if (!this.texture) return
const screen = this.renderer.size
const iW = this.texture.image.width
const iH = this.texture.image.height
const iRatio = iW / iH
let w = 1, h = 1
if (this.width && this.height) {
w = this.width * screen.wWidth / screen.width
h = this.height * screen.wHeight / screen.height
} else if (this.width) {
w = this.width * screen.wWidth / screen.width
h = w / iRatio
} else if (this.height) {
h = this.height * screen.wHeight / screen.height
w = h * iRatio
} else {
if (iRatio > 1) w = h * iRatio
else h = w / iRatio
}
if (this.mesh) {
this.mesh.scale.x = w
this.mesh.scale.y = h
}
},
},
__hmrId: 'Image',
})

View File

@ -1,8 +1,7 @@
import { ComponentPropsOptions, defineComponent, inject, watch } from 'vue' import { ComponentPropsOptions, defineComponent, watch } from 'vue'
import { BufferGeometry, Material, Mesh as TMesh } from 'three' import { BufferGeometry, Material, Mesh as TMesh } from 'three'
import Object3D from '../core/Object3D' import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
import { bindProp } from '../tools' import { bindProp } from '../tools'
import { ThreeInterface } from '../core/useThree'
export const pointerProps = { export const pointerProps = {
onPointerEnter: Function, onPointerEnter: Function,
@ -14,23 +13,18 @@ export const pointerProps = {
onClick: Function, onClick: Function,
} }
interface MeshSetupInterface { export interface MeshSetupInterface extends Object3DSetupInterface {
three?: ThreeInterface
mesh?: TMesh mesh?: TMesh
geometry?: BufferGeometry geometry?: BufferGeometry
material?: Material material?: Material
loading?: boolean loading?: boolean
} }
export interface MeshInterface { export interface MeshInterface extends MeshSetupInterface {
setGeometry(g: BufferGeometry): void
setMaterial(m: Material): void setMaterial(m: Material): void
} }
export function defaultSetup(): MeshSetupInterface {
const three = inject('three') as ThreeInterface
return { three }
}
const Mesh = defineComponent({ const Mesh = defineComponent({
name: 'Mesh', name: 'Mesh',
extends: Object3D, extends: Object3D,
@ -39,10 +33,8 @@ const Mesh = defineComponent({
receiveShadow: Boolean, receiveShadow: Boolean,
...pointerProps, ...pointerProps,
}, },
setup() { setup(): MeshSetupInterface {
return defaultSetup() return object3DSetup()
},
created() {
}, },
provide() { provide() {
return { return {
@ -114,8 +106,8 @@ export function meshComponent(name, props, createGeometry) {
name, name,
extends: Mesh, extends: Mesh,
props, props,
setup() { setup(): MeshSetupInterface {
return defaultSetup() return object3DSetup()
}, },
created() { created() {
this.createGeometry() this.createGeometry()

View File

@ -1,54 +0,0 @@
import { defineComponent } from 'vue';
import { Sprite, SpriteMaterial, TextureLoader } from 'three';
import Object3D from '../core/Object3D';
export default defineComponent({
extends: Object3D,
emits: ['loaded'],
props: {
src: String,
},
data() {
return {
loading: true,
};
},
created() {
this.texture = new TextureLoader().load(this.src, this.onLoaded);
this.material = new SpriteMaterial({ map: this.texture });
this.sprite = new Sprite(this.material);
this.geometry = this.sprite.geometry;
this.initObject3D(this.sprite);
},
unmounted() {
this.texture.dispose();
this.material.dispose();
},
methods: {
onLoaded() {
this.loading = false;
this.updateUV();
this.$emit('loaded');
},
updateUV() {
this.iWidth = this.texture.image.width;
this.iHeight = this.texture.image.height;
this.iRatio = this.iWidth / this.iHeight;
let x = 0.5, y = 0.5;
if (this.iRatio > 1) {
y = 0.5 / this.iRatio;
} else {
x = 0.5 / this.iRatio;
}
const positions = this.geometry.attributes.position.array;
positions[0] = -x; positions[1] = -y;
positions[5] = x; positions[6] = -y;
positions[10] = x; positions[11] = y;
positions[15] = -x; positions[16] = y;
this.geometry.attributes.position.needsUpdate = true;
},
},
__hmrId: 'Sprite',
});

58
src/meshes/Sprite.ts Normal file
View File

@ -0,0 +1,58 @@
import { defineComponent } from 'vue'
import { Sprite, SpriteMaterial, Texture, TextureLoader } from 'three'
import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
interface SpriteSetupInterface extends Object3DSetupInterface {
texture?: Texture
material?: SpriteMaterial
sprite?: Sprite
}
export default defineComponent({
extends: Object3D,
emits: ['loaded'],
props: {
src: { type: String, required: true },
},
setup(): SpriteSetupInterface {
return object3DSetup()
},
created() {
this.texture = new TextureLoader().load(this.src, this.onLoaded)
this.material = new SpriteMaterial({ map: this.texture })
this.sprite = new Sprite(this.material)
this.initObject3D(this.sprite)
},
unmounted() {
this.texture?.dispose()
this.material?.dispose()
},
methods: {
onLoaded() {
this.updateUV()
this.$emit('loaded')
},
updateUV() {
if (!this.texture || !this.sprite) return
const iWidth = this.texture.image.width
const iHeight = this.texture.image.height
const iRatio = iWidth / iHeight
let x = 0.5, y = 0.5
if (iRatio > 1) {
x = 0.5 * iRatio
} else {
y = 0.5 / iRatio
}
const positions = this.sprite.geometry.attributes.position.array as Array<number>
positions[0] = -x; positions[1] = -y
positions[5] = x; positions[6] = -y
positions[10] = x; positions[11] = y
positions[15] = -x; positions[16] = y
this.sprite.geometry.attributes.position.needsUpdate = true
},
},
__hmrId: 'Sprite',
})