问题描述
我从默认情况下每 2 秒采样一次从 websocket 中检索的数据。 我使用 zustand 传播这些数据进行状态管理。 我有多个依赖于此数据的动画/组件。 为了补偿 2 秒的间隔差距,我计算了每帧的数据可能不是由 zustand 处理,而是由 useState 处理。
我可以使用 CustomEvent 来每帧更新所有依赖组件,或者我可以使用我更喜欢的自定义钩子。
问题是每当 api > zustand > useStore 更新 hook 的本地状态(样本)时,useFrame 就会丢失本地状态。
这是钩子...
/**
* merge two streams of similar data
* one stream comes from api and has a default sample-rate of about 2 seconds
* the second stream updates every frame change,roughly 60 frames / second
*/
export default () => {
const { dc,status,metrics } = useStore((state) => state.api);
const [sample,setSample] = useState(metrics.slice(-1)[0]);
const advanceSample = (duration,sample) => {
if (status === 'open') {
const radiansPerSecond = (sample.rpm / 60) * 2 * Math.PI;
const radiansPerFrame = radiansPerSecond * duration;
const r = (sample.r + radiansPerFrame) % (2 * Math.PI);
const active = degreesToActive[r * (180 / Math.PI)];
return {
ms: Date.Now(),r,rpm: sample.rpm,c1: { mA: mA(active,dc),t: t(active,dc) },c2: { mA: mA(active,c3: { mA: mA(active,c4: { mA: mA(active,c5: { mA: mA(active,c6: { mA: mA(active,};
}
return sample;
};
useFrame(({ clock },delta) => setSample(advanceSample(delta,sample)));
// const sampleEvent = new CustomEvent('sample',{ detail: { sample } });
// document.dispatchEvent(sampleEvent);
return sample;
};
快速回答是否定的,在这种情况下,useFrame、zustand 和 React.useState 都没有冲突
我的解决方案是通过 zustand 在每一帧上更新托管状态,并通过状态管理器传播状态,如下所示...... 存储方法:
// increment state
next: (duration) => {
const { dc,metrics } = get().api;
const [sample] = metrics.slice(-1);
const ms = Date.Now();
if (get().api.status === 'open') {
const radiansPerSecond = (sample.rpm / 60) * 2 * Math.PI;
const radiansPerFrame = radiansPerSecond * duration;
const r = (sample.r + radiansPerFrame) % (2 * Math.PI);
const active = activeCoilIndex[r * (180 / Math.PI)];
set({
api: {
...get().api,metrics: [
...get().api.metrics,{
ms,...range(1,6).reduce((accumulator,coil,index) => ({ ...accumulator,[`c${coil}`]: { mA: mA(active,dc) } }),{}),},].slice(-512),});
}
然后在一个单独的组件中:
// increment state at generally 60fps
const nextSample = useStore((state) => state.api.next);
useFrame(({ clock },delta) => nextSample(delta));
最后传播:
// use current state within each component as follows
const unsubscribe = useStore.subscribe(
(metrics) => {
const [sample] = metrics.slice(-1);
if (crankshaftRef.current) crankshaftRef.current.rotation.z = sample.r;
const sqrRodLength = Math.pow(rodLength,2);
const sqrCrankRadius = Math.pow(crankRadius,2);
const calcMotion = (offsetRotation) => {
const radians = sample.r + offsetRotation;
const cosR = Math.cos(radians);
const sinR = Math.sin(radians);
const displacement = crankRadius * cosR + Math.sqrt(sqrRodLength - sqrCrankRadius * Math.pow(sinR,2));
const moment = Math.asin(crankRadius / (rodLength / sinR)) * -1;
return [displacement,moment];
};
if (conrod1Ref.current && plunger1Ref.current) {
const [displacement,moment] = calcMotion(pistonsModels['piston1'].offsetRotation);
conrod1Ref.current.position.x = displacement;
conrod1Ref.current.rotation.z = moment;
plunger1Ref.current.position.x = displacement;
}
...
},(state) => state.api.metrics
);
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)