<template>
  <div>
    <div class="ink-wrap">
      <div class="ink-bar">
        <span class="readout" id="ink-readout"
          >Drag a labelled point to reposition it</span
        >
      </div>

      <div id="chart">
        <apexchart
          type="line"
          height="380"
          :options="chartOptions"
          :series="series"
        ></apexchart>
      </div>

      <div class="ink-note">
        The chart sets <code>chart.ink.enabled</code>, so its point annotations
        are <b>draggable</b>: grab a labelled marker and move it.
        <b>Click a note</b> to open its floating editor card: rename it inline,
        pick an accent color, toggle bold, step the text size, grow/shrink or
        reshape the <b>marker</b>, or <b>delete</b> the note (Enter commits,
        Escape closes; the swatches come from
        <code>chart.ink.noteColors</code>). On release of a drag the new
        position is converted back to data coordinates and written to
        <code>annotations.points[].x/y</code>, so the annotation stays glued to
        that data location on later zoom or resize. Use <b>+ Note</b> (the
        palette, from <code>chart.ink.palette</code>) then click the plot to
        drop a new labelled note. The x-axis <b>Window</b> band moves (drag its
        middle) or resizes (drag an edge), and the y-axis <b>Target</b> line
        drags vertically. Fires <code>annotationDragged</code> /
        <code>annotationEdited</code> / <code>annotationStyled</code> /
        <code>annotationCreated</code> / <code>annotationDeleted</code>. With
        the history (Rewind) feature enabled, <b>Ctrl/Cmd+Z</b> undoes any edit
        and Shift+Ctrl/Cmd+Z redoes it. Needs the <code>ink</code> feature. (Set
        <code>draggable:false</code> on a single annotation to pin it.)
      </div>
    </div>
  </div>
</template>

<script>
import VueApexCharts from 'vue-apexcharts'
import ApexCharts from 'apexcharts'

function signal() {
  var out = []
  for (var i = 0; i < 40; i++) {
    var v = 50 + 22 * Math.sin(i / 4.0) + 9 * Math.sin(i / 1.4) + i * 0.4
    out.push([i, Math.round(v)])
  }
  return out
}

export default {
components: {
apexchart: VueApexCharts,
},
data: function () {
return {
series: [
  { name: 'Signal', data: signal() }
],
chartOptions: {
chart: {
  id: 'signal',
  type: 'line',
  height: 380,
  fontFamily: 'Helvetica, Arial, sans-serif',
  animations: { enabled: false },
  ink: { enabled: true, palette: true },
  history: { enabled: true },
  toolbar: { show: false },
  zoom: { enabled: false },
},
stroke: { width: 2, curve: 'smooth' },
colors: ['#0EA5E9'],
title: { text: 'Signal (drag the callouts)', align: 'left' },
xaxis: { type: 'numeric', title: { text: 'Sample' } },
yaxis: { title: { text: 'Value' } },
annotations: {
  points: [
    {
      x: 6, y: 74, id: 'peak',
      marker: { size: 7, fillColor: '#fff', strokeColor: '#0EA5E9', strokeWidth: 3 },
      label: { text: 'Peak', borderColor: '#0EA5E9', style: { color: '#fff', background: '#0EA5E9' } },
    },
    {
      x: 20, y: 52, id: 'dip',
      marker: { size: 7, fillColor: '#fff', strokeColor: '#ef4444', strokeWidth: 3 },
      label: { text: 'Watch', borderColor: '#ef4444', style: { color: '#fff', background: '#ef4444' } },
    },
  ],
  xaxis: [
    {
      x: 10, x2: 16, id: 'window', fillColor: '#7DD3FC', opacity: 0.28,
      label: { text: 'Window', style: { color: '#fff', background: '#0EA5E9' } },
    },
  ],
  yaxis: [
    {
      y: 62, id: 'target', borderColor: '#f59e0b', strokeDashArray: 4,
      label: { text: 'Target', style: { color: '#fff', background: '#f59e0b' } },
    },
  ],
},
},
}
},
mounted: function () {
  // The vue-apexcharts wrapper owns the render, so reach the live instance by
  // its chart.id. Poll until it exists, then wire the same readout the vanilla
  // build does. The ink feature drives the chart instance directly (drag / edit
  // annotations), so no reactive data changes and the chart is not re-rendered.
  var timer = window.setInterval(function () {
    var chart = ApexCharts.getChartByID('signal')
    if (!chart) return
    window.clearInterval(timer)

    var readout = document.getElementById('ink-readout')

    chart.addEventListener('annotationDragged', function (c, o) {
      readout.textContent =
        "Moved '" + o.id + "' to x=" + Number(o.x).toFixed(2) + ', y=' + Number(o.y).toFixed(2)
    })
    chart.addEventListener('annotationStyled', function (c, o) {
      readout.textContent = "Restyled '" + o.id + "'"
    })
    chart.addEventListener('annotationDeleted', function (c, o) {
      readout.textContent = "Deleted '" + o.id + "' (Ctrl/Cmd+Z restores it)"
    })
  }, 50)
},,
}
</script>

<style>
.ink-wrap {
  max-width: 820px;
  margin: 12px auto;
  font-family: Helvetica, Arial, sans-serif;
}
.ink-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  margin: 4px 6px 10px;
}
.ink-bar .readout {
  font-family: monospace;
  font-size: 13px;
  color: #445;
}
.ink-note {
  background: #eef2ff;
  border-left: 3px solid #0ea5e9;
  padding: 11px 15px;
  font-size: 13px;
  color: #234;
  border-radius: 2px;
  line-height: 1.6;
  margin: 12px 6px;
}
.ink-note code {
  background: #dfe3ff;
  padding: 1px 5px;
  border-radius: 3px;
}
</style>
Annotation Authoring (Ink) - Vue Interactivity | ApexCharts.js | ApexCharts.js