152 lines
3.7 KiB
Vue
Executable File
152 lines
3.7 KiB
Vue
Executable File
<template>
|
||
<view
|
||
class="clay-card"
|
||
:class="[
|
||
`clay-card-${size}`,
|
||
{ 'clay-card-primary': variant === 'primary' },
|
||
{ 'clay-card-gold': variant === 'gold' },
|
||
{ 'clay-card-inset': inset },
|
||
customClass
|
||
]"
|
||
:style="customStyle"
|
||
@tap="handleTap"
|
||
>
|
||
<slot></slot>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'ClayCard',
|
||
props: {
|
||
// 卡片尺寸:sm, md, lg
|
||
size: {
|
||
type: String,
|
||
default: 'md'
|
||
},
|
||
// 变体:default, primary, gold
|
||
variant: {
|
||
type: String,
|
||
default: 'default'
|
||
},
|
||
// 是否凹陷效果
|
||
inset: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 自定义类名
|
||
customClass: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// 自定义样式
|
||
customStyle: {
|
||
type: Object,
|
||
default: () => ({})
|
||
}
|
||
},
|
||
methods: {
|
||
handleTap(e) {
|
||
this.$emit('tap', e)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* ============================================
|
||
Claymorphism 卡片组件
|
||
使用示例:
|
||
<ClayCard size="lg" variant="primary">内容</ClayCard>
|
||
============================================ */
|
||
|
||
.clay-card {
|
||
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||
border-radius: 24rpx;
|
||
position: relative;
|
||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||
|
||
/* 外部双阴影 - 创造凸起效果 */
|
||
box-shadow:
|
||
8rpx 8rpx 16rpx rgba(0, 0, 0, 0.06),
|
||
-8rpx -8rpx 16rpx rgba(255, 255, 255, 0.8),
|
||
inset 2rpx 2rpx 4rpx rgba(255, 255, 255, 0.9),
|
||
inset -2rpx -2rpx 4rpx rgba(0, 0, 0, 0.03);
|
||
|
||
&.clay-card-sm {
|
||
border-radius: 16rpx;
|
||
box-shadow:
|
||
6rpx 6rpx 12rpx rgba(0, 0, 0, 0.04),
|
||
-6rpx -6rpx 12rpx rgba(255, 255, 255, 0.8),
|
||
inset 2rpx 2rpx 4rpx rgba(255, 255, 255, 0.9),
|
||
inset -2rpx -2rpx 4rpx rgba(0, 0, 0, 0.03);
|
||
}
|
||
|
||
&.clay-card-md {
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
&.clay-card-lg {
|
||
border-radius: 32rpx;
|
||
box-shadow:
|
||
12rpx 12rpx 24rpx rgba(0, 0, 0, 0.08),
|
||
-12rpx -12rpx 24rpx rgba(255, 255, 255, 0.7),
|
||
inset 4rpx 4rpx 8rpx rgba(255, 255, 255, 0.85),
|
||
inset -4rpx -4rpx 8rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
box-shadow:
|
||
4rpx 4rpx 8rpx rgba(0, 0, 0, 0.06),
|
||
-4rpx -4rpx 8rpx rgba(255, 255, 255, 0.6),
|
||
inset 4rpx 4rpx 8rpx rgba(0, 0, 0, 0.05),
|
||
inset -4rpx -4rpx 8rpx rgba(255, 255, 255, 0.4);
|
||
}
|
||
}
|
||
|
||
/* 彩色粘土卡片 */
|
||
.clay-card-primary {
|
||
background: linear-gradient(145deg, #FF9500, #FF6B00);
|
||
color: #fff;
|
||
box-shadow:
|
||
10rpx 10rpx 20rpx rgba(255, 107, 0, 0.2),
|
||
-10rpx -10rpx 20rpx rgba(255, 255, 255, 0.7),
|
||
inset 3rpx 3rpx 6rpx rgba(255, 255, 255, 0.4),
|
||
inset -3rpx -3rpx 6rpx rgba(0, 0, 0, 0.1);
|
||
|
||
&:active {
|
||
box-shadow:
|
||
5rpx 5rpx 10rpx rgba(255, 107, 0, 0.25),
|
||
-5rpx -5rpx 10rpx rgba(255, 255, 255, 0.5),
|
||
inset 5rpx 5rpx 10rpx rgba(0, 0, 0, 0.15),
|
||
inset -5rpx -5rpx 10rpx rgba(255, 255, 255, 0.2);
|
||
}
|
||
}
|
||
|
||
.clay-card-gold {
|
||
background: linear-gradient(145deg, #FFD60A, #FF9F0A);
|
||
box-shadow:
|
||
10rpx 10rpx 20rpx rgba(255, 159, 10, 0.2),
|
||
-10rpx -10rpx 20rpx rgba(255, 255, 255, 0.7),
|
||
inset 3rpx 3rpx 6rpx rgba(255, 255, 255, 0.4),
|
||
inset -3rpx -3rpx 6rpx rgba(0, 0, 0, 0.1);
|
||
|
||
&:active {
|
||
box-shadow:
|
||
5rpx 5rpx 10rpx rgba(255, 159, 10, 0.25),
|
||
-5rpx -5rpx 10rpx rgba(255, 255, 255, 0.5),
|
||
inset 5rpx 5rpx 10rpx rgba(0, 0, 0, 0.15),
|
||
inset -5rpx -5rpx 10rpx rgba(255, 255, 255, 0.2);
|
||
}
|
||
}
|
||
|
||
/* 凹陷粘土卡片 (Inset) */
|
||
.clay-card-inset {
|
||
background: linear-gradient(145deg, #e8e8e8, #f8f8f8);
|
||
box-shadow:
|
||
inset 6rpx 6rpx 12rpx rgba(0, 0, 0, 0.08),
|
||
inset -6rpx -6rpx 12rpx rgba(255, 255, 255, 0.9);
|
||
}
|
||
</style>
|