89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
import React from 'react';
|
|
import { StyleSheet, View } from 'react-native';
|
|
import Svg, { Defs, LinearGradient, Stop, Text as SvgText, TSpan } from 'react-native-svg';
|
|
|
|
interface GradientTextProps {
|
|
text: string;
|
|
color?: { offset: string, color: string }[];
|
|
fontSize?: number;
|
|
fontWeight?: string;
|
|
width?: number;
|
|
lineHeight?: number;
|
|
}
|
|
|
|
export default function GradientText(props: GradientTextProps) {
|
|
const { text, color, fontSize = 48, fontWeight = "700", width = 300, lineHeight = 1.2 } = props;
|
|
|
|
// Split text into words and create lines that fit within the specified width
|
|
const createLines = (text: string, maxWidth: number) => {
|
|
const words = text.split(' ');
|
|
const lines: string[] = [];
|
|
let currentLine = '';
|
|
|
|
words.forEach(word => {
|
|
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
// Approximate text width (this is a simple estimation)
|
|
const testWidth = testLine.length * (fontSize * 0.6);
|
|
|
|
if (testWidth > maxWidth && currentLine) {
|
|
lines.push(currentLine);
|
|
currentLine = word;
|
|
} else {
|
|
currentLine = testLine;
|
|
}
|
|
});
|
|
|
|
if (currentLine) {
|
|
lines.push(currentLine);
|
|
}
|
|
|
|
return lines;
|
|
};
|
|
|
|
const lines = createLines(text, width - 40); // 40px padding
|
|
const lineHeightPx = fontSize * lineHeight;
|
|
const totalHeight = lines.length * lineHeightPx;
|
|
|
|
return (
|
|
<View style={[styles.container, { width }]}>
|
|
<Svg height={totalHeight} width={width}>
|
|
<Defs>
|
|
<LinearGradient id="textGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
{color?.map((item, index) => (
|
|
<Stop key={index} offset={item.offset} stopColor={item.color} />
|
|
))}
|
|
</LinearGradient>
|
|
</Defs>
|
|
|
|
<SvgText
|
|
x="50%"
|
|
y={fontSize}
|
|
fontFamily="System"
|
|
fontSize={fontSize}
|
|
fontWeight={fontWeight}
|
|
textAnchor="middle"
|
|
fill="url(#textGradient)"
|
|
>
|
|
{lines.map((line, index) => (
|
|
<TSpan
|
|
key={index}
|
|
x="50%"
|
|
dy={index === 0 ? 0 : lineHeightPx}
|
|
textAnchor="middle"
|
|
>
|
|
{line}
|
|
</TSpan>
|
|
))}
|
|
</SvgText>
|
|
</Svg>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
alignSelf: 'center',
|
|
},
|
|
}); |