如何在 React Native 中使用最短路径旋转图像
How to rotate an image using the shortest route in React Native
我正在尝试使用 React Native 旋转图像。我已经设法做到这一点,如下例所示,但我更希望箭头使用较短的路线旋转到新方位(即在这种情况下顺时针而不是逆时针)。
如果当前 bearingAnim
值为 315
且下一个值为 45
则旋转将向后过渡,而不是从 315 => 45
.
如何调整代码以使用最短旋转?
const bearing = this.bearingAnim.interpolate({
inputRange: [0, 360],
outputRange: ['0deg', '360deg'],
});
return <Animated.Image style={{ transform: [{ rotate: bearing }] }} source={markerGreen} />;
因为每个方向都可以设置为正角或负角(clockwise/counter顺时针旋转),例如315(顺时针)是 -45(逆时针),您可以比较当前方向和新方向(顺时针和逆时针)之间的增量绝对值,并将新角度设置为增量绝对值最小的角度:
const getNewDirectionangle = (direction, newDirection) => {
const delta = {
clockwise: (newDirection-direction)%360,
counterClockwise: (newDirection-direction-360)%360
}
return
Math.abs(delta.clockwise) < Math.abs(delta.counterClockwise) ?
direction + delta.clockwise :
direction + delta.counterClockwise
}
以下是一个 React.js 现场演示来说明这个概念:
const { useState } = React,
{ render } = ReactDOM,
rootNode = document.getElementById('root')
const Pointer = ({rotationAngle}) => {
return (
<div className="map">
<div
className="pointer"
style={{transform: `rotate(${rotationAngle}deg)`}}
/>
</div>
)
}
const Controls = ({onRotate}) => {
const [azimuth, setAzimuth] = useState(),
onInput = ({target:{value}}) => setAzimuth(value%360)
return (
<form>
<input type="number" onChange={onInput} />
<input type="button" value="Rotate" onClick={() => onRotate(azimuth)} />
</form>
)
}
const App = () => {
const [direction, setDirection] = useState(0),
onRotate = newDirection => {
const delta = {
clockwise: (newDirection-direction)%360,
counterClockwise: (newDirection-direction-360)%360
}
setDirection(
Math.abs(delta.clockwise) < Math.abs(delta.counterClockwise) ?
direction + delta.clockwise :
direction + delta.counterClockwise
)
}
return (
<div className="wrapper">
<Pointer rotationAngle={direction} />
<Controls {...{onRotate}}/>
</div>
)
}
render (
<App />,
rootNode
)
.wrapper {
width: 250px;
display: flex;
flex-direction: column;
align-items: center;
}
.map {
width: 100%;
height: 120px;
display: flex;
flex-direction: row;
justify-content: center;
background-image: url("https://i.stack.imgur.com/3yuKI.png");
background-size: cover;
margin: 5px
}
.pointer {
transition: transform 1s ease-in;
transform-origin: 50% 58%;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMS43NTIgMjYuMjU2Ij48ZGVmcyBpZD0iZGVmczUiPjxjbGlwUGF0aCBpZD0iYSIgY2xpcFBhdGhVbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGQ9Ik0xNi4zMy0uNDhoODMuNzM0djEwOS4zNUgxNi4zM3oiIGlkPSJwYXRoMiIgLz48L2NsaXBQYXRoPjwvZGVmcz48cGF0aCBkPSJNMjguOTk5IDg3LjMzNmMtMTYuMDUtMTYuMDUtMTYuMDUtNDIuMDg3IDAtNTguMTM3QzM4LjY4NSAxOS41MTIgNDguMzcgOS44MjYgNTguMDc3LjE0TDg3LjEzNiAyOS4yYzE2LjA1IDE2LjA1IDE2LjA1IDQyLjA4NyAwIDU4LjEzNy0xNi4wNSAxNi4wNS00Mi4wODcgMTYuMDUtNTguMTM3IDB6IiBjbGlwLXBhdGg9InVybCgjYSkiIGZpbGw9IiM3MGFkNDciIGZpbGwtcnVsZT0iZXZlbm9kZCIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggLTQuNDg4IC0uMDM3KSIgaWQ9InBhdGg3IiAvPjxwYXRoIGQ9Ik0zLjA3NCAxNS4zODJjMC00LjI4OSAzLjQ5NS03Ljc3MyA3Ljc5NC03Ljc3MyA0LjMwNSAwIDcuNzk0IDMuNDg0IDcuNzk0IDcuNzczIDAgNC4yOTQtMy40ODkgNy43NzMtNy43OTQgNy43NzMtNC4zIDAtNy43OTQtMy40NzktNy43OTQtNy43NzN6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGlkPSJwYXRoOSIgLz48L3N2Zz4=");
background-repeat: no-repeat;
background-size: cover;
width: 50px;
height: 60px;
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
我给你写了一个函数,可以根据旧方向计算出正确的角度
她需要获得新旧角度
它将return您需要添加的方向以达到新的方向
(如果箭头需要向后移动它会 return 减去它会向后移动)
function newRotate(oldV, newV) {
const diff1 = newV - oldV;
let myOldV = oldV;
if (newV < oldV) newV += 360;
else myOldV += 360;
const diff2 = newV - myOldV;
const shortDiff = Math.abs(diff1) < Math.abs(diff2) ? diff1 : diff2;
return oldV + shortDiff;
}
这是使用方法
const value =newRotate(oldValue,newValue)
Animated.timing(routeAnimtion, {
toValue: value,
duration: 10,
}).start();
我正在尝试使用 React Native 旋转图像。我已经设法做到这一点,如下例所示,但我更希望箭头使用较短的路线旋转到新方位(即在这种情况下顺时针而不是逆时针)。
如果当前 bearingAnim
值为 315
且下一个值为 45
则旋转将向后过渡,而不是从 315 => 45
.
如何调整代码以使用最短旋转?
const bearing = this.bearingAnim.interpolate({
inputRange: [0, 360],
outputRange: ['0deg', '360deg'],
});
return <Animated.Image style={{ transform: [{ rotate: bearing }] }} source={markerGreen} />;
因为每个方向都可以设置为正角或负角(clockwise/counter顺时针旋转),例如315(顺时针)是 -45(逆时针),您可以比较当前方向和新方向(顺时针和逆时针)之间的增量绝对值,并将新角度设置为增量绝对值最小的角度:
const getNewDirectionangle = (direction, newDirection) => {
const delta = {
clockwise: (newDirection-direction)%360,
counterClockwise: (newDirection-direction-360)%360
}
return
Math.abs(delta.clockwise) < Math.abs(delta.counterClockwise) ?
direction + delta.clockwise :
direction + delta.counterClockwise
}
以下是一个 React.js 现场演示来说明这个概念:
const { useState } = React,
{ render } = ReactDOM,
rootNode = document.getElementById('root')
const Pointer = ({rotationAngle}) => {
return (
<div className="map">
<div
className="pointer"
style={{transform: `rotate(${rotationAngle}deg)`}}
/>
</div>
)
}
const Controls = ({onRotate}) => {
const [azimuth, setAzimuth] = useState(),
onInput = ({target:{value}}) => setAzimuth(value%360)
return (
<form>
<input type="number" onChange={onInput} />
<input type="button" value="Rotate" onClick={() => onRotate(azimuth)} />
</form>
)
}
const App = () => {
const [direction, setDirection] = useState(0),
onRotate = newDirection => {
const delta = {
clockwise: (newDirection-direction)%360,
counterClockwise: (newDirection-direction-360)%360
}
setDirection(
Math.abs(delta.clockwise) < Math.abs(delta.counterClockwise) ?
direction + delta.clockwise :
direction + delta.counterClockwise
)
}
return (
<div className="wrapper">
<Pointer rotationAngle={direction} />
<Controls {...{onRotate}}/>
</div>
)
}
render (
<App />,
rootNode
)
.wrapper {
width: 250px;
display: flex;
flex-direction: column;
align-items: center;
}
.map {
width: 100%;
height: 120px;
display: flex;
flex-direction: row;
justify-content: center;
background-image: url("https://i.stack.imgur.com/3yuKI.png");
background-size: cover;
margin: 5px
}
.pointer {
transition: transform 1s ease-in;
transform-origin: 50% 58%;
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMS43NTIgMjYuMjU2Ij48ZGVmcyBpZD0iZGVmczUiPjxjbGlwUGF0aCBpZD0iYSIgY2xpcFBhdGhVbml0cz0idXNlclNwYWNlT25Vc2UiPjxwYXRoIGQ9Ik0xNi4zMy0uNDhoODMuNzM0djEwOS4zNUgxNi4zM3oiIGlkPSJwYXRoMiIgLz48L2NsaXBQYXRoPjwvZGVmcz48cGF0aCBkPSJNMjguOTk5IDg3LjMzNmMtMTYuMDUtMTYuMDUtMTYuMDUtNDIuMDg3IDAtNTguMTM3QzM4LjY4NSAxOS41MTIgNDguMzcgOS44MjYgNTguMDc3LjE0TDg3LjEzNiAyOS4yYzE2LjA1IDE2LjA1IDE2LjA1IDQyLjA4NyAwIDU4LjEzNy0xNi4wNSAxNi4wNS00Mi4wODcgMTYuMDUtNTguMTM3IDB6IiBjbGlwLXBhdGg9InVybCgjYSkiIGZpbGw9IiM3MGFkNDciIGZpbGwtcnVsZT0iZXZlbm9kZCIgdHJhbnNmb3JtPSJtYXRyaXgoLjI2NDU4IDAgMCAuMjY0NTggLTQuNDg4IC0uMDM3KSIgaWQ9InBhdGg3IiAvPjxwYXRoIGQ9Ik0zLjA3NCAxNS4zODJjMC00LjI4OSAzLjQ5NS03Ljc3MyA3Ljc5NC03Ljc3MyA0LjMwNSAwIDcuNzk0IDMuNDg0IDcuNzk0IDcuNzczIDAgNC4yOTQtMy40ODkgNy43NzMtNy43OTQgNy43NzMtNC4zIDAtNy43OTQtMy40NzktNy43OTQtNy43NzN6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGlkPSJwYXRoOSIgLz48L3N2Zz4=");
background-repeat: no-repeat;
background-size: cover;
width: 50px;
height: 60px;
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>
我给你写了一个函数,可以根据旧方向计算出正确的角度
她需要获得新旧角度 它将return您需要添加的方向以达到新的方向 (如果箭头需要向后移动它会 return 减去它会向后移动)
function newRotate(oldV, newV) {
const diff1 = newV - oldV;
let myOldV = oldV;
if (newV < oldV) newV += 360;
else myOldV += 360;
const diff2 = newV - myOldV;
const shortDiff = Math.abs(diff1) < Math.abs(diff2) ? diff1 : diff2;
return oldV + shortDiff;
}
这是使用方法
const value =newRotate(oldValue,newValue)
Animated.timing(routeAnimtion, {
toValue: value,
duration: 10,
}).start();