Ctrl K
ComunidadGuías…

src/services/chartAnnotations.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
export interface AnnotationOptions {
  line_?: {
    yMin: number
    yMax: number
    borderColor: string
    borderWidth: number
  }
  label_?: {
    xValue: number
    yValue: number
    backgroundColor: string
    content: string[]
    borderWidth: number
    font: {
      size: number
    }
    color?: string
  }
}

function getCanvasContext(ctx: unknown): CanvasRenderingContext2D | null {
  if (ctx && typeof (ctx as CanvasRenderingContext2D).save === 'function')
    return ctx as CanvasRenderingContext2D

  return null
}

export const inlineAnnotationPlugin = {
  id: 'inlineAnnotationPlugin',
  afterDatasetsDraw: (chart: any, args: any, options: AnnotationOptions) => {
    const ctx = getCanvasContext(chart?.ctx)
    if (!ctx)
      return

    const { chartArea } = chart
    const { left, right } = chartArea

    Object.entries(options).forEach(([key, val]) => {
      if (key.startsWith('line_')) {
        const { yMin, borderColor, borderWidth } = val
        const yScale = chart.scales.y
        const y = yScale.getPixelForValue(yMin)

        ctx.save()
        ctx.beginPath()
        ctx.moveTo(left, y) // Start the line at the left edge of the chart area
        ctx.lineTo(right, y) // End the line at the right edge of the chart area
        ctx.lineTo(chart.width, y)
        ctx.lineWidth = borderWidth
        ctx.strokeStyle = borderColor
        ctx.stroke()
        ctx.restore()
      }

      if (key.startsWith('label_')) {
        const { xValue, yValue, backgroundColor, content, font, color } = val
        const xScale = chart.scales.x
        const yScale = chart.scales.y
        const x = xScale.getPixelForValue(xValue)
        const y = yScale.getPixelForValue(yValue)

        const labelWidth = ctx.measureText(content[0]).width + 10
        const labelHeight = font.size + 6

        ctx.save()
        ctx.fillStyle = backgroundColor
        ctx.fillRect(x - labelWidth / 2, y - labelHeight / 2, labelWidth, labelHeight)
        ctx.restore()

        ctx.save()
        ctx.fillStyle = color ?? '#000'
        ctx.font = `${font.size}px sans-serif`
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        ctx.fillText(content[0], x, y)
        ctx.restore()
      }
    })
  },
}