fix: shadow
This commit is contained in:
parent
eadb745d63
commit
92578a7dce
|
|
@ -13,6 +13,7 @@ import { Canvas, Paragraph as SkiaParagraph, Path, Skia, useFonts } from '@shopi
|
||||||
import ParallelogramButton from '@/components/ParallelogramButton'
|
import ParallelogramButton from '@/components/ParallelogramButton'
|
||||||
import ParallelogramGridItem from '@/components/ParallelogramGridItem'
|
import ParallelogramGridItem from '@/components/ParallelogramGridItem'
|
||||||
import BannerSection from '@/components/BannerSection'
|
import BannerSection from '@/components/BannerSection'
|
||||||
|
import ParallelogramShadow from '@/components/ParallelogramShadow'
|
||||||
import { useTemplateActions } from '@/hooks/actions/use-template-actions'
|
import { useTemplateActions } from '@/hooks/actions/use-template-actions'
|
||||||
import { useTemplates } from '@/hooks/data'
|
import { useTemplates } from '@/hooks/data'
|
||||||
import { useFavoriteTemplates } from '@/hooks/data/use-favorite-templates'
|
import { useFavoriteTemplates } from '@/hooks/data/use-favorite-templates'
|
||||||
|
|
@ -582,26 +583,29 @@ const GooActions = observer<GooActionsProps>(function GooActions({ gooPoints, on
|
||||||
onClick={onAddGoo}
|
onClick={onAddGoo}
|
||||||
>
|
>
|
||||||
<Canvas style={{ position: 'absolute', inset: 0 }}>
|
<Canvas style={{ position: 'absolute', inset: 0 }}>
|
||||||
|
{/* 白色主体 */}
|
||||||
<Path
|
<Path
|
||||||
path={Skia.Path.Make()
|
path={Skia.Path.Make()
|
||||||
.moveTo(skewOffset+padding, padding)
|
.moveTo(skewOffset + padding, padding)
|
||||||
.lineTo(width-padding, padding)
|
.lineTo(width - padding, padding)
|
||||||
.lineTo(width - skewOffset-padding, height-padding)
|
.lineTo(width - skewOffset - padding, height - padding)
|
||||||
.lineTo(padding, height-padding)
|
.lineTo(padding, height - padding)
|
||||||
.close()}
|
.close()}
|
||||||
color={Skia.Color('#FFFFFF')}
|
color={Skia.Color('#FFFFFF')}
|
||||||
/>
|
/>
|
||||||
|
{/* 黑色描边(适当加粗,避免底边过细) */}
|
||||||
<Path
|
<Path
|
||||||
path={Skia.Path.Make()
|
path={Skia.Path.Make()
|
||||||
.moveTo(skewOffset+padding, padding)
|
.moveTo(skewOffset + padding, padding)
|
||||||
.lineTo(width-padding, padding)
|
.lineTo(width - padding, padding)
|
||||||
.lineTo(width - skewOffset-padding, height-padding)
|
.lineTo(width - skewOffset - padding, height - padding)
|
||||||
.lineTo(padding, height-padding)
|
.lineTo(padding, height - padding)
|
||||||
.close()}
|
.close()}
|
||||||
color={Skia.Color('#000000')}
|
color={Skia.Color('#323232')}
|
||||||
style="stroke"
|
style="stroke"
|
||||||
strokeWidth={1}
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
|
<ParallelogramShadow height={height} padding={padding} skewOffset={skewOffset} width={width} />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
<Block className="absolute inset-0 flex-row items-center gap-[4px] pl-[12px]">
|
<Block className="absolute inset-0 flex-row items-center gap-[4px] pl-[12px]">
|
||||||
{isDev && isPolling && <Block className="ml-[4px] size-[6px] rounded-full bg-green-500" />}
|
{isDev && isPolling && <Block className="ml-[4px] size-[6px] rounded-full bg-green-500" />}
|
||||||
|
|
@ -624,13 +628,13 @@ const GooActions = observer<GooActionsProps>(function GooActions({ gooPoints, on
|
||||||
.lineTo(addWidth - addSkewOffset - padding, addHeight - padding)
|
.lineTo(addWidth - addSkewOffset - padding, addHeight - padding)
|
||||||
.lineTo(padding, addHeight - padding)
|
.lineTo(padding, addHeight - padding)
|
||||||
.close()}
|
.close()}
|
||||||
color={Skia.Color('#000000')}
|
color={Skia.Color('#323232')}
|
||||||
style="stroke"
|
style="stroke"
|
||||||
strokeWidth={1}
|
strokeWidth={1}
|
||||||
/>
|
/>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
<Block className="absolute inset-0 items-center justify-center">
|
<Block className="absolute inset-0 items-center justify-center">
|
||||||
<Ionicons color="#000000" name="add" size={12} style={{ fontWeight: 'bold' }} />
|
<Ionicons color="#323232" name="add" size={12} style={{ fontWeight: 'bold' }} />
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import {
|
||||||
vec,
|
vec,
|
||||||
} from '@shopify/react-native-skia'
|
} from '@shopify/react-native-skia'
|
||||||
import { Block } from '@share/components'
|
import { Block } from '@share/components'
|
||||||
|
import ParallelogramShadow from './ParallelogramShadow'
|
||||||
|
|
||||||
type MediaItem = {
|
type MediaItem = {
|
||||||
id: string
|
id: string
|
||||||
|
|
@ -103,10 +104,14 @@ const ParallelogramGridItem = memo<Props>(function ParallelogramGridItem({
|
||||||
|
|
||||||
const labelHeight = 24
|
const labelHeight = 24
|
||||||
const cardHeight = itemWidth + labelHeight
|
const cardHeight = itemWidth + labelHeight
|
||||||
|
// 预留给外部阴影的额外画布高度,避免阴影被裁剪
|
||||||
|
const shadowMargin = 4
|
||||||
|
|
||||||
// 平行四边形路径(只裁剪内容,不拉伸内容)
|
// 平行四边形路径(只裁剪内容,不拉伸内容)
|
||||||
const skewOffset = 8
|
const skewOffset = 8
|
||||||
const padding = 2 // 四周内缩,避免描边被裁掉
|
const padding = 2 // 四周内缩,避免描边被裁掉
|
||||||
|
|
||||||
|
// 外层(黑色)边框 & 裁剪路径
|
||||||
const parallelogramPath = useMemo(() => {
|
const parallelogramPath = useMemo(() => {
|
||||||
const p = Skia.Path.Make()
|
const p = Skia.Path.Make()
|
||||||
p.moveTo(skewOffset + padding, padding)
|
p.moveTo(skewOffset + padding, padding)
|
||||||
|
|
@ -181,8 +186,8 @@ const ParallelogramGridItem = memo<Props>(function ParallelogramGridItem({
|
||||||
height: cardHeight,
|
height: cardHeight,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Block style={{ width: itemWidth, height: cardHeight, position: 'relative' }}>
|
<Block style={{ width: itemWidth, height: cardHeight + shadowMargin, position: 'relative' }}>
|
||||||
<Canvas style={{ width: itemWidth, height: cardHeight, position: 'absolute' }}>
|
<Canvas style={{ width: itemWidth, height: cardHeight + shadowMargin, position: 'absolute' }}>
|
||||||
<Group clip={parallelogramPath}>
|
<Group clip={parallelogramPath}>
|
||||||
{isVisible && displayImage && (
|
{isVisible && displayImage && (
|
||||||
<SkiaImage
|
<SkiaImage
|
||||||
|
|
@ -215,7 +220,7 @@ const ParallelogramGridItem = memo<Props>(function ParallelogramGridItem({
|
||||||
y={itemWidth}
|
y={itemWidth}
|
||||||
width={itemWidth}
|
width={itemWidth}
|
||||||
height={1}
|
height={1}
|
||||||
color="#000000"
|
color="#323232"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -238,11 +243,20 @@ const ParallelogramGridItem = memo<Props>(function ParallelogramGridItem({
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
{/* 先画阴影,再画描边,保证描边永远在最外层 */}
|
||||||
|
<ParallelogramShadow
|
||||||
|
height={cardHeight + shadowMargin}
|
||||||
|
baseHeight={cardHeight}
|
||||||
|
padding={padding}
|
||||||
|
skewOffset={skewOffset}
|
||||||
|
width={itemWidth}
|
||||||
|
/>
|
||||||
|
|
||||||
<Path
|
<Path
|
||||||
path={parallelogramPath}
|
path={parallelogramPath}
|
||||||
style="stroke"
|
style="stroke"
|
||||||
strokeWidth={isSelected ? 3 : 2}
|
strokeWidth={3}
|
||||||
color={isSelected ? '#FFE500' : '#000000'}
|
color={isSelected ? '#FFE500' : '#323232'}
|
||||||
/>
|
/>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
import { Path, Skia } from '@shopify/react-native-skia'
|
||||||
|
|
||||||
|
export type ParallelogramShadowProps = {
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
skewOffset: number
|
||||||
|
padding: number
|
||||||
|
/** 平行四边形主体的高度(即底边所在的 y),不传则等于 height */
|
||||||
|
baseHeight?: number
|
||||||
|
/** 阴影整体偏移量,默认 2 像素 */
|
||||||
|
offset?: number
|
||||||
|
/** 阴影颜色,默认 #323232 */
|
||||||
|
color?: string
|
||||||
|
/** 阴影线粗细,默认 3 像素 */
|
||||||
|
strokeWidth?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用平行四边形按钮/卡片的底部 + 右侧硬阴影
|
||||||
|
*
|
||||||
|
* 约定:
|
||||||
|
* - 与主体外侧的黑色描边紧贴
|
||||||
|
* - 整体向右下偏移 offset 像素
|
||||||
|
*/
|
||||||
|
const ParallelogramShadow = memo<ParallelogramShadowProps>(function ParallelogramShadow({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
skewOffset,
|
||||||
|
padding,
|
||||||
|
baseHeight,
|
||||||
|
offset = 2,
|
||||||
|
color = '#323232',
|
||||||
|
strokeWidth = 3,
|
||||||
|
}) {
|
||||||
|
const skiaColor = Skia.Color(color)
|
||||||
|
const h = baseHeight ?? height
|
||||||
|
// 只有在提供 baseHeight(即有额外画布空间)时才再往外多挪 1 像素,避免压住原始边框又不被裁剪
|
||||||
|
const extraOffsetY = baseHeight ? 1 : 0
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* 底部阴影线 */}
|
||||||
|
<Path
|
||||||
|
path={Skia.Path.Make()
|
||||||
|
// 当有 baseHeight 时:相对于主体底边再向下挪 1px;否则保持在 canvas 内部
|
||||||
|
.moveTo(padding + offset, h - padding + offset + extraOffsetY)
|
||||||
|
.lineTo(width - skewOffset - padding + offset, h - padding + offset + extraOffsetY)}
|
||||||
|
color={skiaColor}
|
||||||
|
style="stroke"
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
/>
|
||||||
|
{/* 右侧阴影线 */}
|
||||||
|
<Path
|
||||||
|
path={Skia.Path.Make()
|
||||||
|
// 右侧阴影:仅在垂直方向多挪 1px,水平方向仍保持在 canvas 内
|
||||||
|
.moveTo(width - skewOffset - padding + offset, h - padding + offset + extraOffsetY)
|
||||||
|
.lineTo(width - padding + offset, padding + offset + extraOffsetY)}
|
||||||
|
color={skiaColor}
|
||||||
|
style="stroke"
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
ParallelogramShadow.displayName = 'ParallelogramShadow'
|
||||||
|
|
||||||
|
export default ParallelogramShadow
|
||||||
|
|
||||||
Loading…
Reference in New Issue