我有一个组件 父母 其中有一个Animated.value "this.progress",它的取值范围是[1, 3]。
父节点渲染一个组件 儿童 和 传来 作为道具。
// File Parent.js
import React from "react";
import { Animated } from "react-native";
import Child from "./Child.js"
class Parent extends React.Component {
constructor(props) {
super(props);
this.progress = new Animated.Value(1)
}
render() {
return (
<Child
progress = {this.progress}
/>
);
}
}
孩子的位置取决于进度。
如果一个动画改变了进度的值,那么Child必须以accoringly的方式移动(例如,如果进度从1到2的动画,用户必须看到Child以平稳的方式从[1,3]移动到[2,2])。
为此,我使用了,两个插值。
// In the constructor of Child.js
this.interpolateX = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [1, 2, 1],
});
this.interpolateY = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [3, 2, 1],
});
我用它们来固定 "孩子 "的位置 用 "变换"。
// Render method of Child.js
render() {
return (
<Animated.View
style={[
{
transform: [
{
translateX: this.interpolateX,
},
{
translateY: this.interpolateY,
},
],
},
{ position: 'absolute' },
{ left: 0 },
{ top: 0 },
]}
/>
);
}
效果很好,但现在我还想用用户的手指让孩子移动。为此,我定义了一个panResponder。问题是panResponder也使用了一个transform。现在我有两个变换。
我不知道如何结合这两个变换。这是我试过的。
// File Child.js
import React from "react";
import { Animated, PanResponder } from "react-native";
class Child extends React.Component {
constructor(props) {
super(props);
this.interpolateX = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [1, 2, 1],
});
this.interpolateY = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [3, 2, 1],
});
this.offset = new Animated.ValueXY({ x: 0, y: 0 });
this._val = { x: 0, y: 0 };
this.offset.addListener((value) => (this._val = value));
// Initiate the panResponder
this.panResponder = PanResponder.create({
// Ask to be the responder
onStartShouldSetPanResponder: () => true,
// Called when the gesture starts
onPanResponderGrant: () => {
this.offset.setOffset({
x: this._val.x,
y: this._val.y,
});
this.offset.setValue({ x: 0, y: 0 });
},
// Called when a move is made
onPanResponderMove: Animated.event([
null,
{ dx: this.offset.x, dy: this.offset.y },
]),
onPanResponderRelease: (evt, gesturestate) => {
console.log(
"released with offsetX: " +
this.offset.x._value +
"/" +
this.offset.y._value
);
},
});
}
render() {
const panStyle = {
transform: this.offset.getTranslateTransform(),
};
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
panStyle,
{
transform: [
{
translateX: this.interpolateX,
},
{
translateY: this.interpolateY,
},
],
},
{ position: "absolute" },
{ left: 0 },
{ top: 0 },
]}
/>
);
}
}
export default Child;
没有用,panStyle似乎被忽略了。我想你不可能将两个变换组合在一起。
我也试过在变换中 "添加 "这两个表达式,但没有成功(也许是可行的)。
我最后的想法是,当用户移动Child时,有一个布尔值 "isMoving "等于true。如果isMoving为假,我就使用第一个变换,否则就使用第二个变换。这看起来很有希望,但我没有成功地使它工作。
你能告诉我如何做到这一点吗?
一个布尔变量isMoving表示使用哪种变换是好主意。技巧是。
这就是结果。
// File Child.js
import React from "react";
import { Animated, PanResponder } from "react-native";
class Child extends React.Component {
constructor(props) {
super(props);
this.interpolateX = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [1, 2, 1],
});
this.interpolateY = this.props.progress.interpolate({
inputRange: [1, 2, 3],
outputRange: [3, 2, 1],
});
this.offset = new Animated.ValueXY({ x: 0, y: 0 });
this.state = {
isMoving: false,
};
// Initiate the panResponder
this.panResponder = PanResponder.create({
// Ask to be the responder
onStartShouldSetPanResponder: () => true,
// Called when the gesture starts
onPanResponderGrant: () => {
this.setState({
isMoving: true,
});
this.offset.setOffset({
x: this.interpolateX.__getValue(),
y: this.interpolateY.__getValue(),
});
this.offset.setValue({ x: 0, y: 0 });
},
// Called when a move is made
onPanResponderMove: Animated.event([
null,
{ dx: this.offset.x, dy: this.offset.y },
]),
onPanResponderRelease: (evt, gesturestate) => {
this.setState({
isMoving: false,
});
},
});
}
render() {
const panStyle = {
transform: this.offset.getTranslateTransform(),
};
if (this.state.isMoving)
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[panStyle, { position: "absolute" }, { left: 0 }, { top: 0 }]}
/>
);
else
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
{
transform: [
{
translateX: this.interpolateX,
},
{
translateY: this.interpolateY,
},
],
},
{ position: "absolute" },
{ left: 0 },
{ top: 0 },
]}
/>
);
}
}
export default Child;