#react-native #touchableopacity #onpress #panresponder
#react-native #touchableopacity #при нажатии #panresponder
Вопрос:
Я пытаюсь создать вращающийся кубик Рубика, в котором каждый маленький кубик является осязаемым компонентом, который запускает событие — прикосновение к кубикам оранжевого, зеленого и желтого цветов запускает правильные события, тогда как прикосновение к некоторым кубикам других цветов приводит к запуску событий на одном из этих 3 (оранжевый / зеленый / желтый) цвета. Как мне это исправить?
Это App.js:
import React, { Component, PropTypes } from 'react';
import {
Dimensions,
PanResponder,
View,
TouchableOpacity,
Text,
} from 'react-native';
import { transformOrigin, rotateXY, rotateXZ } from './utils';
import SmallBox from './SmallBox';
const HEIGHT = Dimensions.get('window').height;
const WIDTH = Dimensions.get('window').width;
const styles = {
container: {
position: 'absolute',
left: WIDTH / 2 - 50,
top: HEIGHT / 2 - 50,
width: 100,
height: 100,
backgroundColor: 'transparent',
},
rectangle: {
position: 'absolute',
left: 0,
top: 0,
width: 100,
height: 100,
zIndex: 10,
},
smallBox: {
height: 100 / 3,
width: 100 / 3,
borderWidth: 1,
justifyContent: 'center',
alignItems: 'center',
},
};
export default class Cube extends Component {
componentWillMount() {
this.panResponder = PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onPanResponderMove: this.handlePanResponderMove.bind(this),
});
}
handlePanResponderMove(e, gestureState) {
const { dx, dy } = gestureState;
const origin = { x: 0, y: 0, z: -50 };
let matrix = rotateXY(dx, dy);
transformOrigin(matrix, origin);
this.refViewFront.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
//test
matrix = rotateXY(dx 180, dy);
transformOrigin(matrix, origin);
this.refViewBack.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
matrix = rotateXY(dx 90, dy);
transformOrigin(matrix, origin);
this.refViewRight.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
matrix = rotateXY(dx - 90, dy);
transformOrigin(matrix, origin);
this.refViewLeft.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
matrix = rotateXZ(dx, dy - 90);
transformOrigin(matrix, origin);
this.refViewTop.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
matrix = rotateXZ(-dx, dy 90);
transformOrigin(matrix, origin);
this.refViewBottom.setNativeProps({
style: { transform: [{ perspective: 1000 }, { matrix: matrix }] },
});
}
renderRight(color) {
return (
<View
ref={(component) => (this.refViewRight = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='yellow' position='top-left' />
<SmallBox num={1} color='yellow' position='top-middle' />
<SmallBox num={1} color='yellow' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='yellow' position='middle-left' />
<SmallBox num={1} color='yellow' position='middle-middle' />
<SmallBox num={1} color='yellow' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='yellow' position='bottom-left' />
<SmallBox num={1} color='yellow' position='bottom-middle' />
<SmallBox num={1} color='yellow' position='bottom-right' />
</View>
</View>
);
}
renderLeft(color) {
return (
<View
ref={(component) => (this.refViewLeft = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='blue' position='top-left' />
<SmallBox num={1} color='blue' position='top-middle' />
<SmallBox num={1} color='blue' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='blue' position='middle-left' />
<SmallBox num={1} color='blue' position='middle-middle' />
<SmallBox num={1} color='blue' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='blue' position='bottom-left' />
<SmallBox num={1} color='blue' position='bottom-middle' />
<SmallBox num={1} color='blue' position='bottom-right' />
</View>
</View>
);
}
renderFront(color) {
return (
<View
ref={(component) => (this.refViewFront = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='red' position='top-left' />
<SmallBox num={1} color='red' position='top-middle' />
<SmallBox num={1} color='red' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='red' position='middle-left' />
<SmallBox num={1} color='red' position='middle-middle' />
<SmallBox num={1} color='red' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='red' position='bottom-left' />
<SmallBox num={1} color='red' position='bottom-middle' />
<SmallBox num={1} color='red' position='bottom-right' />
</View>
</View>
);
}
renderBack(color) {
return (
<View
ref={(component) => (this.refViewBack = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='green' position='top-left' />
<SmallBox num={1} color='green' position='top-middle' />
<SmallBox num={1} color='green' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='green' position='middle-left' />
<SmallBox num={1} color='green' position='middle-middle' />
<SmallBox num={1} color='green' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='green' position='bottom-left' />
<SmallBox num={1} color='green' position='bottom-middle' />
<SmallBox num={1} color='green' position='bottom-right' />
</View>
</View>
);
}
renderTop(color) {
return (
<View
ref={(component) => (this.refViewTop = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='white' position='top-left' />
<SmallBox num={1} color='white' position='top-middle' />
<SmallBox num={1} color='white' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='white' position='middle-left' />
<SmallBox num={1} color='white' position='middle-middle' />
<SmallBox num={1} color='white' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='white' position='bottom-left' />
<SmallBox num={1} color='white' position='bottom-middle' />
<SmallBox num={1} color='white' position='bottom-right' />
</View>
</View>
);
}
renderBottom(color) {
return (
<View
ref={(component) => (this.refViewBottom = component)}
style={[styles.rectangle, color ? { backgroundColor: color } : null]}
{...this.panResponder.panHandlers}
>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='orange' position='top-left' />
<SmallBox num={1} color='orange' position='top-middle' />
<SmallBox num={1} color='orange' position='top-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='orange' position='middle-left' />
<SmallBox num={1} color='orange' position='middle-middle' />
<SmallBox num={1} color='orange' position='middle-right' />
</View>
<View style={{ flexDirection: 'row' }}>
<SmallBox num={1} color='orange' position='bottom-left' />
<SmallBox num={1} color='orange' position='bottom-middle' />
<SmallBox num={1} color='orange' position='bottom-right' />
</View>
</View>
);
}
render() {
return (
<View style={{ flex: 1, backgroundColor: '#fff5c0' }}>
<View style={styles.container}>
{this.renderLeft('blue')}
{this.renderRight('yellow')}
{this.renderFront('red')}
{this.renderBack('green')}
{this.renderTop('white')}
{this.renderBottom('orange')}
</View>
</View>
);
}
}
Это utils.js:
import MatrixMath from 'react-native/Libraries/Utilities/MatrixMath';
export const rotateXY = (dx, dy) => {
const radX = (Math.PI / 180) * dy;
const cosX = Math.cos(radX);
const sinX = Math.sin(radX);
const radY = (Math.PI / 180) * -dx;
const cosY = Math.cos(radY);
const sinY = Math.sin(radY);
return [
cosY,
sinX * sinY,
cosX * sinY,
0,
0,
cosX,
-sinX,
0,
-sinY,
cosY * sinX,
cosX * cosY,
0,
0,
0,
0,
1,
];
};
export const rotateXZ = (dx, dy) => {
const radX = (Math.PI / 180) * dx;
const cosX = Math.cos(radX);
const sinX = Math.sin(radX);
const radY = (Math.PI / 180) * dy;
const cosY = Math.cos(radY);
const sinY = Math.sin(radY);
return [
cosX,
-cosY * sinX,
sinX * sinY,
0,
sinX,
cosX * cosY,
-sinY * cosX,
0,
0,
sinY,
cosY,
0,
0,
0,
0,
1,
];
};
//source: https://gist.github.com/jmurzy/0d62c0b5ea88ca806c16b5e8a16deb6a#file-foldview-transformutil-transformorigin-js
export const transformOrigin = (matrix, origin) => {
const { x, y, z } = origin;
const translate = MatrixMath.createIdentityMatrix();
MatrixMath.reuseTranslate3dCommand(translate, x, y, z);
MatrixMath.multiplyInto(matrix, translate, matrix);
const untranslate = MatrixMath.createIdentityMatrix();
MatrixMath.reuseTranslate3dCommand(untranslate, -x, -y, -z);
MatrixMath.multiplyInto(matrix, matrix, untranslate);
};
Это SmallBox.js:
import React from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
TouchableHighlight,
} from 'react-native';
export default function SmallBox({ num, position, color }) {
return (
<TouchableOpacity
style={styles.smallBox}
onPress={() => console.log(color, position)}
>
<Text>{num}</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
smallBox: {
margin: 0.2,
height: 100 / 3,
width: 100 / 3,
borderWidth: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Комментарии:
1. Возможно ли, что щелчок «проходит» через ваш компонент и щелкает по другой стороне куба?
2. Это возможно — противоположная сторона запускает событие.. как мне проверить? Есть идеи, как это исправить?
3. Вы можете отобразить только одну сторону куба и проверить, правильно ли срабатывают все цвета. Если они это делают, то, скорее всего, это происходит с другой стороны. Также добавьте идентификатор к каждой стороне сетки, как в (31,32,33, где дом десятых — это сторона, а единица измерения — 1-9) и запишите это в журнал консоли.