import React, { memo, useMemo } from 'react' import { Pressable } from 'react-native' import { Canvas, Group, Image as SkiaImage, LinearGradient, Paragraph, Path, Rect, Skia, useFonts, useImage, vec, } from '@shopify/react-native-skia' type MediaItem = { id: string url: string webpPreviewUrl?: string authorName?: string likeCount?: number title?: string } type Props = { item: MediaItem isSelected: boolean itemWidth: number isVisible: boolean onSelect: () => void } const ParallelogramGridItem = memo(function ParallelogramGridItem({ item, isSelected, itemWidth, isVisible, onSelect, }) { const previewUrl = item.webpPreviewUrl || item.url || '' // 整个卡片(图片区域 + 底部文字区域)的高度 const labelHeight = 24 const cardHeight = itemWidth + labelHeight // 平行四边形路径(只裁剪内容,不拉伸内容),覆盖整张卡片 const skewOffset = 8 const padding = 2 // 四周内缩,避免描边被裁掉 const parallelogramPath = useMemo(() => { const p = Skia.Path.Make() // 顶点全部在 Canvas 内部,留出 padding 空间 p.moveTo(skewOffset + padding, padding) p.lineTo(itemWidth - padding, padding) p.lineTo(itemWidth - skewOffset - padding, cardHeight - padding) p.lineTo(padding, cardHeight - padding) p.close() return p }, [cardHeight, itemWidth]) const image = useImage(isVisible ? previewUrl : undefined) // 字体管理,用于绘制作者和点赞数文本 const fontMgr = useFonts({ System: [], }) const authorParagraph = useMemo(() => { if (!fontMgr) return null const builder = Skia.ParagraphBuilder.Make( { textAlign: 0, }, fontMgr, ) builder.pushStyle({ color: Skia.Color('#323232'), fontSize: 10, fontFamilies: ['System'], fontStyle: { weight: 400 }, }) builder.addText(item.authorName || '未知作者') const para = builder.build() para.layout(40) return para }, [fontMgr, item.authorName]) const likeParagraph = useMemo(() => { if (!fontMgr) return null const builder = Skia.ParagraphBuilder.Make( { textAlign: 0, }, fontMgr, ) // 红色小心形符号 builder.pushStyle({ color: Skia.Color('#FF0000'), fontSize: 8, fontFamilies: ['System'], fontStyle: { weight: 900 }, }) builder.addText('❤ ') // 白色数字 builder.pushStyle({ color: Skia.Color('#323232'), fontSize: 10, fontFamilies: ['System'], fontStyle: { weight: 400 }, }) builder.addText(String(item.likeCount ?? 0)) const para = builder.build() para.layout(40) return para }, [fontMgr, item.likeCount]) return ( {/* 整个卡片(图片 + 渐变 + 文本 + 黄色条)都被平行四边形裁剪 */} {/* 上半部分:背景图片 */} {image && ( )} {/* 图片区域上的底部遮罩渐变 */} {/* 底部黄色信息条(同样被平行四边形裁剪) */} {/* 底部作者 + 喜欢数文本(在平行四边形内部,显示在黄色条上) */} {authorParagraph && ( )} {likeParagraph && ( )} {/* 边框 */} ) }) export default ParallelogramGridItem