Files
go-pixelnebula/animation/types.go
2025-04-18 17:24:18 +08:00

182 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package animation
import (
"strings"
"sync"
)
var (
// 字符串构建器对象池
animationBuilderPool = sync.Pool{
New: func() interface{} {
return new(strings.Builder)
},
}
// 动画映射对象池
animationMapPool = sync.Pool{
New: func() interface{} {
return make(map[string]string)
},
}
)
// AnimationType 表示动画类型
type AnimationType string
// 预定义动画类型常量
const (
Rotate AnimationType = "rotate" // 旋转动画
Gradient AnimationType = "gradient" // 渐变动画
Transform AnimationType = "transform" // 变换动画
Fade AnimationType = "fade" // 淡入淡出动画
Path AnimationType = "path" // 路径动画
Color AnimationType = "color" // 颜色变换动画
Bounce AnimationType = "bounce" // 弹跳动画
Wave AnimationType = "wave" // 波浪动画
Blink AnimationType = "blink" // 闪烁动画
)
// Animation 表示一个SVG动画接口
type Animation interface {
// GenerateSVG 生成动画的SVG代码
GenerateSVG() string
// GetTargetID 获取目标元素ID
GetTargetID() string
// GetType 获取动画类型
GetType() AnimationType
}
// BaseAnimation 基础动画结构,包含所有动画共有的属性
type BaseAnimation struct {
Type AnimationType // 动画类型
Duration float64 // 动画持续时间(秒)
RepeatCount int // 重复次数,-1表示无限重复
Delay float64 // 延迟时间(秒)
TargetID string // 目标元素ID
Attributes map[string]string // 动画属性
}
// GetTargetID 获取目标元素ID
func (a *BaseAnimation) GetTargetID() string {
return a.TargetID
}
// GetType 获取动画类型
func (a *BaseAnimation) GetType() AnimationType {
return a.Type
}
// Manager 动画管理器,负责管理所有动画
type Manager struct {
animations []Animation
}
// NewAnimationManager 创建一个新的动画管理器
func NewAnimationManager() *Manager {
return &Manager{
animations: make([]Animation, 0, 10), // 预分配容量
}
}
// AddAnimation 添加一个动画
func (m *Manager) AddAnimation(animation Animation) {
m.animations = append(m.animations, animation)
}
// GetAnimations 获取所有动画
func (m *Manager) GetAnimations() []Animation {
return m.animations
}
// GetAnimationsByType 获取指定类型的动画
func (m *Manager) GetAnimationsByType(animType AnimationType) []Animation {
// 预分配足够容量
result := make([]Animation, 0, len(m.animations)/2)
for _, anim := range m.animations {
if anim.GetType() == animType {
result = append(result, anim)
}
}
return result
}
// GenerateSVGAnimations 生成SVG动画代码
func (m *Manager) GenerateSVGAnimations() string {
if len(m.animations) == 0 {
return ""
}
// 从对象池获取构建器
sb := animationBuilderPool.Get().(*strings.Builder)
sb.Reset()
sb.Grow(1024) // 预分配足够的容量
defer animationBuilderPool.Put(sb)
// 添加SVG命名空间声明
sb.WriteString("<defs>\n")
// 获取定义内容构建器
defsContent := animationBuilderPool.Get().(*strings.Builder)
defsContent.Reset()
defsContent.Grow(512)
defer animationBuilderPool.Put(defsContent)
// 获取动画内容构建器
animationsContent := animationBuilderPool.Get().(*strings.Builder)
animationsContent.Reset()
animationsContent.Grow(512)
defer animationBuilderPool.Put(animationsContent)
// 获取旋转动画映射
rotateAnimations := animationMapPool.Get().(map[string]string)
defer func() {
// 清空映射并归还
for k := range rotateAnimations {
delete(rotateAnimations, k)
}
animationMapPool.Put(rotateAnimations)
}()
// 一次性处理所有动画以减少循环开销
for _, anim := range m.animations {
svgCode := anim.GenerateSVG()
if svgCode == "" {
continue
}
// 根据动画类型决定放置位置
switch anim.GetType() {
case Gradient:
// 渐变定义需要放在defs中
defsContent.WriteString(svgCode)
case Rotate:
// 旋转动画需要包裹目标元素,先存储起来
if start := strings.Index(svgCode, "<animateTransform"); start != -1 {
if end := strings.Index(svgCode[start:], "/>"); end != -1 {
rotateAnimations[anim.GetTargetID()] = svgCode[start : start+end+2]
}
}
default:
// 其他动画元素直接添加到SVG中
animationsContent.WriteString(svgCode)
}
}
// 只有当存在需要放在defs中的内容时才添加defs标签
if defsContent.Len() > 0 {
sb.WriteString(defsContent.String())
sb.WriteString("</defs>\n")
} else {
// 如果没有需要放在defs中的内容则不添加defs标签
sb.Reset()
}
// 添加直接放置的动画元素
sb.WriteString(animationsContent.String())
return sb.String()
}