fix(setup): setup page display timing is incorrect
This commit is contained in:
parent
cc3424d4d8
commit
f6277bcc83
7 changed files with 362 additions and 90 deletions
|
@ -9,6 +9,8 @@ import { stringToHex } from '@/utils'
|
|||
import { Toaster } from '@/components/ui/Sonner'
|
||||
import UserInfoDomain from '@/domain/UserInfo'
|
||||
import Setup from '@/app/content/views/Setup'
|
||||
import MessageListDomain from '@/domain/MessageList'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
const hostRoomId = stringToHex(document.location.host)
|
||||
|
||||
|
@ -16,15 +18,31 @@ export default function App() {
|
|||
const send = useRemeshSend()
|
||||
const roomDomain = useRemeshDomain(RoomDomain())
|
||||
const userInfoDomain = useRemeshDomain(UserInfoDomain())
|
||||
send(roomDomain.command.JoinRoomCommand(hostRoomId))
|
||||
const isLogin = useRemeshQuery(userInfoDomain.query.IsLoginQuery())
|
||||
const messageListDomain = useRemeshDomain(MessageListDomain())
|
||||
const joinRoomFinished = useRemeshQuery(roomDomain.query.IsFinishedQuery())
|
||||
const userInfoFinished = useRemeshQuery(userInfoDomain.query.IsFinishedQuery())
|
||||
|
||||
const userInfo = useRemeshQuery(userInfoDomain.query.UserInfoQuery())
|
||||
|
||||
const notUserInfo = userInfoFinished && !userInfo
|
||||
|
||||
useEffect(() => {
|
||||
if (userInfoFinished) {
|
||||
if (userInfo) {
|
||||
!joinRoomFinished && send(roomDomain.command.JoinRoomCommand(hostRoomId))
|
||||
} else {
|
||||
send(messageListDomain.command.ClearListCommand())
|
||||
}
|
||||
}
|
||||
}, [userInfoFinished, userInfo, joinRoomFinished])
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppContainer>
|
||||
<Header />
|
||||
<Main />
|
||||
<Footer />
|
||||
{!isLogin && <Setup />}
|
||||
{notUserInfo && <Setup />}
|
||||
</AppContainer>
|
||||
<AppButton></AppButton>
|
||||
<Toaster richColors offset="104px" position="top-center"></Toaster>
|
||||
|
|
|
@ -18,7 +18,7 @@ export default defineContentScript({
|
|||
async main(ctx) {
|
||||
const store = Remesh.store({
|
||||
externs: [IndexDBStorageImpl, BrowserSyncStorageImpl, PeerRoomImpl],
|
||||
inspectors: [RemeshLogger()]
|
||||
inspectors: __DEV__ ? [RemeshLogger()] : []
|
||||
})
|
||||
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
|
|
|
@ -76,17 +76,18 @@ const Setup: FC = () => {
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
send(messageListDomain.command.ClearListCommand())
|
||||
const timer = new Timer(
|
||||
async () => {
|
||||
const userInfo = await refreshUserInfo()
|
||||
await createMessage(userInfo)
|
||||
await createMessage(await refreshUserInfo())
|
||||
},
|
||||
{ delay: 2000, immediate: true, limit: mockTextList.length }
|
||||
)
|
||||
|
||||
timer.start()
|
||||
return () => timer.stop()
|
||||
return () => {
|
||||
timer.stop()
|
||||
send(messageListDomain.command.ClearListCommand())
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<div className="absolute inset-0 z-50 flex rounded-xl bg-black/10 shadow-2xl backdrop-blur-sm">
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { Remesh } from 'remesh'
|
||||
import { map, merge, tap } from 'rxjs'
|
||||
import { map, merge, switchMap, tap, defer, of, EMPTY, mergeMap } from 'rxjs'
|
||||
import { type MessageUser } from './MessageList'
|
||||
import { PeerRoomExtern } from '@/domain/externs/PeerRoom'
|
||||
import MessageListDomain from '@/domain/MessageList'
|
||||
import UserInfoDomain from '@/domain/UserInfo'
|
||||
import { callbackToObservable, desert } from '@/utils'
|
||||
import { nanoid } from 'nanoid'
|
||||
import StatusModule from './modules/Status'
|
||||
|
||||
export enum MessageType {
|
||||
Like = 'like',
|
||||
|
@ -40,6 +41,10 @@ const RoomDomain = Remesh.domain({
|
|||
|
||||
const MessageListQuery = messageListDomain.query.ListQuery
|
||||
|
||||
const RoomStatusState = StatusModule(domain, {
|
||||
name: 'Room.RoomStatusModule'
|
||||
})
|
||||
|
||||
const PeerListState = domain.state<string[]>({
|
||||
name: 'Room.PeerListState',
|
||||
default: [peerRoom.selfId]
|
||||
|
@ -56,15 +61,15 @@ const RoomDomain = Remesh.domain({
|
|||
name: 'RoomJoinRoomCommand',
|
||||
impl: (_, roomId: string) => {
|
||||
peerRoom.joinRoom(roomId)
|
||||
return [JoinRoomEvent(peerRoom.selfId)]
|
||||
return [JoinRoomEvent(roomId), RoomStatusState.command.SetFinishedCommand()]
|
||||
}
|
||||
})
|
||||
|
||||
const LeaveRoomCommand = domain.command({
|
||||
name: 'RoomLeaveRoomCommand',
|
||||
impl: (_) => {
|
||||
impl: (_, roomId: string) => {
|
||||
peerRoom.leaveRoom()
|
||||
return [LeaveRoomEvent(peerRoom.selfId)]
|
||||
return [LeaveRoomEvent(roomId), RoomStatusState.command.SetInitialCommand()]
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -156,6 +161,18 @@ const RoomDomain = Remesh.domain({
|
|||
name: 'RoomLeaveRoomEvent'
|
||||
})
|
||||
|
||||
const OnMessageEvent = domain.event<RoomMessage>({
|
||||
name: 'RoomOnMessageEvent'
|
||||
})
|
||||
|
||||
const OnJoinRoomEvent = domain.event<string>({
|
||||
name: 'RoomOnJoinRoomEvent'
|
||||
})
|
||||
|
||||
const OnLeaveRoomEvent = domain.event<string>({
|
||||
name: 'RoomOnLeaveRoomEvent'
|
||||
})
|
||||
|
||||
const UpdatePeerListCommand = domain.command({
|
||||
name: 'RoomUpdatePeerListCommand',
|
||||
impl: ({ get }, action: { type: 'create' | 'delete'; peerId: string }) => {
|
||||
|
@ -208,45 +225,37 @@ const RoomDomain = Remesh.domain({
|
|||
|
||||
domain.effect({
|
||||
name: 'RoomOnMessageEffect',
|
||||
impl: ({ get }) => {
|
||||
const onMessage$ = callbackToObservable<RoomMessage>(peerRoom.onMessage.bind(peerRoom))
|
||||
return onMessage$.pipe(
|
||||
map((message) => {
|
||||
impl: ({ fromEvent, get }) => {
|
||||
const onMessage$ = fromEvent(JoinRoomEvent).pipe(
|
||||
switchMap(() => callbackToObservable<RoomMessage>(peerRoom.onMessage.bind(peerRoom))),
|
||||
mergeMap((message) => {
|
||||
console.log('onMessage', message)
|
||||
|
||||
const messageEvent$ = of(OnMessageEvent(message))
|
||||
|
||||
const commandEvent$ = (() => {
|
||||
switch (message.type) {
|
||||
case 'text':
|
||||
return messageListDomain.command.CreateItemCommand({
|
||||
return of(
|
||||
messageListDomain.command.CreateItemCommand({
|
||||
...message,
|
||||
date: Date.now(),
|
||||
likeUsers: [],
|
||||
hateUsers: []
|
||||
})
|
||||
case 'like': {
|
||||
if (!get(messageListDomain.query.HasItemQuery(message.id))) {
|
||||
return null
|
||||
}
|
||||
const _message = get(messageListDomain.query.ItemQuery(message.id))
|
||||
return messageListDomain.command.UpdateItemCommand({
|
||||
..._message,
|
||||
likeUsers: desert(
|
||||
_message.likeUsers,
|
||||
{
|
||||
userId: message.userId,
|
||||
username: message.username,
|
||||
userAvatar: message.userAvatar
|
||||
},
|
||||
'userId'
|
||||
)
|
||||
})
|
||||
}
|
||||
case 'like':
|
||||
case 'hate': {
|
||||
if (!get(messageListDomain.query.HasItemQuery(message.id))) {
|
||||
return null
|
||||
return EMPTY
|
||||
}
|
||||
const _message = get(messageListDomain.query.ItemQuery(message.id))
|
||||
return messageListDomain.command.UpdateItemCommand({
|
||||
const users = message.type === 'like' ? 'likeUsers' : 'hateUsers'
|
||||
return of(
|
||||
messageListDomain.command.UpdateItemCommand({
|
||||
..._message,
|
||||
hateUsers: desert(
|
||||
_message.hateUsers,
|
||||
[users]: desert(
|
||||
_message[users],
|
||||
{
|
||||
userId: message.userId,
|
||||
username: message.username,
|
||||
|
@ -255,59 +264,72 @@ const RoomDomain = Remesh.domain({
|
|||
'userId'
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
default:
|
||||
console.warn('unknown message type', message)
|
||||
return null
|
||||
console.warn('未知消息类型', message)
|
||||
return EMPTY
|
||||
}
|
||||
})()
|
||||
return merge(messageEvent$, commandEvent$)
|
||||
})
|
||||
)
|
||||
return onMessage$
|
||||
}
|
||||
})
|
||||
|
||||
domain.effect({
|
||||
name: 'RoomOnJoinRoomEffect',
|
||||
impl: () => {
|
||||
const onJoinRoom$ = callbackToObservable<string>(peerRoom.onJoinRoom.bind(peerRoom))
|
||||
return onJoinRoom$.pipe(
|
||||
impl: ({ fromEvent }) => {
|
||||
const onJoinRoom$ = fromEvent(JoinRoomEvent).pipe(
|
||||
switchMap(() => callbackToObservable<string>(peerRoom.onJoinRoom.bind(peerRoom))),
|
||||
map((peerId) => {
|
||||
console.log('onJoinRoom', peerId)
|
||||
return [UpdatePeerListCommand({ type: 'create', peerId }), JoinRoomEvent(peerId)]
|
||||
return [UpdatePeerListCommand({ type: 'create', peerId }), OnJoinRoomEvent(peerId)]
|
||||
})
|
||||
)
|
||||
return onJoinRoom$
|
||||
}
|
||||
})
|
||||
|
||||
domain.effect({
|
||||
name: 'RoomOnLeaveRoomEffect',
|
||||
impl: () => {
|
||||
const onLeaveRoom$ = callbackToObservable<string>(peerRoom.onLeaveRoom.bind(peerRoom))
|
||||
return onLeaveRoom$.pipe(
|
||||
impl: ({ fromEvent }) => {
|
||||
const onLeaveRoom$ = fromEvent(JoinRoomEvent).pipe(
|
||||
switchMap(() => callbackToObservable<string>(peerRoom.onLeaveRoom.bind(peerRoom))),
|
||||
map((peerId) => {
|
||||
console.log('onLeaveRoom', peerId)
|
||||
return [UpdatePeerListCommand({ type: 'delete', peerId }), LeaveRoomEvent(peerId)]
|
||||
return [UpdatePeerListCommand({ type: 'delete', peerId }), OnLeaveRoomEvent(peerId)]
|
||||
})
|
||||
)
|
||||
return onLeaveRoom$
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
query: {
|
||||
PeerListQuery,
|
||||
MessageListQuery
|
||||
MessageListQuery,
|
||||
...RoomStatusState.query
|
||||
},
|
||||
event: {
|
||||
SendTextMessageEvent,
|
||||
SendLikeMessageEvent,
|
||||
SendHateMessageEvent,
|
||||
JoinRoomEvent,
|
||||
LeaveRoomEvent
|
||||
LeaveRoomEvent,
|
||||
OnMessageEvent,
|
||||
OnJoinRoomEvent,
|
||||
OnLeaveRoomEvent,
|
||||
...RoomStatusState.event
|
||||
},
|
||||
command: {
|
||||
JoinRoomCommand,
|
||||
LeaveRoomCommand,
|
||||
SendTextMessageCommand,
|
||||
SendLikeMessageCommand,
|
||||
SendHateMessageCommand
|
||||
SendHateMessageCommand,
|
||||
...RoomStatusState.command
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Remesh } from 'remesh'
|
||||
import { BrowserSyncStorageExtern } from '@/domain/externs/Storage'
|
||||
import StorageEffect from '@/domain/modules/StorageEffect'
|
||||
import StatusModule from './modules/Status'
|
||||
|
||||
export interface UserInfo {
|
||||
id: string
|
||||
|
@ -26,6 +27,10 @@ const UserInfoDomain = Remesh.domain({
|
|||
default: null
|
||||
})
|
||||
|
||||
const UserInfoStatusModule = StatusModule(domain, {
|
||||
name: 'UserInfo.StatusModule'
|
||||
})
|
||||
|
||||
const UserInfoQuery = domain.query({
|
||||
name: 'UserInfo.UserInfoQuery',
|
||||
impl: ({ get }) => {
|
||||
|
@ -33,17 +38,17 @@ const UserInfoDomain = Remesh.domain({
|
|||
}
|
||||
})
|
||||
|
||||
const IsLoginQuery = domain.query({
|
||||
name: 'UserInfo.IsLoginQuery',
|
||||
impl: ({ get }) => {
|
||||
return !!get(UserInfoState())?.id
|
||||
}
|
||||
})
|
||||
|
||||
const UpdateUserInfoCommand = domain.command({
|
||||
name: 'UserInfo.UpdateUserInfoCommand',
|
||||
impl: (_, userInfo: UserInfo | null) => {
|
||||
return [UserInfoState().new(userInfo), UpdateUserInfoEvent(), SyncToStorageEvent()]
|
||||
return [
|
||||
UserInfoState().new(userInfo),
|
||||
UpdateUserInfoEvent(),
|
||||
SyncToStorageEvent(),
|
||||
userInfo
|
||||
? UserInfoStatusModule.command.SetFinishedCommand()
|
||||
: UserInfoStatusModule.command.SetInitialCommand()
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -74,21 +79,25 @@ const UserInfoDomain = Remesh.domain({
|
|||
|
||||
storageEffect
|
||||
.set(SyncToStorageEvent)
|
||||
.get<UserInfo>((value) => SyncToStateCommand(value))
|
||||
.watch<UserInfo>((value) => SyncToStateCommand(value!))
|
||||
.get<UserInfo>((value) => {
|
||||
return [SyncToStateCommand(value), UserInfoStatusModule.command.SetFinishedCommand()]
|
||||
})
|
||||
.watch<UserInfo>((value) => [SyncToStateCommand(value)])
|
||||
|
||||
return {
|
||||
query: {
|
||||
UserInfoQuery,
|
||||
IsLoginQuery
|
||||
...UserInfoStatusModule.query
|
||||
},
|
||||
command: {
|
||||
UpdateUserInfoCommand
|
||||
UpdateUserInfoCommand,
|
||||
...UserInfoStatusModule.command
|
||||
},
|
||||
event: {
|
||||
SyncToStateEvent,
|
||||
SyncToStorageEvent,
|
||||
UpdateUserInfoEvent
|
||||
UpdateUserInfoEvent,
|
||||
...UserInfoStatusModule.event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
102
src/domain/modules/Status.ts
Normal file
102
src/domain/modules/Status.ts
Normal file
|
@ -0,0 +1,102 @@
|
|||
import { DomainConceptName, RemeshDomainContext } from 'remesh'
|
||||
|
||||
export enum Status {
|
||||
Initial = 0b001, // 1
|
||||
Loading = 0b010, // 2
|
||||
Finished = 0b100 // 4
|
||||
}
|
||||
|
||||
export interface StatusOptions {
|
||||
name: DomainConceptName<'StatusModule'>
|
||||
default?: Status
|
||||
}
|
||||
|
||||
const StatusModule = (domain: RemeshDomainContext, options: StatusOptions) => {
|
||||
const StatusState = domain.state({
|
||||
name: `${options.name}.StatusState`,
|
||||
default: options.default ?? Status.Initial
|
||||
})
|
||||
|
||||
const StatusQuery = domain.query({
|
||||
name: `${options.name}.StatusQuery`,
|
||||
impl: ({ get }) => {
|
||||
return get(StatusState())
|
||||
}
|
||||
})
|
||||
|
||||
const IsInitialQuery = domain.query({
|
||||
name: `${options.name}.IsInitialQuery`,
|
||||
impl: ({ get }) => {
|
||||
const state = get(StatusState())
|
||||
return (state & Status.Initial) !== 0
|
||||
}
|
||||
})
|
||||
|
||||
const IsLoadingQuery = domain.query({
|
||||
name: `${options.name}.IsLoadingQuery`,
|
||||
impl: ({ get }) => {
|
||||
const state = get(StatusState())
|
||||
return (state & Status.Loading) !== 0
|
||||
}
|
||||
})
|
||||
|
||||
const IsFinishedQuery = domain.query({
|
||||
name: `${options.name}.IsFinishedQuery`,
|
||||
impl: ({ get }) => {
|
||||
const state = get(StatusState())
|
||||
return (state & Status.Finished) !== 0
|
||||
}
|
||||
})
|
||||
|
||||
const UpdateStatusEvent = domain.event<Status>({
|
||||
name: `${options.name}.UpdateStatusEvent`
|
||||
})
|
||||
|
||||
const SetInitialCommand = domain.command({
|
||||
name: `${options.name}.SetInitialCommand`,
|
||||
impl: () => {
|
||||
return [StatusState().new(Status.Initial), UpdateStatusEvent(Status.Initial)]
|
||||
}
|
||||
})
|
||||
|
||||
const SetLoadingCommand = domain.command({
|
||||
name: `${options.name}.SetLoadingCommand`,
|
||||
impl: () => {
|
||||
return [StatusState().new(Status.Loading), UpdateStatusEvent(Status.Loading)]
|
||||
}
|
||||
})
|
||||
|
||||
const SetFinishedCommand = domain.command({
|
||||
name: `${options.name}.SetFinishedCommand`,
|
||||
impl: () => {
|
||||
return [StatusState().new(Status.Finished), UpdateStatusEvent(Status.Finished)]
|
||||
}
|
||||
})
|
||||
|
||||
const UpdateStatusCommand = domain.command({
|
||||
name: `${options.name}.UpdateStatusCommand`,
|
||||
impl: (_, status: Status) => {
|
||||
return [StatusState().new(status), UpdateStatusEvent(status)]
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
query: {
|
||||
StatusQuery,
|
||||
IsInitialQuery,
|
||||
IsLoadingQuery,
|
||||
IsFinishedQuery
|
||||
},
|
||||
command: {
|
||||
SetInitialCommand,
|
||||
SetLoadingCommand,
|
||||
SetFinishedCommand,
|
||||
UpdateStatusCommand
|
||||
},
|
||||
event: {
|
||||
UpdateStatusEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default StatusModule
|
|
@ -57,8 +57,83 @@ function createAvatarSvg() {
|
|||
'rgb(165, 42, 42)', // Red
|
||||
'rgb(145, 85, 61)', // Auburn
|
||||
'rgb(128, 128, 128)', // Grey
|
||||
'rgb(185, 55, 55)' // Fire
|
||||
// ... 其他颜色
|
||||
'rgb(185, 55, 55)', // Fire
|
||||
'rgb(255, 192, 203)', // Pastel Pink
|
||||
'rgb(255, 105, 180)', // Bright Pink
|
||||
'rgb(230, 230, 250)', // Lavender
|
||||
'rgb(64, 224, 208)', // Turquoise
|
||||
'rgb(0, 191, 255)', // Bright Blue
|
||||
'rgb(148, 0, 211)', // Deep Purple
|
||||
'rgb(50, 205, 50)', // Lime Green
|
||||
'rgb(255, 165, 0)', // Vivid Orange
|
||||
'rgb(220, 20, 60)', // Crimson Red
|
||||
'rgb(192, 192, 192)', // Silver
|
||||
'rgb(255, 215, 0)', // Gold
|
||||
'rgb(255, 255, 255)', // White
|
||||
'rgb(124, 252, 0)', // Lawn Green
|
||||
'rgb(127, 255, 0)', // Chartreuse
|
||||
'rgb(0, 255, 127)', // Spring Green
|
||||
'rgb(72, 209, 204)', // Medium Turquoise
|
||||
'rgb(0, 255, 255)', // Cyan
|
||||
'rgb(0, 206, 209)', // Dark Turquoise
|
||||
'rgb(32, 178, 170)', // Light Sea Green
|
||||
'rgb(95, 158, 160)', // Cadet Blue
|
||||
'rgb(70, 130, 180)', // Steel Blue
|
||||
'rgb(176, 196, 222)', // Light Steel Blue
|
||||
'rgb(30, 144, 255)', // Dodger Blue
|
||||
'rgb(135, 206, 235)', // Sky Blue
|
||||
'rgb(0, 0, 139)', // Dark Blue
|
||||
'rgb(138, 43, 226)', // Blue Violet
|
||||
'rgb(75, 0, 130)', // Indigo
|
||||
'rgb(139, 0, 139)', // Dark Magenta
|
||||
'rgb(153, 50, 204)', // Dark Orchid
|
||||
'rgb(186, 85, 211)', // Medium Orchid
|
||||
'rgb(218, 112, 214)', // Orchid
|
||||
'rgb(221, 160, 221)', // Plum
|
||||
'rgb(238, 130, 238)', // Violet
|
||||
'rgb(255, 0, 255)', // Magenta
|
||||
'rgb(216, 191, 216)', // Thistle
|
||||
'rgb(255, 20, 147)', // Deep Pink
|
||||
'rgb(255, 69, 0)', // Orange Red
|
||||
'rgb(255, 140, 0)', // Dark Orange
|
||||
'rgb(255, 165, 0)', // Orange
|
||||
'rgb(250, 128, 114)', // Salmon
|
||||
'rgb(233, 150, 122)', // Dark Salmon
|
||||
'rgb(240, 128, 128)', // Light Coral
|
||||
'rgb(205, 92, 92)', // Indian Red
|
||||
'rgb(255, 99, 71)', // Tomato
|
||||
'rgb(255, 160, 122)', // Light Salmon
|
||||
'rgb(220, 20, 60)', // Crimson
|
||||
'rgb(139, 0, 0)', // Dark Red
|
||||
'rgb(178, 34, 34)', // Fire Brick
|
||||
'rgb(250, 235, 215)', // Antique White
|
||||
'rgb(255, 239, 213)', // Papaya Whip
|
||||
'rgb(255, 235, 205)', // Blanched Almond
|
||||
'rgb(255, 222, 173)', // Navajo White
|
||||
'rgb(245, 245, 220)', // Beige
|
||||
'rgb(255, 228, 196)', // Bisque
|
||||
'rgb(255, 218, 185)', // Peach Puff
|
||||
'rgb(244, 164, 96)', // Sandy Brown
|
||||
'rgb(210, 180, 140)', // Tan
|
||||
'rgb(222, 184, 135)', // Burly Wood
|
||||
'rgb(250, 250, 210)', // Light Goldenrod Yellow
|
||||
'rgb(255, 250, 205)', // Lemon Chiffon
|
||||
'rgb(255, 245, 238)', // Sea Shell
|
||||
'rgb(253, 245, 230)', // Old Lace
|
||||
'rgb(255, 228, 225)', // Misty Rose
|
||||
'rgb(255, 240, 245)', // Lavender Blush
|
||||
'rgb(250, 240, 230)', // Linen
|
||||
'rgb(255, 228, 181)', // Moccasin
|
||||
'rgb(255, 250, 250)', // Snow
|
||||
'rgb(240, 255, 255)', // Azure
|
||||
'rgb(240, 255, 240)', // Honeydew
|
||||
'rgb(245, 245, 245)', // White Smoke
|
||||
'rgb(245, 255, 250)', // Mint Cream
|
||||
'rgb(240, 248, 255)', // Alice Blue
|
||||
'rgb(240, 248, 255)', // Ghost White
|
||||
'rgb(248, 248, 255)', // Ghost White
|
||||
'rgb(255, 250, 240)', // Floral White
|
||||
'rgb(253, 245, 230)' // Old Lace
|
||||
],
|
||||
hairColor: 'black',
|
||||
dyeColorOffset: '50%',
|
||||
|
@ -72,8 +147,54 @@ function createAvatarSvg() {
|
|||
'rgb(188, 143, 143)', // Dusty Rose
|
||||
'rgb(135, 206, 235)', // Sky Blue
|
||||
'rgb(245, 255, 250)', // Mint Cream
|
||||
'rgb(245, 222, 179)' // Wheat
|
||||
// ... 其他颜色
|
||||
'rgb(245, 222, 179)', // Wheat
|
||||
'rgb(47, 79, 79)', // Dark Slate Gray
|
||||
'rgb(72, 61, 139)', // Dark Slate Blue
|
||||
'rgb(60, 20, 20)', // Dark Brown
|
||||
'rgb(25, 25, 112)', // Midnight Blue
|
||||
'rgb(139, 0, 0)', // Dark Red
|
||||
'rgb(85, 107, 47)', // Olive Drab
|
||||
'rgb(128, 0, 128)', // Purple
|
||||
'rgb(0, 100, 0)', // Dark Green
|
||||
'rgb(0, 0, 139)', // Dark Blue
|
||||
'rgb(105, 105, 105)', // Dim Gray
|
||||
'rgb(240, 128, 128)', // Light Coral
|
||||
'rgb(255, 160, 122)', // Light Salmon
|
||||
'rgb(255, 218, 185)', // Peach Puff
|
||||
'rgb(255, 228, 196)', // Bisque
|
||||
'rgb(255, 222, 173)', // Navajo White
|
||||
'rgb(255, 250, 205)', // Lemon Chiffon
|
||||
'rgb(250, 250, 210)', // Light Goldenrod Yellow
|
||||
'rgb(255, 239, 213)', // Papaya Whip
|
||||
'rgb(255, 245, 238)', // Sea Shell
|
||||
'rgb(255, 248, 220)', // Cornsilk
|
||||
'rgb(255, 255, 240)', // Ivory
|
||||
'rgb(240, 255, 240)', // Honeydew
|
||||
'rgb(240, 255, 255)', // Azure
|
||||
'rgb(240, 248, 255)', // Alice Blue
|
||||
'rgb(248, 248, 255)', // Ghost White
|
||||
'rgb(255, 250, 250)', // Snow
|
||||
'rgb(255, 240, 245)', // Lavender Blush
|
||||
'rgb(255, 228, 225)', // Misty Rose
|
||||
'rgb(230, 230, 250)', // Lavender
|
||||
'rgb(216, 191, 216)', // Thistle
|
||||
'rgb(221, 160, 221)', // Plum
|
||||
'rgb(238, 130, 238)', // Violet
|
||||
'rgb(218, 112, 214)', // Orchid
|
||||
'rgb(186, 85, 211)', // Medium Orchid
|
||||
'rgb(147, 112, 219)', // Medium Purple
|
||||
'rgb(138, 43, 226)', // Blue Violet
|
||||
'rgb(148, 0, 211)', // Dark Violet
|
||||
'rgb(153, 50, 204)', // Dark Orchid
|
||||
'rgb(139, 69, 19)', // Saddle Brown
|
||||
'rgb(160, 82, 45)', // Sienna
|
||||
'rgb(210, 105, 30)', // Chocolate
|
||||
'rgb(205, 133, 63)', // Peru
|
||||
'rgb(244, 164, 96)', // Sandy Brown
|
||||
'rgb(222, 184, 135)', // Burly Wood
|
||||
'rgb(255, 250, 240)', // Floral White
|
||||
'rgb(253, 245, 230)', // Old Lace
|
||||
'rgb(250, 240, 230)' // Linen
|
||||
],
|
||||
mouthPoints: []
|
||||
}
|
||||
|
@ -250,7 +371,6 @@ function createAvatarSvg() {
|
|||
return createElement(svgTemplate)
|
||||
}
|
||||
|
||||
// 导出函数
|
||||
export default function generateUglyAvatar() {
|
||||
const svgElement = createAvatarSvg()
|
||||
const serializer = new XMLSerializer()
|
||||
|
|
Loading…
Reference in a new issue