反应本机线性渐变圆角边缘纹理

时间:2019-01-03 16:29:28

标签: javascript react-native gradient expo linear-gradients

如您在图像中看到的,第一个圆导致边缘为石榴石, 第二圈。

第二个圆是使用以下方法创建的:LinearGradient di expo,“ react-native-community”。

第一个圆圈是使用js代码编写的,您可以在下面找到该代码,所涉及的库是rn-gradients,我报告该代码的原因是为了更好地理解该操作是为了解决此问题。

我尝试了很多尝试,但是无法解决这个问题。

我想尝试解决这个问题,因为与react-native-community相比,该模块非常轻巧,因此不需要链接。

有人可以给我一些建议吗?

链接:Expo

代码:

import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { LinearGradient } from './rn-gradients/index.js';
import { LinearGradient as LinearGradient2 } from 'expo';

export default class App extends Component {
  render() {
    var size = 80;
    return (
      <View
        style={{
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: '#000',
        }}>
        <LinearGradient
          colors={['#8a49a1', '#c1558b', '#e56969', '#ffc273', '#ffdf9e']}
          height={size}
          width={size}
          rotation={90}
          style={{
            borderRadius: size / 2,
            alignItems: 'center',
            justifyContent: 'center',
          }}>
          <Text
            style={{
              fontSize: 10,
            }}>
            LinearGradient
          </Text>
        </LinearGradient>
        <LinearGradient2
          colors={['#8a49a1', '#c1558b', '#e56969', '#ffc273', '#ffdf9e']}
          height={size}
          width={size}
          rotation={90}
          style={{
            borderRadius: size / 2,
            marginTop: 10,
            alignItems: 'center',
            justifyContent: 'center',
          }}>
          <Text
            style={{
              fontSize: 10,
            }}>
            LinearGradient2
          </Text>
        </LinearGradient2>
      </View>
    );
  }
}

LinearGradient:

import React from 'react';
import PropTypes from 'prop-types';
import { View, StyleSheet, Animated, Dimensions } from 'react-native';
//const {height as heightD, width as widthD} = Dimensions.get('window');
import { normalizeIntervals, degToRad } from './utils';

const { hairlineWidth } = StyleSheet;
const doubleHairlineWidth = hairlineWidth * 2;
const negativeHairlineWidth = -hairlineWidth;

export default class LinearGradient extends React.Component {
  render() {
    const { style, height, width, colors, children } = this.props;
    let { intervals, rotation } = this.props;

    rotation %= 360; // set rotation greater than 360° to its less than 360° equivalent

    if (rotation < 0) {
      rotation = 360 + rotation; // set negative rotation to its positive equivalent
    }

    let normalizedRotation = rotation;
    let scaleX = 1;
    let scaleY = 1;

    if (rotation >= 90) {
      if (rotation <= 180) {
        normalizedRotation = 180 - normalizedRotation;
        scaleY = -1;
      } else if (rotation < 270) {
        normalizedRotation %= 90;
        scaleX = -1;
        scaleY = -1;
      } else if (rotation < 360) {
        normalizedRotation = 360 - normalizedRotation;
        scaleX = -1;
      }
    }

    const sin1 = Math.sin(degToRad(90 - normalizedRotation));
    const sin2 = Math.sin(degToRad(normalizedRotation));
    const gradientYLength = height * sin1 + width * sin2;
    const gradientXLength = width * sin1 + height * sin2;
    const gradientArrayLength = Math.ceil(gradientYLength / hairlineWidth);
    const normalIntervals = normalizeIntervals(
      intervals,
      colors,
      gradientArrayLength
    );

    return (
      <View
        style={[style, { height, width, overflow: 'hidden' }]}>
        <View style={styles.container}>
          <View
            style={{
              transform: [
                { scaleX },
                { scaleY },
                { rotate: `${normalizedRotation}deg` },
              ],
            }}>
            {[...Array(gradientArrayLength)].map((_, i) => {
              return (
                <Animated.View
                  key={i}
                  style={{
                    height: doubleHairlineWidth,
                    marginTop: negativeHairlineWidth,
                    width: gradientXLength,
                    backgroundColor: new Animated.Value(i).interpolate({
                      inputRange: normalIntervals,
                      outputRange: colors,
                    }),
                  }}
                />
              );
            })}
          </View>
        </View>
        {children}
      </View>
    );
  }
}

LinearGradient.defaultProps = {
  height: 5,
  width: 5,
  rotation: 0,
};

LinearGradient.propTypes = {
  height: PropTypes.any,
  width: PropTypes.any,
  colors: PropTypes.arrayOf(PropTypes.string).isRequired,
  intervals: PropTypes.arrayOf(PropTypes.number),
  rotation: PropTypes.number, // in degrees - NOT radians.
};

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFill,
    justifyContent: 'center',
    alignItems: 'center',
    //overflow: 'hidden',
  },
});

实用程序:

export function normalizeIntervals(intervals, colors, gradientArrayLength) {
  if (intervals) {
    if (intervals.length !== colors.length) {
      throw new Error('intervals.length should be equal to colors.length');
    }
    if (!intervals.every((e, i, a) => !i || e > a[i - 1])) {
      throw new Error(
        'Each consecutive interval must be greater than the previous one'
      );
    }
  } else if (!intervals) {
    const { length } = colors;
    intervals = [...Array(length)].map((_, i) => i / (length - 1));
  }

  return intervals.map(num => num * (gradientArrayLength - 1));
}

const DEG_PER_RAD = Math.PI / 180;
export const degToRad = deg => deg * DEG_PER_RAD;

export const getHypotenuse = (a, b) => Math.sqrt(a ** 2 + b ** 2);

0 个答案:

没有答案