在 React Native 中保存时旋转图像的问题

Sah*_*a D 5 android rotation signature ios react-native

实际行为:

我应该在横向右模式下实现签名板以及绘制签名的时间戳。然后对视图进行截图,并通过旋转将其以纵向模式保存在文档目录(iOS)或外部目录(Android)中。我成功地使用transform: [{rotate: '90deg"}]css属性和react-native-signature-capture在横向右模式下实现了签名屏幕,使用react-native-view-shot和react-native-view-shot保存了捕获的签名截图以及在本地目录中绘制的签名的时间戳使用 react-native-fs 将其转换为 base64 格式。

但是保存的屏幕截图不是纵向模式,我尝试旋转图像,同时将其保存在文档目录 (iOS) 或外部目录 (Android) 中而不使用任何模块。我还尝试在使用画布上下文 API 保存图像时旋转图像,但无法找到在 react-native 中访问画布以旋转图像的方法,同时将其保存为画布与 HTML DOM 相关。

预期行为:

我应该将与时间戳一起绘制的签名以纵向模式保存在文档目录(iOS)或外部目录(Android)中,如下面的屏幕截图所示。

其他资源:

代码 :

render() {
  return (
    <View
    style={{
      flex: 1,
      flexDirection: 'row',
      overflow: "hidden",
    }}>
    <StatusBar hidden={true} />
    <View
      style={{
        flex: 0.8,
        flexDirection: 'row-reverse',
        marginVertical: width / 18,
        overflow: "hidden",
      }}>
      <ViewShot
        ref="viewShot"
        style={[styles.viewShot, { transform: [{ rotate: this.state.bool && '90deg' }] }]}>
        {/* options={{ width: height, height: width }}> */}
        <SignatureCapture
          style={styles.signature}
          ref={sign => (this.signComponent = sign)}
          onSaveEvent={this._onSaveEvent}
          onDragEvent={this._onDragEvent}
          saveImageFileInExtStorage={true}
          showNativeButtons={false}
          showTitleLabel={false}
          showBorder={false}
          viewMode={'portrait'}
          square={true}
          backgroundColor={"white"}
          maxSize={800}
          rotateClockwise={!!true}
        />
        <View
          ref="timeRef"
          style={{
            width: width / 10,
            height: width / 3,
            justifyContent: 'flex-end',
            flexDirection: 'row-reverse',
          }}>
          <View
            style={{
              width: width / 1.8,
              height: width / 1.8,
              transform: [{ rotate: '-90deg' }],
              overflow: "hidden",
              paddingLeft: width / 18,
              paddingTop: width / 25
            }}>
            <Text style={styles.time}>{this.state.data}</Text>
          </View>
        </View>
      </ViewShot>
      <Image
        ref="imageRef"
        source={{ uri: this.state.imageUri }}
        style={{ transform: [{ rotate: '90deg' }] }}
      />
    </View>
    <View
      style={{
        flex: 0.2,
        alignItems: 'center',
        justifyContent: 'space-around',
        flexDirection: 'column',
        overflow: "hidden",
        backgroundColor: Colors.white,
      }}>
      <View
        style={{
          backgroundColor: Colors.darkGreen,
          width: width / 2,
          justifyContent: 'center',
          alignItems: 'center',
          paddingRight: width / 25,
          paddingVertical: width / 37.5,
          transform: [{ rotate: '-90deg' }],
          overflow: "hidden",
        }}>
        <TouchableOpacity
          hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
          onPress={() => {
            this.saveSign();
          }}>
          <Text style={{ fontSize: width / 18, color: Colors.white }}>Submit </Text>
        </TouchableOpacity>
      </View>
      <View
        style={{
          backgroundColor: '#5476ab',
          width: width / 2,
          justifyContent: 'center',
          alignItems: 'center',
          paddingVertical: width / 37.5,
          transform: [{ rotate: '-90deg' }],
          overflow: "hidden",
        }}>
        <TouchableOpacity
          hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
          onPress={() => {
            this.resetSign();
          }}>
          <Text style={{ fontSize: width / 18, color: Colors.white }}>Clear</Text>
        </TouchableOpacity>
      </View>
      <View
        style={{
          backgroundColor: '#73c5de',
          width: width / 2,
          justifyContent: 'center',
          alignItems: 'center',
          paddingVertical: 10,
          transform: [{ rotate: '-90deg' }],
        }}>
        <TouchableOpacity
          hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
          onPress={() => {
            this.onCancel();
          }}>
          <Text style={{ fontSize: width / 18, color: Colors.white }}>Cancel</Text>
        </TouchableOpacity>
      </View>
    </View>
  </View>


 );
}

_onSaveEvent(result) {

    this.setState({ signature: result.pathName, 
                    markResult: result.encoded });
  }

 _onDragEvent() {

    this.setState({ dragged: true });
  }

saveSign() {

    if (this.state.dragged === true) {
      this.setState({ bool: true });
      this.refs.viewShot.capture().then(uri => {
        this.setState({ imageUri: uri });
        console.log("uri123", uri);
         RNFS.readFile(this.state.imageUri, 
          'base64').then(image => {
          console.log("image123", image);
          this.setState({ sign: image }, () => {
            this.ChangeOrientation();
          });
        });
       });
      } else {
      Alert.alert('NALG', 'Please sign the signature 
      pad to submit');
      }

 ChangeOrientation() {

    this.props.getSignature(this.state.sign);
    this.props.setModalVisible(!this.props.modalVisible);
  }
Run Code Online (Sandbox Code Playgroud)

实际行为截图:

在此处输入图片说明

预期行为的屏幕截图:

在此处输入图片说明

环境:

反应原生:0.61.1

反应原生视图拍摄:^3.0.2

反应原生签名捕获:^0.4.10

反应本机-fs:^2.16.2

Kes*_*era 0

const showImagePicker = () => {
    const options = {
      title: i18n.t('issueReport.form.photoSelection'),
      storageOptions: {
        skipBackup: true,
        path: 'images',
      },
      allowsEditing: true,
    };

    ImagePicker.showImagePicker(options, response => {
      const { originalRotation } = response
      console.log('Response = ', response);
      console.log('originalRotation = ', originalRotation);

      if (originalRotation === 90) {
        setOriginalRotation(90)
      } else if (originalRotation === 270) {
        setOriginalRotation(-90)

      }
      setSelectedImageFile(response);

      if (response && response.height === 3000) {
        setLandscape(true)
      }

      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      } else {
        const source = { uri: response.uri };

        console.log('Image Path', source);
        // You can also display the image using data:
        // const source = { uri: 'data:image/jpeg;base64,' + response.data };
        setSelectedImage(source);
        setPhotoSelectVisible(true);
      }
    });
  };
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息 https://github.com/react-native-image-picker/react-native-image-picker/issues/655