Merge pull request #20 from elderdog/main

feat: add border color option
This commit is contained in:
LeoKu 2023-09-29 12:02:52 +08:00 committed by GitHub
commit 06ad45f138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 10 deletions

View File

@ -21,6 +21,28 @@
</ul> </ul>
</SectionWrapper> </SectionWrapper>
<SectionWrapper :title="t('label.borderColor')">
<ul class="color-list">
<li
v-for="borderColor in SETTINGS.borderColor"
:key="borderColor"
class="color-list__item"
@click="switchBorderColor(borderColor)"
>
<div
:style="{ background: borderColor }"
class="bg-color"
:class="[
{
active: borderColor === avatarOption.background.borderColor,
transparent: borderColor === 'transparent',
},
]"
/>
</li>
</ul>
</SectionWrapper>
<SectionWrapper :title="t('label.backgroundColor')"> <SectionWrapper :title="t('label.backgroundColor')">
<ul class="color-list"> <ul class="color-list">
<li <li
@ -173,6 +195,15 @@ function switchWrapperShape(wrapperShape: WrapperShape) {
} }
} }
function switchBorderColor(borderColor: string) {
if (borderColor !== avatarOption.value.background.borderColor) {
setAvatarOption({
...avatarOption.value,
background: { ...avatarOption.value.background, borderColor },
})
}
}
function switchBgColor(bgColor: string) { function switchBgColor(bgColor: string) {
if (bgColor !== avatarOption.value.background.color) { if (bgColor !== avatarOption.value.background.color) {
setAvatarOption({ setAvatarOption({

View File

@ -5,12 +5,18 @@
:style="{ :style="{
width: `${avatarSize}px`, width: `${avatarSize}px`,
height: `${avatarSize}px`, height: `${avatarSize}px`,
...getWrapperShapeStyle(),
}" }"
:class="getWrapperShapeClassName()" :class="getWrapperShapeClassName()"
> >
<Background :color="avatarOption.background.color" /> <Background :color="avatarOption.background.color" />
<div class="avatar-payload" v-html="svgContent" /> <div class="avatar-payload" v-html="svgContent" />
<Border
:color="avatarOption.background.borderColor"
:radius="getWrapperShapeStyle().borderRadius"
/>
</div> </div>
</template> </template>
@ -26,10 +32,11 @@ import { ref, toRefs, watchEffect } from 'vue'
import { WidgetType, WrapperShape } from '@/enums' import { WidgetType, WrapperShape } from '@/enums'
import type { AvatarOption } from '@/types' import type { AvatarOption } from '@/types'
import { getRandomAvatarOption } from '@/utils' import { getRandomAvatarOption } from '@/utils'
import { AVATAR_LAYER, NONE } from '@/utils/constant' import { AVATAR_LAYER, NONE, SHAPE_STYLE_SET } from '@/utils/constant'
import { widgetData } from '@/utils/dynamic-data' import { widgetData } from '@/utils/dynamic-data'
import Background from './widgets/Background.vue' import Background from './widgets/Background.vue'
import Border from './widgets/Border.vue'
interface VueColorAvatarProps { interface VueColorAvatarProps {
option: AvatarOption option: AvatarOption
@ -58,6 +65,10 @@ function getWrapperShapeClassName() {
} }
} }
function getWrapperShapeStyle() {
return SHAPE_STYLE_SET[avatarOption.value.wrapperShape]
}
const svgContent = ref('') const svgContent = ref('')
watchEffect(async () => { watchEffect(async () => {
@ -133,15 +144,6 @@ watchEffect(async () => {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
&.circle {
border-radius: 50%;
}
&.squircle {
// TODO: Radius should adapt to the avatar size
border-radius: 25px;
}
.avatar-payload { .avatar-payload {
position: relative; position: relative;
z-index: 2; z-index: 2;

View File

@ -0,0 +1,31 @@
<template>
<div
class="avatar-border"
:style="{ borderColor: props.color, borderRadius: props.radius }"
></div>
</template>
<script lang="ts" setup>
import { type AvatarOption } from '../../types'
interface BorderProps {
color: AvatarOption['background']['borderColor']
radius: string
}
const props = defineProps<BorderProps>()
</script>
<style lang="scss" scoped>
.avatar-border {
position: absolute;
top: 0;
left: 0;
z-index: 3;
width: 100%;
height: 100%;
border-style: solid;
border-width: 10px;
transition: border-color 0.1s;
}
</style>

View File

@ -16,6 +16,7 @@ export default {
}, },
label: { label: {
wrapperShape: 'Avatar Shape', wrapperShape: 'Avatar Shape',
borderColor: 'Border Color',
backgroundColor: 'Background Color', backgroundColor: 'Background Color',
colors: 'colors', colors: 'colors',
}, },

View File

@ -16,6 +16,7 @@ export default {
}, },
label: { label: {
wrapperShape: '头像形状', wrapperShape: '头像形状',
borderColor: '边框颜色',
backgroundColor: '背景颜色', backgroundColor: '背景颜色',
colors: '颜色', colors: '颜色',
}, },

View File

@ -46,6 +46,7 @@ export interface AvatarOption {
background: { background: {
color: string color: string
borderColor: string
} }
widgets: Partial<AvatarWidgets> widgets: Partial<AvatarWidgets>
@ -70,4 +71,5 @@ export interface AvatarSettings {
commonColors: string[] commonColors: string[]
skinColors: string[] skinColors: string[]
backgroundColor: string[] backgroundColor: string[]
borderColor: string[]
} }

View File

@ -99,6 +99,10 @@ export const SETTINGS: Readonly<AvatarSettings> = {
'transparent', 'transparent',
] ]
}, },
get borderColor() {
return [...this.commonColors, 'transparent']
},
} }
export const SCREEN = { export const SCREEN = {
@ -114,6 +118,7 @@ export const SPECIAL_AVATARS: Readonly<AvatarOption[]> = [
wrapperShape: 'squircle', wrapperShape: 'squircle',
background: { background: {
color: 'linear-gradient(62deg, #8EC5FC, #E0C3FC)', color: 'linear-gradient(62deg, #8EC5FC, #E0C3FC)',
borderColor: 'transparent',
}, },
widgets: { widgets: {
face: { face: {
@ -158,6 +163,7 @@ export const SPECIAL_AVATARS: Readonly<AvatarOption[]> = [
wrapperShape: 'squircle', wrapperShape: 'squircle',
background: { background: {
color: '#fd6f5d', color: '#fd6f5d',
borderColor: 'transparent',
}, },
widgets: { widgets: {
face: { face: {
@ -207,3 +213,16 @@ export const NOT_COMPATIBLE_AGENTS = [
] as const ] as const
export const DOWNLOAD_DELAY = 800 export const DOWNLOAD_DELAY = 800
export const SHAPE_STYLE_SET = {
[WrapperShape.Circle]: {
borderRadius: '50%',
},
[WrapperShape.Square]: {
borderRadius: '0',
},
[WrapperShape.Squircle]: {
// TODO: Radius should adapt to the avatar size
borderRadius: '25px',
},
}

View File

@ -75,6 +75,9 @@ export function getRandomAvatarOption(
hairColor, // Handle special cases and prevent color conflicts. hairColor, // Handle special cases and prevent color conflicts.
], ],
}), }),
borderColor: getRandomValue(SETTINGS.borderColor, {
avoid: [useOption.background?.color],
}),
}, },
widgets: { widgets: {