feat: 线性渐变字体+默认语言为中文
This commit is contained in:
parent
c85242f398
commit
1f35ce1c4a
@ -1,6 +1,6 @@
|
|||||||
import MemberBgSvg from '@/assets/icons/svg/memberBg.svg';
|
import MemberBgSvg from '@/assets/icons/svg/memberBg.svg';
|
||||||
import ProSecondTextSvg from '@/assets/icons/svg/proSecondText.svg';
|
|
||||||
import ProTextSvg from '@/assets/icons/svg/proText.svg';
|
import ProTextSvg from '@/assets/icons/svg/proText.svg';
|
||||||
|
import GradientText from '@/components/textLinear';
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
import { useRouter } from 'expo-router';
|
import { useRouter } from 'expo-router';
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -31,12 +31,20 @@ const MemberCard = ({ pro }: { pro: string }) => {
|
|||||||
{/* 会员标识 */}
|
{/* 会员标识 */}
|
||||||
<View style={[styles.memberContainer, { left: width * 0.25, top: width * 0.1, opacity: 1 }]}>
|
<View style={[styles.memberContainer, { left: width * 0.25, top: width * 0.1, opacity: 1 }]}>
|
||||||
<MemberBgSvg />
|
<MemberBgSvg />
|
||||||
<ThemedText style={{ fontSize: 12, color: "#2D3D60", position: "absolute", left: 0, top: 0, bottom: 0, right: 0, textAlign: "center", textAlignVertical: "center" }}>{"成为会员"}</ThemedText>
|
<ThemedText style={{ fontSize: 12, color: "#2D3D60", position: "absolute", left: 0, top: 0, bottom: 0, right: 0, textAlign: "center", textAlignVertical: "center" }}>{t("personal:member.goPremium")}</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
{/* 解锁更多魔法 */}
|
{/* 解锁更多魔法 */}
|
||||||
<View style={{ position: "absolute", bottom: width * 0.07, left: width * 0.1 }}>
|
<View style={{ position: "absolute", bottom: width * 0.02, left: -width * 0.01, opacity: pro === "pro" ? 1 : 0.5, width: width * 0.1, flexWrap: "wrap" }}>
|
||||||
{/* <ThemedText style={{ fontSize: 11, color: "red" }}>{"解锁更多魔法"}</ThemedText> */}
|
<GradientText
|
||||||
<ProSecondTextSvg />
|
text={t("personal:member.unlock")}
|
||||||
|
width={width * 0.4}
|
||||||
|
fontSize={16}
|
||||||
|
lineHeight={1.5}
|
||||||
|
color={[
|
||||||
|
{ offset: "0%", color: "#FF512F" },
|
||||||
|
{ offset: "100%", color: "#F09819" }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|||||||
89
components/textLinear.tsx
Normal file
89
components/textLinear.tsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
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',
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -36,7 +36,7 @@ i18n
|
|||||||
defaultNS: 'common',
|
defaultNS: 'common',
|
||||||
|
|
||||||
// 设置默认语言为中文
|
// 设置默认语言为中文
|
||||||
lng: 'zh',
|
lng: 'en',
|
||||||
fallbackLng: 'en',
|
fallbackLng: 'en',
|
||||||
debug: process.env.NODE_ENV === 'development',
|
debug: process.env.NODE_ENV === 'development',
|
||||||
|
|
||||||
|
|||||||
@ -125,5 +125,9 @@
|
|||||||
"agreement": "I have read and agree to",
|
"agreement": "I have read and agree to",
|
||||||
"membership": "《Membership Agreement》",
|
"membership": "《Membership Agreement》",
|
||||||
"agreementError": "Please read and agree to the agreement"
|
"agreementError": "Please read and agree to the agreement"
|
||||||
|
},
|
||||||
|
"member": {
|
||||||
|
"goPremium": "Go Premium",
|
||||||
|
"unlock": "Unlock more memory magic"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,5 +125,9 @@
|
|||||||
"agreement": "我已阅读并同意",
|
"agreement": "我已阅读并同意",
|
||||||
"membership": "《会员协议》",
|
"membership": "《会员协议》",
|
||||||
"agreementError": "请先阅读并同意协议"
|
"agreementError": "请先阅读并同意协议"
|
||||||
|
},
|
||||||
|
"member": {
|
||||||
|
"goPremium": "开通会员",
|
||||||
|
"unlock": "解锁更多记忆魔法"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -74,7 +74,7 @@
|
|||||||
"react-native-render-html": "^6.3.4",
|
"react-native-render-html": "^6.3.4",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"react-native-safe-area-context": "5.4.0",
|
||||||
"react-native-screens": "~4.11.1",
|
"react-native-screens": "~4.11.1",
|
||||||
"react-native-svg": "^15.11.2",
|
"react-native-svg": "15.11.2",
|
||||||
"react-native-toast-message": "^2.3.0",
|
"react-native-toast-message": "^2.3.0",
|
||||||
"react-native-uuid": "^2.0.3",
|
"react-native-uuid": "^2.0.3",
|
||||||
"react-native-view-shot": "4.0.3",
|
"react-native-view-shot": "4.0.3",
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
"react-native-render-html": "^6.3.4",
|
"react-native-render-html": "^6.3.4",
|
||||||
"react-native-safe-area-context": "5.4.0",
|
"react-native-safe-area-context": "5.4.0",
|
||||||
"react-native-screens": "~4.11.1",
|
"react-native-screens": "~4.11.1",
|
||||||
"react-native-svg": "^15.11.2",
|
"react-native-svg": "15.11.2",
|
||||||
"react-native-toast-message": "^2.3.0",
|
"react-native-toast-message": "^2.3.0",
|
||||||
"react-native-uuid": "^2.0.3",
|
"react-native-uuid": "^2.0.3",
|
||||||
"react-native-view-shot": "4.0.3",
|
"react-native-view-shot": "4.0.3",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user