React Native变换与中心点的转换

17

我想旋转一个Text组件,角度为-90deg。该组件应该从左侧角落而不是中心旋转。我正在使用以下代码:

render() {
     return (
            <View style = {{flex : 1}}>
                <View style={styles.sidebar}>
                    <Text style={styles.lblSideBar} numberOfLines = {1} >DUMMY TEXT</Text>
                </View>
            </View>);
}

const styles = StyleSheet.create({
  sidebar : {
    flex : 1,
    flexDirection : 'row',
    alignItems : 'flex-end',
    justifyContent : 'center',
    width : 30,
  },
  lblSideBar : {
      bottom : 20,
      transform : [{rotate : '-90deg'}],
  }
});

我想要底部空间为20像素,但由于旋转默认从中心进行,所以文本在旋转后覆盖了底部区域。请建议如何实现? 此外react-native需要支持pivotPointanchorPointtransformOrigin,以便可以轻松地实现此属性。


1
我考虑了一下,有了以下的想法。如果我们把文本放在一个视图中,然后旋转该视图。然后我们将文本绝对定位在视图的左上角。 这对我起作用了。我现在不确定如何制作一个工作示例,但也许有人有时间做到这一点并发布一个答案。 - morksinaanab
6个回答

22

我刚刚创建了一个withAnchorPoint函数,可以使得在react-native中使用锚点的变换更加容易。 https://github.com/sueLan/react-native-anchor-point.

您可以像这样使用它:

import { withAnchorPoint } from 'react-native-anchor-point';

getTransform = () => {
    let transform = {
        transform: [{ perspective: 400 }, { rotateX: rotateValue }],
    };
    return withAnchorPoint(transform, { x: 0.5, y: 0 }, { width: CARD_WIDTH, height: CARD_HEIGHT });
};
    
<Animated.View style={[styles.blockBlue, this.getTransform()]} />

我还为此撰写了一篇文章。enter image description here

以下的代码可以设置视图的锚点或称为中心点。

  1. 在x轴、y轴、z轴上平移视图
  2. 应用旋转
  3. 在x轴、y轴、z轴上将视图向后平移-x、-y、-z
          translateX: -w / 2
          rotateY
          translateX: w / 2

这意味着将锚点设置为(0,0.5)。我们在变换样式中应用它,如下所示

   const transform = {
      transform: [
          {translateX: -w / 2}, 
          rotateY, 
          {translateX: w / 2}
      ]
    }
    return (   
        <Animated.View style={transform}></Animated.View>
    )
  }

          translateX: w / 2
          rotateY
          translateX: -w / 2

这意味着将锚点设置为 (1, 0.5)

          translateX: -w / 2
          translateY: -h / 2
          rotateZ
          translateX: w / 2
          translateY: h / 2

这意味着将锚点设置为 (0, 0)

          translateX: w / 2
          translateY: h / 2
          rotateZ
          translateX: -w / 2
          translateX: -h / 2

这意味着将锚点设置为 (1, 1)

在iOS中,它被称为锚点。关于锚点

layer.anchorPoint = CGPointMake(0, 0)

在安卓中,它被称为枢轴点。

  viewToMove.setPivotX(0);
  viewToMove.setPivotY(0);

2
constructor(props) {
     super(props)
     this.state = {
          angle: 0
     }
}

componentDidMount() {
    this.progress()
}

