文字加渐变效果

使用到的第三方库是react-native-svg,

效果如下:
image.png

代码如下:

import React, { useMemo, useState } from "react";
import { StyleSheet, Text as RNText, View } from "react-native";
import Svg, { Defs, LinearGradient, Stop, Text, Use } from "react-native-svg";
import { FontFamily } from "../../../constants";

const getFallbackWidth = (text, fontSize) => {
  const value = `${text ?? ""}`;
  let width = 0;

  value.split("").forEach((char) => {
    if (char === " ") {
      width += fontSize * 0.32;
    } else if (/[\u4e00-\u9fa5]/.test(char)) {
      width += fontSize;
    } else {
      width += fontSize * 0.58;
    }
  });

  return Math.max(1, Math.ceil(width));
};

/**
 * 渐变文字(根据文本适应宽度)
 */
export default function LinearGradientText({
  text,
  color01 = "#FEAE5C",
  color02 = "#FEF97B",
  color03 = "#FFFEAD",
  fontSize = 36,
  lineHeight = 44,
}) {
  const fallbackWidth = useMemo(() => getFallbackWidth(text, fontSize), [fontSize, text]);
  const [measuredWidth, setMeasuredWidth] = useState(0);
  const width = measuredWidth || fallbackWidth;
  const textStyle = useMemo(() => ({
    fontFamily: FontFamily.ExtraBold,
    fontSize,
    fontWeight: "800",
    lineHeight,
  }), [fontSize, lineHeight]);

  return <View style={{ width, height: lineHeight }}>
    <RNText
      numberOfLines={1}
      onLayout={({ nativeEvent }) => {
        const nextWidth = Math.ceil(nativeEvent.layout.width);
        if (nextWidth > 0 && nextWidth !== measuredWidth) {
          setMeasuredWidth(nextWidth);
        }
      }}
      style={[styles.measureText, textStyle]}>
      {text}
    </RNText>
    <Svg width={width} height={lineHeight} viewBox={`0 0 ${width} ${lineHeight}`}>
      <Defs>
        <LinearGradient
          id="Gradient"
          gradientUnits="userSpaceOnUse"
          x1="0"
          y1={lineHeight}
          x2={width}
          y2="0">
          <Stop offset="0.02" stopColor={color01} />
          <Stop offset="0.4" stopColor={color02} />
          <Stop offset="1" stopColor={color03} />
        </LinearGradient>
        <Text
          id="Text"
          x="0"
          y={fontSize}
          fontSize={fontSize}
          textAnchor="start"
          fontFamily={FontFamily.ExtraBold}
          fontWeight={"800"}>
          {text}
        </Text>
      </Defs>
      <Use href="#Text" fill="url(#Gradient)" />
    </Svg>
  </View>
}

const styles = StyleSheet.create({
  measureText: {
    left: 0,
    opacity: 0,
    position: "absolute",
    top: 0,
  },
});

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容