package canvas import ( "image/color" "math" "sort" ) // Gradient 渐变接口 type Gradient interface { At(x, y int) color.Color } // GradientStop 渐变色标 type GradientStop struct { Offset float64 Color color.Color } // LinearGradient 线性渐变 type LinearGradient struct { X0, Y0, X1, Y1 float64 Stops []GradientStop } // NewLinearGradient 创建线性渐变 func NewLinearGradient(x0, y0, x1, y1 float64) *LinearGradient { return &LinearGradient{ X0: x0, Y0: y0, X1: x1, Y1: y1, Stops: []GradientStop{}, } } // AddColorStop 添加色标 func (g *LinearGradient) AddColorStop(offset float64, color color.Color) { g.Stops = append(g.Stops, GradientStop{Offset: offset, Color: color}) sort.Slice(g.Stops, func(i, j int) bool { return g.Stops[i].Offset < g.Stops[j].Offset }) } // At 获取指定位置的颜色 func (g *LinearGradient) At(x, y int) color.Color { if len(g.Stops) == 0 { return color.Transparent } // 计算投影位置 (0-1) dx := g.X1 - g.X0 dy := g.Y1 - g.Y0 lenSq := dx*dx + dy*dy t := 0.0 if lenSq > 0 { t = ((float64(x)-g.X0)*dx + (float64(y)-g.Y0)*dy) / lenSq if t < 0 { t = 0 } else if t > 1 { t = 1 } } // 查找色标区间 var start, end GradientStop for i, stop := range g.Stops { if stop.Offset >= t { if i == 0 { return stop.Color } start = g.Stops[i-1] end = stop break } } if start.Color == nil { return g.Stops[len(g.Stops)-1].Color } // 区间插值 localT := (t - start.Offset) / (end.Offset - start.Offset) return interpolateColor(start.Color, end.Color, localT) } // RadialGradient 径向渐变 type RadialGradient struct { X0, Y0, R0, X1, Y1, R1 float64 Stops []GradientStop } // NewRadialGradient 创建径向渐变 func NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) *RadialGradient { return &RadialGradient{ X0: x0, Y0: y0, R0: r0, X1: x1, Y1: y1, R1: r1, Stops: []GradientStop{}, } } // AddColorStop 添加色标 func (g *RadialGradient) AddColorStop(offset float64, color color.Color) { g.Stops = append(g.Stops, GradientStop{Offset: offset, Color: color}) sort.Slice(g.Stops, func(i, j int) bool { return g.Stops[i].Offset < g.Stops[j].Offset }) } // At 获取指定位置的颜色 func (g *RadialGradient) At(x, y int) color.Color { if len(g.Stops) == 0 { return color.Transparent } // 计算到焦点的距离 dx1, dy1 := float64(x)-g.X1, float64(y)-g.Y1 d1 := math.Sqrt(dx1*dx1 + dy1*dy1) // 计算梯度值 (0-1) t := (d1 - g.R0) / (g.R1 - g.R0) if t < 0 { t = 0 } else if t > 1 { t = 1 } // 查找色标区间 var start, end GradientStop for i, stop := range g.Stops { if stop.Offset >= t { if i == 0 { return stop.Color } start = g.Stops[i-1] end = stop break } } if start.Color == nil { return g.Stops[len(g.Stops)-1].Color } // 区间插值 localT := (t - start.Offset) / (end.Offset - start.Offset) return interpolateColor(start.Color, end.Color, localT) }