How to scale an object from top left to react natively using matrices?

I read this article, which explains how to make rotation transforms into responsive native using MatrixMath. I am trying to animate the scale of the object, not the rotation, and I want it to scale using the source in the upper left corner, and not in the center of the object. Can anyone explain how to do this?

Corresponding code bits for the rotation matrix:

const matrix = transformUtil.rotateX(dx);
transformUtil.origin(matrix, { x: 0, y, z: 0 });

const perspective = this.props.perspective || rootDefaultProps.perspective;

ref.setNativeProps({
  style: {
    transform: [
      { perspective },
      { matrix },
    ],
  },
});

and from transformUtil:

import MatrixMath from 'react-native/Libraries/Utilities/MatrixMath';

function 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);
}

function rotateX(deg) {
  const rad = (Math.PI / 180) * deg;
  const cos = Math.cos(rad);
  const sin = Math.sitransfn(rad);
  return [
    1, 0, 0, 0,
    0, cos, -sin, 0,
    0, sin, cos, 0,
    0, 0, 0, 1,
  ];
}

export default {
  rotateX,
  origin: transformOrigin,
};
+6
source share
1 answer

, , , ( ) . , - .

, Snack: https://snack.expo.io/BJnDImQlr

:

, , , . transformOrigin , OP . , , ( ).


    function transformOrigin(matrix, origin) {
        const { x, y, z } = origin;

        const translate = MatrixMath.createIdentityMatrix();
        MatrixMath.reuseTranslate3dCommand(translate, x, y, z);
        MatrixMath.multiplyInto(matrix, translate, matrix);
    }

, ( MatrixMath.createIdentityMatrix), . , , , , x.


    function scale(x) {
        return [
            x, 0, 0, 0,
            0, x, 0, 0,
            0, 0, x, 0,
            0, 0, 0, 1
        ];
    }

.

  • ref .
  • .
  • .
  • (xAxis: 0, yAxis: 0).
  • MatrixMath.multiplyInto .
  • ref setNativeProps.

    function transformScale(ref, scaleBy, width, height) {
        const matrix = MatrixMath.createIdentityMatrix();
        const toScale = scale(scaleBy);

        transformOrigin(matrix, {
            x: (width * scaleBy - width) / 2,
            y: (height * scaleBy - height) / 2,
            z: 0
        });

        MatrixMath.multiplyInto(matrix, matrix, toScale);

        ref.setNativeProps({
            style: { transform: [{ matrix }] }
        });
    }

, , React. , transformScale(this._target, 3, width, height). , scaleBy , .


    export default class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                width: 0,
                height: 0
            };
        }

        handleBaseLayout = (e) => {
            const { width, height } = e.nativeEvent.layout;

            this.setState({ width, height }, () => {
                transformScale(this._target, 3, width, height);
            });
        };

        render() {
            return (
                <View style={styles.container}>
                    <View
                        style={styles.target}
                        ref={c => (this._target = c)}
                        onLayout={this.handleBaseLayout}
                    />
                </View>
            );
        }
    }

    const styles = StyleSheet.create({
        container: {
            flex: 1,
            justifyContent: 'center',
            paddingTop: Constants.statusBarHeight,
            backgroundColor: '#ecf0f1',
            padding: 8,
        },
        target: {
            width: 100,
            height: 100,
            backgroundColor: 'blue',
        },
    });

0

Source: https://habr.com/ru/post/1679912/


All Articles