reactjs - d3 动画 React Native 代码在 IOS 中很快而在 Android 中很慢?
问题描述
我有一个地球仪,我想在 x 轴和 y 轴上旋转并使用 reanimated 2 放大和缩小捏合,这是代码:
const Globe = () => {
const [x, setX] = useState(0);
const [y, setY] = useState(0);
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const scale = useSharedValue(1);
const focalX = useSharedValue(0);
const focalY = useSharedValue(0);
const mapExtent = SVG_WIDTH > SVG_HEIGHT ? SVG_HEIGHT : SVG_WIDTH;
const onGestureEvent = useAnimatedGestureHandler<
PanGestureHandlerGestureEvent,
{
x: number;
y: number;
}
>({
onStart: (_, ctx) => {
ctx.x = translateX.value;
ctx.y = translateY.value;
},
onActive: ({translationX, translationY}, ctx) => {
translateX.value = ctx.x + translationX;
translateY.value = ctx.y + translationY;
},
});
const onPinchGesture = useAnimatedGestureHandler<
PinchGestureHandlerGestureEvent,
{scale: number}
>({
onStart: (_, ctx) => {
ctx.scale = scale.value;
},
onActive: (event, ctx) => {
scale.value = event.scale;
focalX.value = event.focalX;
focalY.value = event.focalY;
},
});
const style = useAnimatedStyle(() => {
return {
transform: [
{translateX: focalX.value},
{translateY: focalY.value},
{translateX: -SVG_WIDTH / 2},
{translateY: -SVG_HEIGHT / 2},
{scale: scale.value},
{translateX: -focalX.value},
{translateY: -focalY.value},
{translateX: SVG_WIDTH / 2},
{translateY: SVG_HEIGHT / 2},
],
};
});
useAnimatedReaction(
() => ({x: translateX.value, y: translateY.value}),
({x, y}) => {
requestAnimationFrame(() => {
runOnJS(setX)(x);
runOnJS(setY)(y);
});
},
[translateX, translateY],
);
return (
<PinchGestureHandler onGestureEvent={onPinchGesture}>
<Animated.View>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={style}>
<Svg width={SVG_WIDTH} height={SVG_HEIGHT}>
<G>
<Circle
cx={SVG_WIDTH / 2}
cy={mapExtent / 2}
r={mapExtent / 2}
fill={'#0099FF'}
/>
<GlobePath x={x} y={y} />
<GlobeCircles x={x} y={y} />
</G>
</Svg>
</Animated.View>
</PanGestureHandler>
</Animated.View>
</PinchGestureHandler>
);
};
我所做的是基于 x 和 y,我在 GlobePath 和 GlobeCircles 上像这样更新 d3 投影:
const GlobePath = ({x, y}: {x: number; y: number}) => {
const projection = d3
.geoOrthographic()
.rotate([x, -y])
.scale(mapExtent / 2)
.clipAngle(clipAngle)
.translate([SVG_WIDTH / 2, mapExtent / 2]);
const geoPath = d3.geoPath().projection(projection);
return (
<Path
d={geoPath(COUNTRIES) as string}
stroke={'#666666'}
strokeOpacity={0.3}
strokeWidth={0.6}
fill={'#DDDDDD'}
opacity={1}
/>
);
};
const GlobeCircles = ({x, y}: {x: number; y: number}) => {
//first should be longitude
const coordinates = [
[19.744822, -34.633016],
[80.229349, 9.818078],
[-98.862052, 37.848794],
];
const projection = d3
.geoOrthographic()
.rotate([x, -y])
.scale(mapExtent / 2)
.clipAngle(clipAngle)
.translate([SVG_WIDTH / 2, mapExtent / 2]);
return (
<G>
{coordinates.map((data, i) => {
//calculate xy position from coordinates (long,lat)
const lang = data[0];
const lat = data[1];
const coordinate = projection([lang, lat]);
const xdata = (coordinate as [number, number])[0]; //first should be longitude
const ydata = (coordinate as [number, number])[1];
//if marker out of circle or back side marker will hide
const centerPos = projection.invert
? projection.invert([SVG_WIDTH / 2, mapExtent / 2])
: [0, 0];
const d = d3.geoDistance([lang, lat], centerPos as [number, number]);
const opacity = d > 1.57 ? 0 : 1;
return (
<Circle
key={`circle:${i}`}
cx={xdata}
cy={ydata}
r={6}
fillOpacity={0.5}
opacity={opacity}
fill="red"
/>
);
})}
</G>
);
};
现在我不太确定为什么我在 android 上的动画很慢,但在 ios 上却很快?代码看起来很简单,只是 x 和 y 发生了变化,而且捏放大和缩小在 android 上不起作用。帮助?
解决方案
推荐阅读
- javascript - 如何以延迟方式调用函数
- r - 根据两列R中的匹配行填充列中的空白
- hazelcast - 是否可以将特定的 Java 依赖项部署到 Hazelcast Cloud 上的节点?
- sql - 创建我们有客户但没有供应商的每个国家/地区的列表
- apache-nifi - Apache NiFi:如何获取登录用户界面的审核日志?
- react-router - 如何让 Rails routes.rb 将多个路径重定向到单个控制器#action?
- selenium - Whether Selenium Grid has public API documentation available?
- c# - 如何在 ASP.NET Core Web API 中添加两个不同的令牌
- mysql - Update large amount of data in SQL database via Airflow
- c# - How can adding certificate to the trusted root certificates