Skip to content

Gallery / charts / Line chart + crosshair

Line chart + crosshair

Line chart that draws in, with a snapping crosshair tooltip

charts advanced chartlinetooltipcrosshairjs
Live preview

Techniques: pathLength · pointer-events · getBoundingClientRect · svg coordinate mapping

Customizeupdates preview, code & clipboard
#7F77DD
280px
Code snippets/charts/chart-line-draw-tooltip.html
<!--
  ============================================================
  SVGarden — https://www.svgarden.dev
  Author : Simon-Pierre Boucher
  Contact: contact@spboucher.ai
  File   : snippets/charts/chart-line-draw-tooltip.html
  Desc   : Line chart that draws in, with a snapping crosshair tooltip
  ============================================================
-->
<div class="sg-chart-line-draw-tooltip" style="--sg-color:#7F77DD; --sg-size:280px;">
  <svg viewBox="0 0 240 120" role="img" aria-label="Line chart of monthly values rising from 24 to 82">
    <title>Monthly values line chart</title>
    <g class="sg-chart-line-draw-tooltip-grid">
      <line x1="20" y1="30" x2="218" y2="30" />
      <line x1="20" y1="56" x2="218" y2="56" />
      <line x1="20" y1="82" x2="218" y2="82" />
      <line x1="20" y1="104" x2="218" y2="104" />
    </g>
    <polyline class="sg-chart-line-draw-tooltip-line" pathLength="100"
      points="20,82 42,72 64,77 86,61 108,66 130,52 152,45 174,50 196,37 218,30" />
    <g class="sg-chart-line-draw-tooltip-hud">
      <line class="sg-chart-line-draw-tooltip-cross" x1="20" y1="14" x2="20" y2="104" />
      <circle class="sg-chart-line-draw-tooltip-dot" cx="20" cy="82" r="3.5" />
      <text class="sg-chart-line-draw-tooltip-lbl" x="20" y="73">24</text>
    </g>
  </svg>
</div>
<script>
  document.querySelectorAll('.sg-chart-line-draw-tooltip:not([data-sg-init])').forEach(function (root) {
    root.setAttribute('data-sg-init', '');
    var svg = root.querySelector('svg');
    var hud = root.querySelector('.sg-chart-line-draw-tooltip-hud');
    var cross = root.querySelector('.sg-chart-line-draw-tooltip-cross');
    var dot = root.querySelector('.sg-chart-line-draw-tooltip-dot');
    var lbl = root.querySelector('.sg-chart-line-draw-tooltip-lbl');
    var pts = [[20,82,24],[42,72,36],[64,77,30],[86,61,48],[108,66,42],[130,52,58],[152,45,66],[174,50,60],[196,37,74],[218,30,82]];
    svg.addEventListener('pointermove', function (e) {
      var r = svg.getBoundingClientRect();
      var x = (e.clientX - r.left) * 240 / r.width;
      var best = pts[0];
      for (var i = 1; i < pts.length; i++) if (Math.abs(pts[i][0] - x) < Math.abs(best[0] - x)) best = pts[i];
      cross.setAttribute('x1', best[0]); cross.setAttribute('x2', best[0]);
      dot.setAttribute('cx', best[0]); dot.setAttribute('cy', best[1]);
      lbl.setAttribute('x', Math.max(28, Math.min(210, best[0])));
      lbl.setAttribute('y', best[1] - 9);
      lbl.textContent = best[2];
      hud.style.opacity = 1;
    });
    svg.addEventListener('pointerleave', function () { hud.style.opacity = 0; });
  });
</script>
<style>
  .sg-chart-line-draw-tooltip {
    width: var(--sg-size);
  }
  .sg-chart-line-draw-tooltip svg {
    display: block;
    width: 100%;
    font-family: inherit;
    touch-action: none;
  }
  .sg-chart-line-draw-tooltip-grid line {
    stroke: rgba(128, 128, 128, 0.3);
    stroke-width: 1;
    stroke-dasharray: 2 4;
  }
  .sg-chart-line-draw-tooltip-line {
    fill: none;
    stroke: var(--sg-color);
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    animation: sg-chart-line-draw-tooltip-in 1.2s ease-out forwards;
  }
  @keyframes sg-chart-line-draw-tooltip-in {
    to { stroke-dashoffset: 0; }
  }
  .sg-chart-line-draw-tooltip-hud {
    opacity: 0;
    transition: opacity 0.15s ease;
    pointer-events: none;
  }
  .sg-chart-line-draw-tooltip-cross {
    stroke: rgba(128, 128, 128, 0.5);
    stroke-width: 1;
  }
  .sg-chart-line-draw-tooltip-dot {
    fill: var(--sg-color);
  }
  .sg-chart-line-draw-tooltip-lbl {
    font-size: 10px;
    font-weight: 600;
    fill: currentColor;
    text-anchor: middle;
  }
</style>

More charts

\n","slug":"chart-line-draw-tooltip","vars":[{"name":"--sg-color","unit":"","initial":"#7F77DD"},{"name":"--sg-size","unit":"px","initial":"280px"}]}