progress(){
     intervalId = BackgroundTimer.setInterval(() => {      
         this.setState({angle: this.state.angle +1})   
     }, (1000); // 1000 milliseconds
}



render () {
        const dx = responsiveHeight(9.5);
        const dy = responsiveHeight(9.5);

        const position= {
            transform: [
              {
                translateX: Math.cos((360 - this.state.angle)  * Math.PI / 180) * dx - Math.sin((360 - this.state.angle) * Math.PI / 180) * dy
              },
              {
                translateY:  Math.sin((360 - this.state.angle)  * Math.PI / 180) * dx + Math.cos((360 - this.state.angle) * Math.PI / 180) * dy
              }
            ]
          };

        return(
            <Animated.View style={position}>
                <Text>Text move</Text>
            </Animated.View>

        );
}

注意:responsiveHeight、responsiveWidth是在react-native-responsive-dimensions中引入的。
请在react-native-background-timer中查看BackgroundTimer。
导入一些库。


0
在做一个项目时,我遇到了一个问题,当我尝试围绕某个点旋转图像时,我无法在React Native中使用CSS来实现。但是我找到了一种方法。
  1. 将您的图像转换为SVG格式,最好使用矢量图像。(您可以使用许多在线工具进行此操作,也可以使用Adobe Illustrator获取SVG代码)。

  2. 然后转到此网站,在该网站上,您可以将SVG代码转换为JSX。我喜欢这个网站,因为使用它,您可以将其转换为适用于React Native和React的代码。

  3. 然后,您可以将JSX添加到您的代码中并运行它,但在此之前,请从此处安装react-native-svg。

  4. 然后通过<G transform=”rotate(90, 300 ,300)” >将整个路径或SVG中的任何内容分组,您可以根据自己的选择执行操作。

//在这里,旋转道具按旋转角度、要围绕其旋转图像的x和y坐标的顺序排列。 ……

或者执行其他操作

<G transform=”scale(.4, .4) translate(520,0)” > …..

您可以在此处查看实时示例。

https://snack.expo.io/@ajay19293/rotate-image-around-a-pivot-point-


0

这个GitHub问题已经有解决方案了。

如果您能够在渲染方法中使用SVG,您可以像这样处理:

const pointX = 25;
const pointY = 25;
<Svg onLayout={this.onLayout} viewBox="0 0 50 50">
  {/* Rotate about point x y */}
  <G transform={`translate(${pointX}, ${pointY})`}>
    {/* Everything in AnimatedG gets rotated */}
    <AnimatedG style={{
      transform: [
        {
          translateX: -this.state.offset
        },
        {
          rotate: animation.interpolate({
            inputRange: [0, 1],
            outputRange: ['0deg', '360deg']
          })
        },
        {
          translateX: this.state.offset
        }
      ]
    }}>
      <G transform={`translate(-${pointX}, -${pointY})`}>
        <Path fill={this.props.color} d="M4.295 0A4.233 4.233 0 001.24 1.24l.75.75a3.175 3.175 0 012.243-.932 3.175 3.175 0 012.244.932l.75-.75A4.233 4.233 0 004.295 0z" />
      </G>
    </AnimatedG>
  </G>
</Svg>

this.state.offset 是一个针对 Android 的 hack,因为它的行为不同。设置该值的 onlayout 如下所示。

onLayout = Platform.OS === 'android'
    ? e => { this.setState({ offset: e.nativeEvent.layout.width / 2 }) }
    : null;

注意:使用25作为我的x和y将围绕中心旋转。
发布解决方案的用户包括这个完全功能的示例

0
以下代码可能会有所帮助,红色视图将使用(0.5,0)作为中心点进行180度的转换,类似于iOS的anchorPoint:
/**
 * Created by YQB on 16/9/14.
 */
import React, {Component} from 'react';
import {StyleSheet,View,Animated,Easing} from 'react-native';

var dimensions =  require('Dimensions') ;
var bgHeight = dimensions.get('window').height;
var bgWidth = dimensions.get('window').width;
var viewHeight = 100;

class RotaTest extends Component {
    constructor(props) {
        super(props);
        this.state = {
            transformView: new Animated.Value(0),
        };
    }
    componentDidMount() {
        Animated.timing(this.state.transformView,{toValue:1,duration:1000}).start();
    }
    render() {
        return(
            <View style={{flex:1}}>
                <View style={layouts.lineLayout}/>
                <Animated.View
                    style={[layouts.bgViewLayout,{transform:[
                        {translateY: -viewHeight/2},
                        {rotateX:this.state.transformView.interpolate({inputRange:[0,1], outputRange:['0deg','180deg']})},
                        {translateY:viewHeight/2}
                    ]}]}/>
            </View>
        );
    }
}
const layouts = StyleSheet.create({
    bgViewLayout:{
        width:bgWidth * 0.3,
        height:viewHeight,
        top: 100,
        left:100,
        backgroundColor:'red'
    },
    lineLayout:{
        width:bgWidth,
        height:0.5,
        top:100,
        backgroundColor:'black'
    }
});
export default RotaTest;

-1

我遇到了相同的问题。 以下是解决方法:

尽管不直接支持以枢轴点旋转,但您可以通过组合旋转、transformX和transformY来实现相同的结果 - 这并不难:

  1. 假设我们已经有了枢轴点的坐标。 在您的情况下,您可以挂钩onLayout事件,该事件会给您提供x、y、width和height。

  2. 取要旋转的对象的中心。同样,onLayout是您的好朋友。

  3. 现在取两个点的x和y差异,并使用这个方便的公式, 其中角度是您想要旋转的角度:

    rad = angle * Math.PI / 180 transformX(Math.cos(angle) * dx - Math.sin(angle) * dy) transformY(Math.sin(angle) * dx + Math.cos(angle) * dy) rotate(angle+"deg")

我把上面的公式留给读者作为练习 :) 实际上,这很简单的三角学。


非常感谢!但对我来说,只设置translateY就可以了 >.< - iou90
9
“dx”和“dy”是什么? - devth
31
“我将其留给读者作为练习…”仅提供部分答案并在最后摆手一下是不明智的。 - Phil Andrews

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接