import React, { memo, useMemo } from 'react' import { Pressable } from 'react-native' import { Group, Paragraph, Skia, useFonts } from '@shopify/react-native-skia' import ParallelogramShape from './ParallelogramShape' export type ParallelogramButtonProps = { label: string state: string isActive: boolean onPress: () => void width: number height: number } const ParallelogramButton = memo(function ParallelogramButton({ label, state, isActive, onPress, width, height, }) { const fontMgr = useFonts({ System: [], }) // 创建英文 state 标签段落(白色字体,黑色描边,字重 700,激活时 #FAE307,未激活时白色) const stateParagraph = useMemo(() => { if (!fontMgr) return null const para = Skia.ParagraphBuilder.Make({}, fontMgr) .pushStyle({ color: isActive ? Skia.Color('#FAE307') : Skia.Color('#FFFFFF'), fontSize: 7, fontFamilies: ['System'], fontStyle: { weight: 700 }, shadows: [ // 黑色描边效果(略微偏移,避免过粗) { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -0.5, y: -0.5 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0.5, y: -0.5 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -0.5, y: 0.5 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0.5, y: 0.5 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -0.5, y: 0 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0.5, y: 0 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0, y: -0.5 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0, y: 0.5 } }, ], }) .addText(state) .build() para.layout(40) return para }, [fontMgr, state, isActive]) // 创建白色字体带黑色描边的中文文本段落 const paragraph = useMemo(() => { if (!fontMgr) return null const para = Skia.ParagraphBuilder.Make({}, fontMgr) .pushStyle({ color: Skia.Color('#FFFFFF'), fontSize: 13, fontFamilies: ['System'], fontStyle: { weight: 900 }, shadows: [ { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -1, y: -1 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 1, y: -1 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -1, y: 1 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 1, y: 1 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: -1, y: 0 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 1, y: 0 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0, y: -1 } }, { color: Skia.Color('#323232'), blurRadius: 0, offset: { x: 0, y: 1 } }, ], }) .addText(label) .build() para.layout(width - 12) // 减去左右 padding return para }, [fontMgr, label, width]) const skewOffset = 8 // 倾斜偏移量(像素)- 统一所有平行四边形的倾斜角度 const padding = 15 // 增加 padding,防止旋转后的文本被裁剪 // 计算实际画布尺寸(包含 padding) const canvasWidth = width + padding * 2 const canvasHeight = height + padding * 2 // 注意:布局占位仍然使用原始 width,避免改变 tab 间距 return ( ( <> {/* 英文 state 标签 - 左上角,以左下角为中心,逆时针旋转 15 度 */} {stateParagraph && (() => { const stateTextX = 8 + skewOffset / 2 + 10 + padding const stateTextY = 4 + padding const rotationAngle = (-15 * Math.PI) / 180 const centerX = padding const centerY = height + padding return ( ) })()} {/* 中文文本 - 以左下角为中心,逆时针旋转 15 度 */} {paragraph && (() => { const textX = 16 + skewOffset / 2 + 2 + padding const textY = height - paragraph.getHeight() + 1 + padding const rotationAngle = (-15 * Math.PI) / 180 const centerX = padding const centerY = height + padding return ( ) })()} )} /> ) }) ParallelogramButton.displayName = 'ParallelogramButton' export default ParallelogramButton