javascript - React Native Animated - 以按下为中心展开圆圈

标签 javascript css react-native animation react-animated

我正在尝试使用 React Native 上的 Animated 创建一个组件,其中一个圆圈从按下的点扩展到包围整个屏幕。

这个想法本质上是一个颜色轮播,比如说:

const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];

您从颜色 0 作为背景开始,然后,当您按下屏幕时,颜色 1 的圆圈从按下点开始扩展(从无到有),并占据整个屏幕。此时,随着动画的完成,colorIndex 会递增,并且动画圆会同时被删除,这样我们就可以无缝地移至下一个颜色,即现在的背景。 (例如,我们现在使用“黑色”作为背景颜色)。

然后,当您再次按下时,该过程会重复,展开一个“绿色”圆圈以填充屏幕,然后将绿色更新为背景色,等等。

(为了澄清我在动画中寻找的内容,请查看 this GIF(减去图标等))。

我正在尝试使用动画和如下代码,在按下主背景组件(TouchableHighlight)时调用:

triggerSwipe(event) {
  this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });

  Animated.timing(
    this.state.diameter,
    { toValue: Dimensions.get('window').height * 2, duration: 500 },
  ).start(() => {
    this.state.diameter.setValue(0);
    this.setState({ colorIndex: this.state.colorIndex + 1 });
  });
}

然后,我的想法是,在 render 函数中,我设置了 absolutelefttop定位圆形组件以等于位置,并将 widthheight 设置为等于 diameter,以及 borderRadius (diameter/2.0 不起作用,因为 diameter 是一个动画对象,而不是数字)。

这里有两个问题我似乎无法弄清楚(都在这个问题底部的 GIF 中可见):

  1. 每个动画之前都会有一个黑色闪光。它涵盖了整个 TouchableHighlight 组件。而且它总是黑色的。不管我穿什么颜色。组件中没有硬编码的黑色(!)。
  2. 位置决定了圆的边缘(或者更准确地说,是圆所转录的正方形),而不是中心。我希望它确定圆的中心,以便圆从我的打印机向外扩展。

我假设如果没有所有代码,#1 真的很难推理。因此,我将在下面粘贴完整的组件代码。我希望第二个更概念化/更容易弄清楚,而无需使用它。

有人能想出一个好方法来断言圆的中心的位置吗?我担心它需要不断更新圆的左/上位置作为其直径的函数(left: location.x -diameter._value/2),这将消除所有据我了解,动画的 native 性能优势。还有更好的想法吗?

这是完整的组件代码:

import React from 'react';
import { TouchableHighlight, Animated } from 'react-native';
import { Dimensions } from 'react-native';

const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];

const color = index => colors[index % colors.length];

class ColorScape extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      colorIndex: 0,
      location: { x: 0, y: 0 },
      diameter: new Animated.Value(0)
    };
  }

  triggerSwipe(event) {
    this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });

    Animated.timing(
      this.state.diameter,
      { toValue: Dimensions.get('window').height * 2, duration: 500 },
    ).start(() => {
      this.state.diameter.setValue(0);
      this.setState({ colorIndex: this.state.colorIndex + 1 });
    });
  }

  render() {
    const { colorIndex, diameter, location } = this.state;

    const circleStyles = {
      backgroundColor: color(colorIndex + 1),
      width: diameter,
      height: diameter,
      borderRadius: diameter,
      position: 'absolute',
      zIndex: 2,
      left: location.x,
      top: location.y
    };

    return (
      <TouchableHighlight
        style={ {
          flex: 1,
          width: '100%',
          height: '100%',
          zIndex: 1,
          backgroundColor: color(colorIndex)
        } }
        onPress={ (event) => this.triggerSwipe(event) }
      >
        <Animated.View
          style={ circleStyles }
        />
      </TouchableHighlight>
    );
  }
}

export default ColorScape;

以下是当前功能(在 iPhone X 模拟器中):

enter image description here

最佳答案

如果您希望圆圈从点击点开始扩展,我建议使用 transform:scale() 而不是设置宽度/高度属性的动画。这样您只需为一个属性设置动画即可。

您仍然需要将圆居中。假设您将宽度/高度设置为 100px。现在,您将 transform:scale(0) 设置为初始大小,如果需要,您可以将圆圈放大到超过 1,这样它将占据全屏。您可以通过数学来获得正确的时机/感觉。

使用这种方法,您仍然会遇到同样的问题,即圆圈从左上角扩大。那是因为你已经把它放在那里了。顶部/左侧是相对于父容器的。现在您需要将圆相对于自身居中。这意味着您需要添加另一个 transform 属性。 变换:translateX(-50%)translateY(-50%)。这将始终使您的圆相对于其中心位置居中。

开始转换:转换:translateX(-50%)translateY(-50%)scale(0) 放大变换:transform:translateX(-50%)translateY(-50%)scale(x),其中x是您希望圆达到的大小。

关于javascript - React Native Animated - 以按下为中心展开圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52301791/

相关文章:

javascript - Rails ERB 内部 Javascript

css - 如何动态更改数组中显示的样式文本组件的属性?

ios - React Native iOS - CocoaPods 找不到 Flipper-Folly 的兼容版本,它们需要更高的最低部署目标

javascript - 用于在 JSON 文件内搜索的 Node.js 端点未返回

javascript - 不要直接改变状态。使用 setState()

javascript - jquery 工具提示抛出错误 : function not defined

html - 旋转 Outlook 客户端正文中的图像

html - <div> 的高度未在 IE 浏览器的表格单元格中计算

javascript - 'async' 修饰符不能在 typescript react 中使用

javascript - ASP.NET web方法获取带有参数的ajax