更新
个人使用最新版本
export default class Anim {
constructor(obj, targetObj, options) {
this.obj = obj;
this.targetObj = targetObj;
this.duration = options.duration;
this.easingFunction = options.easingFunction || Animing.linear;
this.onUpdate = options.onUpdate;
this.onComplete = options.onComplete;
this.repeatInterval = options.repeatInterval || 16; // 默认刷新频率为 16ms (60fps)
this.initValues();
}
initValues() {
this.startValues = {};
this.deltaValues = {};
for (let key in this.targetObj) {
if (this.targetObj.hasOwnProperty(key)) {
this.startValues[key] = this.obj[key] || 0; // 默认起始值为 0
this.deltaValues[key] = this.targetObj[key] - this.startValues[key];
}
}
}
start() {
this.startTime = Date.now();
this.animate();
}
startInfinite() {
this.startTime = Date.now();
this.isInfinite = true;
this.animateInfinite();
}
animate() {
const currentTime = Date.now();
const elapsed = currentTime - (this.startTime || 0);
if (elapsed < this.duration) {
// 计算当前进度
const progress = this.easingFunction(elapsed / this.duration);
// 更新对象的属性值
for (let key in this.targetObj) {
if (this.targetObj.hasOwnProperty(key)) {
this.obj[key] = this.startValues[key] + this.deltaValues[key] * progress;
}
}
// 调用更新回调函数
if (this.onUpdate) {
this.onUpdate(this.obj);
}
// 继续动画
requestAnimationFrame(() => this.animate());
} else {
// 完成动画
for (let key in this.targetObj) {
if (this.targetObj.hasOwnProperty(key)) {
this.obj[key] = this.targetObj[key];
}
}
// 调用完成回调函数
if (this.onComplete) {
this.onComplete(this.obj);
}
}
}
animateInfinite() {
const currentTime = Date.now();
const elapsed = currentTime - (this.startTime || 0);
// 计算当前进度
const progress = this.easingFunction(elapsed / this.duration);
// 更新对象的属性值
for (let key in this.targetObj) {
if (this.targetObj.hasOwnProperty(key)) {
this.obj[key] = this.startValues[key] + this.deltaValues[key] * progress;
}
}
// 调用更新回调函数
if (this.onUpdate) {
this.onUpdate(this.obj);
}
// 继续动画
if (this.isInfinite) {
setTimeout(() => this.animateInfinite(), this.repeatInterval);
}
}
complete() {
this.isInfinite = false;
// 完成动画
for (let key in this.targetObj) {
if (this.targetObj.hasOwnProperty(key)) {
this.obj[key] = this.targetObj[key];
}
}
// 调用完成回调函数
if (this.onComplete) {
this.onComplete(this.obj);
}
}
static linear(t) {//平滑
return t;
}
static easeInQuad(t) {//渐进
return t * t;
}
static easeOutQuad(t) {//渐出
return t * (2 - t);
}
static easeInOutQuad(t) {//渐进渐出
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
static delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
//使用案例
lerpCameraPose(defaultVision, duration = 500, _easingFunction = "easeInOutQuad") {
return new Promise((resolve, reject) => {
const controls = this.controls;
if (!controls) return;
const camera = controls.object; // 当前控制器的相机
let { position, rotation, target } = defaultVision;
const startPosition = {
x: camera.position.x,
y: camera.position.y,
z: camera.position.z,
}
const anim = new Anim(
startPosition, position,
{
duration: duration,
easingFunction: Anim[_easingFunction],
onUpdate: (updated) => {
console.log(updated);
camera.position.set(updated.x, updated.y, updated.z)
if (target) {
controls.target.set(target.x, target.y, target.z)
} else {
camera.rotation.set(rotation.x, rotation.y, rotation.z)
}
},
onComplete: () => {
if (target) {
controls.target.set(target.x, target.y, target.z)
resolve(true)
}
}
}
)
anim.start()
this.dispatchEvent({ type: "viewChange", message: null })
})
}
特点
可以为场景内的模型添加点击,鼠标移入移出和鼠标滑动回调
代码
import { EventDispatcher, Raycaster, Vector2, Vector3 } from "three";
// 事件管理器 用于处理事件交互
export class EventManage {
/**
*
* @param {HTMLElement} dom
* @param {Camera} camera
* @param {Scene} scene
*/
constructor(dom, camera, scene) {
this.mouse = new Vector2();
this.raycaster = new Raycaster();
this.dom = null;
this.camera = null;
this.scene = null;
this.last = null;
this.listener = [];
// super()
this.dom = dom;
this.camera = camera;
this.scene = scene;
const mouse = this.mouse;
const raycaster = this.raycaster;
let last = null;
let lastPos = new Vector3();
let leftbutton = false;
let moved = false; // 判断移动参数
dom.addEventListener("mousemove", (e) => {
// 阻止事件冒泡
e.stopPropagation();
if(!this.camera) return
let _camera = this.camera
mouse.x = (e.offsetX / dom.offsetWidth) * 2 - 1;
mouse.y = (-e.offsetY * 2) / dom.offsetHeight + 1;
raycaster.setFromCamera(mouse, _camera);
const intersection = raycaster.intersectObjects(this.scene.children);
if (intersection.length > 0) {
// console.log(intersection[0]);
let object = intersection[0].object;
object.dispatchEvent({
type: "mousemove",
point: intersection[0].point,
});
if (last && last.uuid == object.uuid) {
} else {
if (last)
last.dispatchEvent({
type: "mouseout",
point: intersection[0].point,
});
object.dispatchEvent({
type: "mousein",
point: intersection[0].point,
});
}
last = object;
lastPos.copy(intersection[0].point);
} else {
if (last) {
last.dispatchEvent({
type: "mouseout",
point: lastPos,
});
last = null;
}
}
// 回调执行
let callbacks = this.listener.filter((item) => item.name == "mousemove");
if (callbacks.length > 0) {
callbacks.forEach(({ callback }) =>
callback({
object: intersection[0],
})
);
}
// 防止拖拽旋转后立即触发点击事件
if (leftbutton) {
moved = true;
}
});
dom.addEventListener("mouseup", (e) => {
// 阻止事件冒泡
e.stopPropagation();
if(!this.camera) return
let _camera = this.camera
raycaster.setFromCamera(mouse, _camera);
const intersection = raycaster.intersectObjects(this.scene.children);
if (intersection.length > 0) {
// console.log(intersection[0]);
intersection[0].object.dispatchEvent({
type: "mouseup",
point: intersection[0].point,
});
}
// moved = false
if (e.button === 0) {
leftbutton = false;
}
});
dom.addEventListener("mousedown", (e) => {
// 阻止事件冒泡
e.stopPropagation();
if(!this.camera) return
let _camera = this.camera
raycaster.setFromCamera(mouse, _camera);
const intersection = raycaster.intersectObjects(this.scene.children);
if (intersection.length > 0) {
// console.log(intersection[0]);
intersection[0].object.dispatchEvent({
type: "mousedown",
point: intersection[0].point,
});
}
if (e.button === 0) {
leftbutton = true;
}
});
dom.addEventListener("click", (e) => {
// 阻止事件冒泡
e.stopPropagation();
if(!this.camera) return
let _camera = this.camera
raycaster.setFromCamera(mouse, _camera);
const intersection = raycaster.intersectObjects(this.scene.children);
if (!moved) {
if (intersection.length > 0) {
// console.log(intersection[0]);
intersection[0].object.dispatchEvent({
type: "click",
point: intersection[0].point,
});
}
console.log(intersection);
let callbacks = this.listener.filter((item) => item.name == "click");
if (callbacks.length > 0) {
callbacks.forEach(({ callback }) =>
callback({
object: intersection[0],
})
);
}
}
moved = false;
});
// setInterval(() => moved = false, 1)
}
addEventListener(name, callback) {
this.listener.push({ name, callback });
}
removeListener(name_, callback_) {
// let {name,callback} = this.listener
for (let i = 0; i < this.listener.length; i++) {
let { name, callback } = this.listener[i];
if (name === name_ && callback === callback_) {
this.listener.splice(i, 1);
}
}
}
}
使用
和dom元素添加回调事件一样
mesh.addEventListener(e,(self)=>callback())
//e : click mousein mouseout mousemove

3984

被折叠的 条评论
为什么被折叠?



