package avatar import ( "encoding/base64" "fmt" "unicode/utf8" ) // 预定义一组好看的颜色 var colors = []string{ "#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7", "#DDA0DD", "#98D8C8", "#F7DC6F", "#BB8FCE", "#85C1E9", "#F8B500", "#00CED1", "#E74C3C", "#3498DB", "#2ECC71", "#9B59B6", "#1ABC9C", "#F39C12", "#E67E22", "#16A085", } // SVG模板 const svgTemplate = ` %s ` // GenerateSVGAvatar 根据用户名生成SVG头像 // username: 用户名 // size: 头像尺寸(像素) func GenerateSVGAvatar(username string, size int) string { initials := getInitials(username) color := stringToColor(username) return fmt.Sprintf(svgTemplate, size, size, color, initials) } // GenerateAvatarDataURI 生成Data URI格式的头像 // 可以直接在HTML img标签或CSS background-image中使用 func GenerateAvatarDataURI(username string, size int) string { svg := GenerateSVGAvatar(username, size) encoded := base64.StdEncoding.EncodeToString([]byte(svg)) return fmt.Sprintf("data:image/svg+xml;base64,%s", encoded) } // getInitials 获取用户名首字母 // 中文取第一个字,英文取首字母(最多2个) func getInitials(username string) string { if username == "" { return "?" } // 检查是否是中文字符 firstRune, _ := utf8.DecodeRuneInString(username) if isChinese(firstRune) { // 中文直接返回第一个字符 return string(firstRune) } // 英文处理:取前两个单词的首字母 // 例如: "John Doe" -> "JD", "john" -> "J" result := []rune{} for i, r := range username { if i == 0 { result = append(result, toUpper(r)) } else if r == ' ' || r == '_' || r == '-' { // 找到下一个字符作为第二个首字母 nextIdx := i + 1 if nextIdx < len(username) { nextRune, _ := utf8.DecodeRuneInString(username[nextIdx:]) if nextRune != utf8.RuneError && nextRune != ' ' { result = append(result, toUpper(nextRune)) break } } } } if len(result) == 0 { return "?" } // 最多返回2个字符 if len(result) > 2 { result = result[:2] } return string(result) } // isChinese 判断是否是中文字符 func isChinese(r rune) bool { return r >= 0x4E00 && r <= 0x9FFF } // toUpper 将字母转换为大写 func toUpper(r rune) rune { if r >= 'a' && r <= 'z' { return r - 32 } return r } // stringToColor 根据字符串生成颜色 // 使用简单的哈希算法确保同一用户名每次生成的颜色一致 func stringToColor(s string) string { if s == "" { return colors[0] } hash := 0 for _, r := range s { hash = (hash*31 + int(r)) % len(colors) } if hash < 0 { hash = -hash } return colors[hash%len(colors)] }