skip to Main Content

I am looking for a solution to display some data based on what you hover on inside the chart. Here’s my jsfiddle and a demo of what I want.
gif image

I hope I’ve made everything clear, and thanks in advance!

const chart = document.getElementById('chart');

new Chart(chart, {
  type: 'doughnut',
  data: {
    labels: ['Bitcoin', 'Ethereum', 'Litecoin', 'Tether'],
    datasets: [{
      data: [50, 30, 10, 10],
      backgroundColor: [
        'orange',
        'purple',
        'darkblue',
        'green'
      ],
      borderWidth: 2,
    }]
  },
  options: {
    responsive: false,
    cutout: '72%',
    plugins: {
      legend: {
        display: false,
      },
    },
  }
});
.chart-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}

.chart-balance {
  position: absolute;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<div class="chart-wrap">
  <canvas id="chart" class="kz-relative kz-index-10" width="224" height="224"></canvas>
  <div class="chart-balance">
    <p class="chart-asset-type">Ethereum</p>
    <h5 class="chart-asset-value">$1,000</h5>
  </div>
</div>

2

Answers


  1. The problem with Chart.js is that it creates a canvas and you cannot manipulate these elements with external javascript code. I really don’t know if there are possible configurations to simulate what you want in Chart.js because I know very little about it.
    Anyway, I managed to do it with the Plotly library. With it I do part of the work with a circular chart and, after that, we have SVG elements in the HTML. With this I can manipulate the default tooltip values so that it appears in the center in custom elements.

    The complete code is there, but I recommend seeing the Plotly documentation and if you don’t know about MutationObserver.

    // https://cdn.jsdelivr.net/npm/[email protected]/plotly.min.js
    
    const data = {
        labels: ["Bitcoin", "Ethereum", "Litecoin", "Tether"],
        values: [50, 30, 10, 10],
        name: "",
        hoverinfo: "label+percent+name",
        hole: 0.65,
        type: "pie",
        marker: {
            colors: ["orange", "purple", "darkblue", "green"],
            line: {
                color: "white",
                width: 4
            }
        }
    }
    
    const layout = {
        paper_bgcolor: "transparent",
        height: 550,
        width: 550,
        showlegend: false
    }
    
    const chartElement = document.querySelector("#chart"),
        chartLabelElement = document.querySelector(".chart-label"),
        chartValueElement = document.querySelector(".chart-value")
    
    chartLabelElement.textContent = data.labels[0]
    chartValueElement.textContent = data.values[0]
    
    Plotly.newPlot(chartElement, [data], layout).then(() => {
        observeTooltip()
    })
    
    function observeTooltip() {
        window.MutationObserver = window.MutationObserver ||
        window.WebKitMutationObserver || window.MozMutationObserver
    
        const observer = new MutationObserver(mutations => {
            const tooltipElement = chartElement.querySelector(".hovertext")
    
            if (tooltipElement) {
                tooltipElement.remove()
    
                const textElements = tooltipElement.querySelectorAll("tspan")
    
                const label = textElements[0].textContent.trim(),
                    value = textElements[1].textContent.trim()
    
                chartLabelElement.textContent = label
                chartValueElement.textContent = value
            }
        })
    
        observer.observe(chartElement, {
            childList: true,
            subtree: true
        })
    }
    .modebar-container {
      display: none;
    }
    
    #chart {
      width: fit-content;
      margin: 0 auto;
    }
    
    #chart path.surface:hover {
      cursor: pointer;
      filter: opacity(0.7);
    }
    
    #chart .hovertext {
      display: none;
    }
    
    .chart-block {
      position: relative;
    }
    
    .chart-center {
      position: absolute;
      top: 0;
      width: 0;
      height: 100%;
      width: 100%;
    
      display: flex;
      flex-wrap: nowrap;
      justify-content: center;
      align-items: center;
      
      text-align: center;
      font-family: "Segoe UI", sans-serif;
    }
    
    .chart-label {
      color: #555;
      font-size: 18px;
      font-weight: 700;
    }
    
    .chart-value {
      color: #000;
      font-size: 48px;
      font-weight: 700;
    }
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/plotly.min.js"></script>
    <div class="chart-block">
        <div class="chart-center">
            <div>
                <div class="chart-label"></div>
                <div class="chart-value"></div>
            </div>
        </div>
        <div id="chart"></div>
    </div>
    Login or Signup to reply.
  2. You can use the onHover hook to update your HTML

    const chart = document.getElementById('chart');
    
    new Chart(chart, {
      type: 'doughnut',
      data: {
        labels: ['Bitcoin', 'Ethereum', 'Litecoin', 'Tether'],
        datasets: [{
          data: [50, 30, 10, 10],
          backgroundColor: [
            'orange',
            'purple',
            'darkblue',
            'green'
          ],
          borderWidth: 2,
        }]
      },
      options: {
        responsive: false,
        onHover: (evt, activeEls) => {
          if (activeEls.length === 0)
            return;
    
          const label = document.getElementsByClassName("chart-asset-type")[0];
          const value = document.getElementsByClassName("chart-asset-value")[0];
    
          label.innerHTML = evt.chart.data.labels[activeEls[0].index];
          value.innerHTML = evt.chart.data.datasets[activeEls[0].datasetIndex].data[activeEls[0].index];
        },
        cutout: '72%',
        plugins: {
          legend: {
            display: false,
          },
        },
      }
    });
    .chart-wrap {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .chart-balance {
      position: absolute;
    }
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    
    <div class="chart-wrap">
      <canvas id="chart" class="kz-relative kz-index-10" width="224" height="224"></canvas>
      <div class="chart-balance">
        <p class="chart-asset-type">Ethereum</p>
        <h5 class="chart-asset-value">$1,000</h5>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search