DotMatrixSpectrumRenderer.ets 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { SpectrumRenderer, SpectrumRenderOptions, buildSpectrumPalette, hslToHex, rgbaFromHex } from './SpectrumRenderer'
  2. /**
  3. * 点阵频谱渲染器
  4. * 使用点阵网格表达频谱能量层级
  5. */
  6. export class DotMatrixSpectrumRenderer implements SpectrumRenderer {
  7. render(ctx: CanvasRenderingContext2D, bands: number[], energy: number,
  8. width: number, height: number, brandColor: string, options?: SpectrumRenderOptions): void {
  9. if (bands.length === 0) return
  10. ctx.clearRect(0, 0, width, height)
  11. const palette = buildSpectrumPalette(brandColor)
  12. const complexityScale: number = Math.max(0.45, Math.min(1, options?.complexityScale ?? 1))
  13. const columns: number = Math.max(12, Math.floor(20 * complexityScale))
  14. const rows: number = Math.max(8, Math.floor(14 * complexityScale))
  15. const cellW: number = width / columns
  16. const cellH: number = height / rows
  17. const radius: number = Math.max(1.6, Math.min(cellW, cellH) * 0.28)
  18. for (let c = 0; c < columns; c++) {
  19. const bandIndex: number = Math.floor((c / columns) * bands.length)
  20. const value: number = Math.max(0, Math.min(1, bands[bandIndex]))
  21. const activeRows: number = Math.floor(value * rows)
  22. const hue: number = (palette.primaryHue + (c / columns) * 135) % 360
  23. for (let r = 0; r < rows; r++) {
  24. const lit: boolean = r >= rows - activeRows
  25. const x: number = c * cellW + cellW * 0.5
  26. const y: number = r * cellH + cellH * 0.5
  27. const alpha: number = lit ? (0.30 + value * 0.65) : 0.08
  28. const lightness: number = lit ? (0.45 + 0.28 * (r / rows)) : 0.22
  29. ctx.fillStyle = rgbaFromHex(hslToHex(hue, 0.82, lightness), alpha)
  30. ctx.beginPath()
  31. ctx.arc(x, y, radius, 0, Math.PI * 2)
  32. ctx.fill()
  33. }
  34. }
  35. ctx.fillStyle = rgbaFromHex(hslToHex(palette.accentHue, 0.88, 0.60), 0.10 + energy * 0.18)
  36. ctx.fillRect(0, height * 0.48, width, 2)
  37. }
  38. reset(): void {
  39. // 无状态
  40. }
  41. }