|
@@ -1,5 +1,11 @@
|
|
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
|
-import { Button, View } from "@tarojs/components";
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ BaseEventOrig,
|
|
|
|
|
+ Button,
|
|
|
|
|
+ Slider,
|
|
|
|
|
+ SliderProps,
|
|
|
|
|
+ View,
|
|
|
|
|
+} from "@tarojs/components";
|
|
|
import Taro, { FC } from "@tarojs/taro";
|
|
import Taro, { FC } from "@tarojs/taro";
|
|
|
import { observer } from "mobx-react";
|
|
import { observer } from "mobx-react";
|
|
|
import {
|
|
import {
|
|
@@ -25,9 +31,10 @@ import {
|
|
|
import { OutlinePass } from "three-platformize/examples/jsm/postprocessing/OutlinePass";
|
|
import { OutlinePass } from "three-platformize/examples/jsm/postprocessing/OutlinePass";
|
|
|
import { RenderPass } from "three-platformize/examples/jsm/postprocessing/RenderPass";
|
|
import { RenderPass } from "three-platformize/examples/jsm/postprocessing/RenderPass";
|
|
|
import { EffectComposer } from "three-platformize/examples/jsm/postprocessing/EffectComposer";
|
|
import { EffectComposer } from "three-platformize/examples/jsm/postprocessing/EffectComposer";
|
|
|
-import { Easing, Tween } from "@tweenjs/tween.js";
|
|
|
|
|
-import { cancelAnimationFrame, requestAnimationFrame } from "@tarojs/runtime";
|
|
|
|
|
|
|
+import { requestAnimationFrame } from "@tarojs/runtime";
|
|
|
import { CanvasAdapter } from "../../components";
|
|
import { CanvasAdapter } from "../../components";
|
|
|
|
|
+import { tweenHandler } from "../../utils";
|
|
|
|
|
+import { ActModel } from "./ActModel";
|
|
|
import "./index.scss";
|
|
import "./index.scss";
|
|
|
|
|
|
|
|
enum MODEL_STATE {
|
|
enum MODEL_STATE {
|
|
@@ -38,19 +45,6 @@ enum MODEL_STATE {
|
|
|
CHECK_HUO = 4,
|
|
CHECK_HUO = 4,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-interface TweenHandlerOptions<T extends object> {
|
|
|
|
|
- /** 当前属性 */
|
|
|
|
|
- curProps: T;
|
|
|
|
|
- /** 目标属性 */
|
|
|
|
|
- targetProps: T;
|
|
|
|
|
- /** 动画更新回调 */
|
|
|
|
|
- onUpdate?: (e: T) => void;
|
|
|
|
|
- /** 动画完成回调 */
|
|
|
|
|
- cb?: Function;
|
|
|
|
|
- /** 动画时长 默认 1000 ms */
|
|
|
|
|
- delay?: number;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
const DEFUALT_SCALE = 20;
|
|
const DEFUALT_SCALE = 20;
|
|
|
const DENGZHAO_MIN_ROTATE = -1.2;
|
|
const DENGZHAO_MIN_ROTATE = -1.2;
|
|
|
const DENGZHAO_MAX_ROTATE = -2.55;
|
|
const DENGZHAO_MAX_ROTATE = -2.55;
|
|
@@ -92,6 +86,10 @@ const IndexPage: FC = observer(() => {
|
|
|
() => modelState === MODEL_STATE.CHECK_WEN,
|
|
() => modelState === MODEL_STATE.CHECK_WEN,
|
|
|
[modelState]
|
|
[modelState]
|
|
|
);
|
|
);
|
|
|
|
|
+ const isHuo = useMemo(
|
|
|
|
|
+ () => modelState === MODEL_STATE.CHECK_HUO,
|
|
|
|
|
+ [modelState]
|
|
|
|
|
+ );
|
|
|
const hotSeparateAnimArr = useRef<ReticleModel[]>([]);
|
|
const hotSeparateAnimArr = useRef<ReticleModel[]>([]);
|
|
|
const hotspotAnimArr = useRef<ReticleModel[]>([]);
|
|
const hotspotAnimArr = useRef<ReticleModel[]>([]);
|
|
|
const tagArr = useRef<TagModel[]>([]);
|
|
const tagArr = useRef<TagModel[]>([]);
|
|
@@ -100,6 +98,7 @@ const IndexPage: FC = observer(() => {
|
|
|
const wenCurStep = useRef(0);
|
|
const wenCurStep = useRef(0);
|
|
|
const wenStep = useRef(0.01);
|
|
const wenStep = useRef(0.01);
|
|
|
const outlinePass = useRef<OutlinePass>();
|
|
const outlinePass = useRef<OutlinePass>();
|
|
|
|
|
+ const modelT = useRef<ActModel>();
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
setTimeout(async () => {
|
|
setTimeout(async () => {
|
|
@@ -200,6 +199,7 @@ const IndexPage: FC = observer(() => {
|
|
|
},
|
|
},
|
|
|
cb: () => {
|
|
cb: () => {
|
|
|
handleAnimatorCallout(true);
|
|
handleAnimatorCallout(true);
|
|
|
|
|
+ modelT.current = new ActModel();
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
renderModel.setAutoRotate(ROTATE_TYPE.TRUE);
|
|
renderModel.setAutoRotate(ROTATE_TYPE.TRUE);
|
|
|
}, 800);
|
|
}, 800);
|
|
@@ -230,31 +230,6 @@ const IndexPage: FC = observer(() => {
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 相机动画
|
|
|
|
|
- */
|
|
|
|
|
- function tweenHandler<T extends object>(options: TweenHandlerOptions<T>) {
|
|
|
|
|
- let animaId: number | NodeJS.Timeout = 0;
|
|
|
|
|
- const { curProps, targetProps, onUpdate, cb } = options;
|
|
|
|
|
-
|
|
|
|
|
- const tween = new Tween(curProps)
|
|
|
|
|
- .to(targetProps, options.delay || 1000)
|
|
|
|
|
- .onUpdate(onUpdate)
|
|
|
|
|
- .onComplete(() => {
|
|
|
|
|
- cancelAnimationFrame(animaId as number);
|
|
|
|
|
- cb && cb();
|
|
|
|
|
- })
|
|
|
|
|
- .easing(Easing.Quintic.Out)
|
|
|
|
|
- .start();
|
|
|
|
|
-
|
|
|
|
|
- function animate(time?: number) {
|
|
|
|
|
- animaId = requestAnimationFrame(animate);
|
|
|
|
|
- tween.update(time);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- animate();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
const modelChildRotation = (e: number) => {
|
|
const modelChildRotation = (e: number) => {
|
|
|
const dengzhao1Mesh = renderModel.model?.getObjectByName("dengzhao1");
|
|
const dengzhao1Mesh = renderModel.model?.getObjectByName("dengzhao1");
|
|
|
|
|
|
|
@@ -574,6 +549,8 @@ const IndexPage: FC = observer(() => {
|
|
|
item.update(time);
|
|
item.update(time);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ modelT.current?.update(time);
|
|
|
|
|
+
|
|
|
if (_modelState.current === MODEL_STATE.CHECK_WEN) {
|
|
if (_modelState.current === MODEL_STATE.CHECK_WEN) {
|
|
|
wenCurStep.current += wenStep.current;
|
|
wenCurStep.current += wenStep.current;
|
|
|
|
|
|
|
@@ -614,16 +591,22 @@ const IndexPage: FC = observer(() => {
|
|
|
if (isSeparate) {
|
|
if (isSeparate) {
|
|
|
handleModelZoomUp(name);
|
|
handleModelZoomUp(name);
|
|
|
break;
|
|
break;
|
|
|
- } else if (modelState === MODEL_STATE.DEFAULT) {
|
|
|
|
|
- if (name === "wen") {
|
|
|
|
|
- wenliHandler(true);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ } else if (modelState === MODEL_STATE.DEFAULT && name === "wen") {
|
|
|
|
|
+ wenliHandler(true);
|
|
|
|
|
+ break;
|
|
|
|
|
+ } else if (modelState === MODEL_STATE.DEFAULT && name === "huo") {
|
|
|
|
|
+ huoHandler(true);
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const setCanvasPosition = (x: number, y: number) => {
|
|
|
|
|
+ mouseV2.current.x = (x / system.windowWidth) * 2 - 1;
|
|
|
|
|
+ mouseV2.current.y = (-y / system.windowHeight) * 2 + 1;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const wenliHandler = (visible: boolean) => {
|
|
const wenliHandler = (visible: boolean) => {
|
|
|
revertModel(() => {
|
|
revertModel(() => {
|
|
|
if (visible) {
|
|
if (visible) {
|
|
@@ -736,11 +719,6 @@ const IndexPage: FC = observer(() => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const setCanvasPosition = (x: number, y: number) => {
|
|
|
|
|
- mouseV2.current.x = (x / system.windowWidth) * 2 - 1;
|
|
|
|
|
- mouseV2.current.y = (-y / system.windowHeight) * 2 + 1;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 返回分解模型
|
|
* 返回分解模型
|
|
|
*/
|
|
*/
|
|
@@ -780,9 +758,57 @@ const IndexPage: FC = observer(() => {
|
|
|
backForSeparate();
|
|
backForSeparate();
|
|
|
} else if (isWen) {
|
|
} else if (isWen) {
|
|
|
wenliHandler(false);
|
|
wenliHandler(false);
|
|
|
|
|
+ } else if (isHuo) {
|
|
|
|
|
+ huoHandler(false);
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const huoHandler = (visible: boolean) => {
|
|
|
|
|
+ revertModel(() => {
|
|
|
|
|
+ if (visible) {
|
|
|
|
|
+ renderModel.setAutoRotate(ROTATE_TYPE.FALSE);
|
|
|
|
|
+ renderModel.setControlsStatus(true, true, false, true, false);
|
|
|
|
|
+ bulbLight.current!.visible = true;
|
|
|
|
|
+ handleAnimatorCallout(false);
|
|
|
|
|
+ handleHuoPlay(true);
|
|
|
|
|
+ setModelState(MODEL_STATE.CHECK_HUO);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ handleHuoPlay(false);
|
|
|
|
|
+ modelChildRotation(5);
|
|
|
|
|
+ renderModel.setControlsStatus(true, true, false);
|
|
|
|
|
+ bulbLight.current!.visible = false;
|
|
|
|
|
+ handleAnimatorCallout(true);
|
|
|
|
|
+ setModelState(MODEL_STATE.DEFAULT);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleHuoPlay = (type: boolean) => {
|
|
|
|
|
+ if (type) {
|
|
|
|
|
+ modelT.current?.startPlay(true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ let opacity = renderModel.modelMaterialList[0].material.opacity;
|
|
|
|
|
+ const timer = setInterval(() => {
|
|
|
|
|
+ opacity += 0.05;
|
|
|
|
|
+ renderModel.modelMaterialList.forEach((i) => {
|
|
|
|
|
+ i.material.opacity = opacity;
|
|
|
|
|
+ i.visible = true;
|
|
|
|
|
+ });
|
|
|
|
|
+ if (opacity >= 1) {
|
|
|
|
|
+ clearInterval(timer);
|
|
|
|
|
+ modelT.current?.startPlay(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 50);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleSlider = (e: BaseEventOrig<SliderProps.onChangeEventDetail>) => {
|
|
|
|
|
+ const opt = e.detail.value / 10 + 1;
|
|
|
|
|
+ // 设置光源强度
|
|
|
|
|
+ bulbLight.current!.intensity = 0.5 * opt;
|
|
|
|
|
+ modelChildRotation(opt);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<View className="page">
|
|
<View className="page">
|
|
|
<CanvasAdapter
|
|
<CanvasAdapter
|
|
@@ -798,7 +824,7 @@ const IndexPage: FC = observer(() => {
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
<View className="toolbar">
|
|
<View className="toolbar">
|
|
|
- {isSingleModel || isWen ? (
|
|
|
|
|
|
|
+ {isSingleModel || isWen || isHuo ? (
|
|
|
<Button className="btn" onClick={handleBack}>
|
|
<Button className="btn" onClick={handleBack}>
|
|
|
返回
|
|
返回
|
|
|
</Button>
|
|
</Button>
|
|
@@ -808,6 +834,10 @@ const IndexPage: FC = observer(() => {
|
|
|
</Button>
|
|
</Button>
|
|
|
)}
|
|
)}
|
|
|
</View>
|
|
</View>
|
|
|
|
|
+
|
|
|
|
|
+ {isHuo && (
|
|
|
|
|
+ <Slider className="slider" value={50} onChanging={handleSlider} />
|
|
|
|
|
+ )}
|
|
|
</View>
|
|
</View>
|
|
|
);
|
|
);
|
|
|
});
|
|
});
|