import type { CanvasShaderType } from '../../renderers/canvas/CanvasShaderNode.js'; import { LinearGradientTemplate, type LinearGradientProps, } from '../templates/LinearGradientTemplate.js'; export interface ComputedLinearGradientValues { x0: number; y0: number; x1: number; y1: number; colors: string[]; } export const LinearGradient: CanvasShaderType< LinearGradientProps, ComputedLinearGradientValues > = { props: LinearGradientTemplate.props, update(node) { const angle = this.props!.angle - (Math.PI / 180) * 90; const nWidth = node.w; const nHeight = node.h; const line = (Math.abs(nWidth * Math.sin(angle)) + Math.abs(nHeight * Math.cos(angle))) * 0.5; this.computed = { x0: line * Math.cos(angle) + nWidth * 0.5, y0: line * Math.sin(angle) + nHeight * 0.5, x1: line * Math.cos(angle + Math.PI) + nWidth * 0.5, y1: line * Math.sin(angle + Math.PI) + nHeight * 0.5, colors: this.props!.colors.map((value) => this.toColorString(value)), }; }, render(ctx, node, renderContext) { renderContext(); const computed = this.computed as ComputedLinearGradientValues; const { tx, ty } = node.globalTransform!; const { w, h } = node.props; const gradient = ctx.createLinearGradient( tx + computed.x0, ty + computed.y0, tx + computed.x1, ty + computed.y1, ); const colors = computed.colors; const stops = this.props!.stops; for (let i = 0; i < colors.length; i++) { gradient.addColorStop(stops[i]!, colors[i]!); } ctx.fillStyle = gradient; ctx.fillRect(tx, ty, w, h); }, };