在React Native中创建矩阵变换系统?

34

我刚刚在React Native中建立了一个相对复杂的图像编辑用户界面。

体验意图与Instagram非常相似,具有捏合缩放,平移和旋转功能。

变换以数据形式存储,例如:

transformation: {
  bottomBoundary: 1989,
  leftBoundary: 410,
  rightBoundary: 1634,
  topBoundary: 765,
  rotation: 0,
},
其中topBoundarybottomBoundary是相对于图像顶部的偏移量,leftBoundaryrightBoundary是相对于图像左侧的偏移量。

旋转时,由于React Native使用对象的中心作为变换原点,因此在90°或270°方向上,需要对图像进行偏移,以使它们仍然"粘附"在顶部/左侧并可以被偏移:

calculateRotationOffset.js

export default function (width, height) {
  const transform = [
    { rotate: `${this.rotation}deg` },
  ]

  /*
    RN rotates around centre point, so we need to
    manually offset the rotation to stick the image
    to the top left corner so that our offsets will
    work.
  */
  if (this.rotation === 90) {
    transform.push(
      { translateX: -((width - height) / 2) },
      { translateY: -((width - height) / 2) },
    )
  } else if (this.rotation === 270) {
    transform.push(
      { translateX: ((width - height) / 2) },
      { translateY: ((width - height) / 2) },
    )
  }
  return transform
}

我的旋转和缩放实现存在问题。

这是完整的示例。

要重现错误,请按照以下步骤:

  1. 将图像旋转一次
  2. 捏合缩放
  3. 再次旋转图像

图像现在将被翻转和偏移不正确。

为了重现错误,这里顺序发生了至少三个变换,因此我无法找到问题所在。

如果需要,本问题肯定会有赏金,我还可能提供货币奖励。谢谢!

更新:经过一些建议,似乎最好的解决方法是通过矩阵变换,然后以某种方式将该矩阵转换回RN可以在屏幕上表示的样式。 矩阵变换需要支持平移,旋转和缩放。


2
这听起来像是一个常见的问题,当你用不应该分离的子变换来表示一个变换时会出现这种情况。你有直接设置矩阵并组合不同矩阵的选项吗?顺便说一下,我不了解React框架。这很可能会让事情变得更容易。例如,当你旋转图像时,偏移量也必须随之旋转。这将通过单个矩阵和适当的运算符隐式完成。 - Nico Schertler
1
@NicoSchertler 我想这是一个选项,但我这样做的原因是为了尽可能轻松地从主图像反弹转换后的图像,根据变换数据。具体来说,使用Cloudinary API。如果您有完全重写解决方案的想法,请通过私信与我联系。 - j_d
1
这些变换是有顺序依赖的,因此如果您正在使用与预期相同的变换顺序(在编辑时),请检查您的代码,但正如Nico所指出的那样,使用累积单个3x3均匀矩阵比这更容易且不会出错。有关更多信息,请参见:理解4x4齐次变换矩阵,它们是3D的,因此您的矩阵将没有Z轴和Z坐标(3x3矩阵),删除(Xz,Yz,Zx,Zy,ZzZ?列中的一个零)。 - Spektre
1
@Spektre 是的,我已经看到过这个提到几次了,但是我不明白这有多简单。 - j_d
1
不要处理打开的命令列表,这些命令相互影响,而是应用或仅记住单个3x3矩阵,而不管情况如何。没有任何if条件。 - Spektre
显示剩余13条评论
1个回答

1
我会用多点触控的方式,使用分解的转换矩阵(旋转、缩放、平移)替换bottomBoundary等内容,并在UI中更新矩阵的平移组件,通过双指操作进行变换,使图像似乎粘在手指上。如果您想将旋转限制为90度的增量,则可以在用户松开时捕捉它。这样可以在不需要当前旋转按钮的情况下自由直观地移动图像。
始终以分解形式存储矩阵可以避免必须对其进行分解或规范化以避免累积数值不准确性(倾斜和改变纵横比)。
创建一个新的DecomposedMatrix类可以帮助结构化代码。关键是要大致处理它的变换,如下所示:
scaleBy(scale) {
    this.scale *= scale;
    this.x *= scale;
    this.y *= scale;
}

1
这个回答太笼统了,只是重复了原帖评论中已经提到的事情。 - j_d
2
@IsaacHinman 它完全改变了 UI,内部逻辑并颠覆了关于是否应该使用需要转换为 React Native 格式的转换矩阵的想法。所以它不是重新陈述事情,而是采取了一个全新的方法。我本来还要添加示例代码,但刚刚改变了我的想法... - jjrv
1
@jjrv 那可能是因为我在你写完之前就已经读完了答案。随你喜欢! - j_d

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