mirror of
https://github.com/Codennnn/vue-color-avatar.git
synced 2024-12-22 12:02:38 +00:00
Merge pull request #20 from elderdog/main
feat: add border color option
This commit is contained in:
commit
06ad45f138
@ -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({
|
||||||
|
@ -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;
|
||||||
|
31
src/components/widgets/Border.vue
Normal file
31
src/components/widgets/Border.vue
Normal 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>
|
@ -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',
|
||||||
},
|
},
|
||||||
|
@ -16,6 +16,7 @@ export default {
|
|||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
wrapperShape: '头像形状',
|
wrapperShape: '头像形状',
|
||||||
|
borderColor: '边框颜色',
|
||||||
backgroundColor: '背景颜色',
|
backgroundColor: '背景颜色',
|
||||||
colors: '颜色',
|
colors: '颜色',
|
||||||
},
|
},
|
||||||
|
@ -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[]
|
||||||
}
|
}
|
||||||
|
@ -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',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -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: {
|
||||||
|
Loading…
Reference in New Issue
Block a user