11import ColorThief from 'colorthief'
22
3+ const DEFAULT_DOMINANT_COLOR = '#28A9E1'
4+ const DOMINANT_COLOR_CACHE_LIMIT = 100
5+ const colorThief = new ColorThief ( )
6+ const dominantColorCache = new Map < string , Promise < string > > ( )
7+
8+ interface DominantColorOptions {
9+ fallback ?: string
10+ quality ?: number
11+ }
12+
313// 将 RGB 转换为十六进制
414function rgbStringToHex ( rgbArray : number [ ] ) : string {
515 if ( rgbArray . length !== 3 || rgbArray . some ( isNaN ) ) throw new Error ( 'Invalid RGB string format' )
@@ -14,11 +24,46 @@ function rgbStringToHex(rgbArray: number[]): string {
1424 return `#${ toHex ( r ) } ${ toHex ( g ) } ${ toHex ( b ) } `
1525}
1626
27+ function getImageCacheKey ( image : HTMLImageElement ) {
28+ return image . currentSrc || image . src || ''
29+ }
30+
31+ function rememberDominantColor ( key : string , colorPromise : Promise < string > ) {
32+ if ( ! key ) return colorPromise
33+
34+ if ( dominantColorCache . size >= DOMINANT_COLOR_CACHE_LIMIT ) {
35+ const firstKey = dominantColorCache . keys ( ) . next ( ) . value
36+ if ( firstKey ) dominantColorCache . delete ( firstKey )
37+ }
38+
39+ dominantColorCache . set ( key , colorPromise )
40+ return colorPromise
41+ }
42+
1743// 提取主要颜色
18- export async function getDominantColor ( image : HTMLImageElement ) : Promise < string > {
19- const colorThief = new ColorThief ( )
20- const dominantColor = colorThief . getColor ( image )
21- return rgbStringToHex ( dominantColor )
44+ export async function getDominantColor (
45+ image : HTMLImageElement | undefined | null ,
46+ options : DominantColorOptions = { } ,
47+ ) : Promise < string > {
48+ const fallback = options . fallback ?? DEFAULT_DOMINANT_COLOR
49+
50+ if ( ! image ) return fallback
51+
52+ const cacheKey = getImageCacheKey ( image )
53+ const cachedColor = cacheKey ? dominantColorCache . get ( cacheKey ) : undefined
54+ if ( cachedColor ) return cachedColor
55+
56+ const colorPromise = Promise . resolve ( )
57+ . then ( ( ) => {
58+ const dominantColor = colorThief . getColor ( image , options . quality ?? 20 )
59+ return rgbStringToHex ( dominantColor )
60+ } )
61+ . catch ( error => {
62+ console . warn ( 'Failed to extract dominant color:' , error )
63+ return fallback
64+ } )
65+
66+ return rememberDominantColor ( cacheKey , colorPromise )
2267}
2368
2469// 预加载图片
0 commit comments