mirror of
https://github.com/troisjs/trois.git
synced 2024-11-24 04:12:02 +08:00
Mesh events : mouseover, click (close #1)
This commit is contained in:
parent
adf64ecb6f
commit
9fbe5696be
@ -1,17 +1,24 @@
|
||||
<template>
|
||||
<Renderer ref="renderer">
|
||||
<Renderer ref="renderer" mouse-over click>
|
||||
<Camera :position="{ z: 10 }" />
|
||||
<Scene>
|
||||
<PointLight :position="{ y: 50, z: 50 }" />
|
||||
<Box ref="box" :size="1" :rotation="{ y: Math.PI / 4, z: Math.PI / 4 }">
|
||||
<LambertMaterial />
|
||||
<Group>
|
||||
<Box ref="box" @hover="boxHover" @click="boxClick" :size="1" :rotation="{ y: Math.PI / 4, z: Math.PI / 4 }">
|
||||
<LambertMaterial :color="boxColor" />
|
||||
</Box>
|
||||
</Group>
|
||||
</Scene>
|
||||
</Renderer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
boxColor: '#ffffff',
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const renderer = this.$refs.renderer;
|
||||
const box = this.$refs.box.mesh;
|
||||
@ -19,5 +26,14 @@ export default {
|
||||
box.rotation.x += 0.01;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
boxHover({ over }) {
|
||||
if (over) this.boxColor = '#ff0000';
|
||||
else this.boxColor = '#ffffff';
|
||||
},
|
||||
boxClick() {
|
||||
console.log(arguments, 'click');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -8,6 +8,8 @@ export default {
|
||||
autoClear: { type: Boolean, default: true },
|
||||
mouseMove: { type: [Boolean, String], default: false },
|
||||
mouseRaycast: { type: Boolean, default: false },
|
||||
mouseOver: { type: Boolean, default: false },
|
||||
click: { type: Boolean, default: false },
|
||||
orbitCtrl: { type: [Boolean, Object], default: false },
|
||||
resize: { type: [Boolean, String], default: true },
|
||||
shadow: Boolean,
|
||||
@ -37,6 +39,8 @@ export default {
|
||||
orbit_ctrl: this.orbitCtrl,
|
||||
mouse_move: this.mouseMove,
|
||||
mouse_raycast: this.mouseRaycast,
|
||||
mouse_over: this.mouseOver,
|
||||
click: this.click,
|
||||
resize: this.resize,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
|
@ -21,6 +21,8 @@ export default function useThree() {
|
||||
orbit_ctrl: false,
|
||||
mouse_move: false,
|
||||
mouse_raycast: false,
|
||||
mouse_over: false,
|
||||
click: false,
|
||||
resize: true,
|
||||
width: 0,
|
||||
height: 0,
|
||||
@ -44,6 +46,9 @@ export default function useThree() {
|
||||
const mousePlane = new Plane(new Vector3(0, 0, 1), 0);
|
||||
const raycaster = new Raycaster();
|
||||
|
||||
// raycast objects
|
||||
const intersectObjects = [];
|
||||
|
||||
// returned object
|
||||
const obj = {
|
||||
conf,
|
||||
@ -62,6 +67,7 @@ export default function useThree() {
|
||||
onAfterInit,
|
||||
onAfterResize, offAfterResize,
|
||||
onBeforeRender, offBeforeRender,
|
||||
addIntersectObject, removeIntersectObject,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -103,6 +109,7 @@ export default function useThree() {
|
||||
window.addEventListener('resize', onResize);
|
||||
}
|
||||
|
||||
conf.mouse_move = conf.mouse_move || conf.mouse_over;
|
||||
if (conf.mouse_move) {
|
||||
if (conf.mouse_move === 'body') {
|
||||
obj.mouse_move_element = document.body;
|
||||
@ -113,6 +120,10 @@ export default function useThree() {
|
||||
obj.mouse_move_element.addEventListener('mouseleave', onMouseleave);
|
||||
}
|
||||
|
||||
if (conf.click) {
|
||||
obj.renderer.domElement.addEventListener('click', onClick);
|
||||
}
|
||||
|
||||
afterInitCallbacks.forEach(c => c());
|
||||
|
||||
return true;
|
||||
@ -171,6 +182,25 @@ export default function useThree() {
|
||||
obj.composer.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* add intersect object
|
||||
*/
|
||||
function addIntersectObject(o) {
|
||||
if (intersectObjects.indexOf(o) === -1) {
|
||||
intersectObjects.push(o);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove intersect object
|
||||
*/
|
||||
function removeIntersectObject(o) {
|
||||
const i = intersectObjects.indexOf(o);
|
||||
if (i !== -1) {
|
||||
intersectObjects.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove listeners
|
||||
*/
|
||||
@ -181,38 +211,77 @@ export default function useThree() {
|
||||
obj.mouse_move_element.removeEventListener('mousemove', onMousemove);
|
||||
obj.mouse_move_element.removeEventListener('mouseleave', onMouseleave);
|
||||
}
|
||||
obj.renderer.domElement.removeEventListener('click', onClick);
|
||||
if (obj.orbitCtrl) obj.orbitCtrl.dispose();
|
||||
this.renderer.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* click listener
|
||||
*/
|
||||
function onClick(e) {
|
||||
mouse.x = (e.clientX / size.width) * 2 - 1;
|
||||
mouse.y = -(e.clientY / size.height) * 2 + 1;
|
||||
raycaster.setFromCamera(mouse, obj.camera);
|
||||
const objects = raycaster.intersectObjects(intersectObjects);
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
const o = objects[i].object;
|
||||
if (o.onClick) o.onClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mousemove listener
|
||||
*/
|
||||
function onMousemove(e) {
|
||||
mouse.x = (e.clientX / size.width) * 2 - 1;
|
||||
mouse.y = -(e.clientY / size.height) * 2 + 1;
|
||||
updateMouseV3();
|
||||
onMousechange(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* mouseleave listener
|
||||
*/
|
||||
function onMouseleave(e) {
|
||||
mouse.x = 0;
|
||||
mouse.y = 0;
|
||||
updateMouseV3();
|
||||
// mouse.x = 0;
|
||||
// mouse.y = 0;
|
||||
onMousechange(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* get 3d mouse position
|
||||
* mouse change
|
||||
*/
|
||||
function updateMouseV3() {
|
||||
function onMousechange(e) {
|
||||
if (conf.mouse_over || conf.mouse_raycast) {
|
||||
raycaster.setFromCamera(mouse, obj.camera);
|
||||
|
||||
if (conf.mouse_raycast) {
|
||||
// get mouse 3d position
|
||||
obj.camera.getWorldDirection(mousePlane.normal);
|
||||
mousePlane.normal.normalize();
|
||||
raycaster.setFromCamera(mouse, obj.camera);
|
||||
raycaster.ray.intersectPlane(mousePlane, mouseV3);
|
||||
}
|
||||
|
||||
if (conf.mouse_over) {
|
||||
const onObjects = raycaster.intersectObjects(intersectObjects);
|
||||
const offObjects = [...intersectObjects];
|
||||
for (let i = 0; i < onObjects.length; i++) {
|
||||
const o = onObjects[i].object;
|
||||
if (!o.hover && o.onHover) {
|
||||
o.hover = true;
|
||||
o.onHover(true);
|
||||
}
|
||||
offObjects.splice(offObjects.indexOf(o), 1);
|
||||
}
|
||||
for (let i = 0; i < offObjects.length; i++) {
|
||||
const o = offObjects[i];
|
||||
if (o.hover && o.onHover) {
|
||||
o.hover = false;
|
||||
o.onHover(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,8 @@ export default {
|
||||
scale: Object,
|
||||
castShadow: Boolean,
|
||||
receiveShadow: Boolean,
|
||||
onHover: Function,
|
||||
onClick: Function,
|
||||
},
|
||||
// can't use setup because it will not be used in sub components
|
||||
// setup() {},
|
||||
@ -29,7 +31,10 @@ export default {
|
||||
},
|
||||
unmounted() {
|
||||
// console.log('Mesh unmounted');
|
||||
if (this.mesh) this.parent.remove(this.mesh);
|
||||
if (this.mesh) {
|
||||
this.three.removeIntersectObject(this.mesh);
|
||||
this.parent.remove(this.mesh);
|
||||
}
|
||||
if (this.geometry) this.geometry.dispose();
|
||||
if (this.material && !this.materialId) this.material.dispose();
|
||||
},
|
||||
@ -39,6 +44,17 @@ export default {
|
||||
this.material = this.three.materials[this.materialId];
|
||||
}
|
||||
this.mesh = new Mesh(this.geometry, this.material);
|
||||
|
||||
if (this.onHover) {
|
||||
this.mesh.onHover = (over) => { this.onHover({ component: this, over }); };
|
||||
this.three.addIntersectObject(this.mesh);
|
||||
}
|
||||
|
||||
if (this.onClick) {
|
||||
this.mesh.onClick = (e) => { this.onClick({ component: this, event: e }); };
|
||||
this.three.addIntersectObject(this.mesh);
|
||||
}
|
||||
|
||||
this.bindProps();
|
||||
this.parent.add(this.mesh);
|
||||
this.$emit('ready');
|
||||
|
Loading…
Reference in New Issue
Block a user