You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Chart.js制作含总访客与新访客信息的非堆叠条形图求助

Hey, great question! You don't need to switch to D3.js for this—Chart.js can absolutely handle your requirement with a few custom tweaks. Let me walk you through how to make this work.

Solution with Chart.js

Your key needs are:

  • Bar height equals total visitors (not the sum of total + new)
  • Tooltip shows both total and new visitor counts
  • Optional: Display new visitor numbers directly on each bar

Core Approach

We’ll use a primary dataset for total visitors (to control bar height), store new visitor data as a custom property on the dataset, then use Chart.js’s built-in callback functions and custom plugins to add the extra info you need.

Step-by-Step Implementation

1. Prepare Your Data

First, split your raw combined data into separate arrays for total and new visitors:

const rawVisitorData = [[20,15], [25,10], [30,15]];
const totalVisitors = rawVisitorData.map(item => item[0]);
const newVisitors = rawVisitorData.map(item => item[1]);
const dateLabels = getDataAttributes(data, 'data-date'); // Your custom date fetching function

2. Configure the Chart

Here’s the full Chart.js configuration that meets all your requirements:

const visitorChart = new Chart(document.getElementById('visitor-chart'), {
  type: 'bar',
  data: {
    labels: dateLabels,
    datasets: [{
      label: 'Total Visitors',
      data: totalVisitors,
      backgroundColor: 'rgba(54, 162, 235, 0.7)',
      borderColor: 'rgba(54, 162, 235, 1)',
      borderWidth: 1,
      // Store new visitor data as a custom property
      newVisitors: newVisitors
    }]
  },
  options: {
    responsive: true,
    scales: {
      y: {
        beginAtZero: true,
        title: {
          display: true,
          text: 'Total Visitors'
        }
      },
      x: {
        title: {
          display: true,
          text: 'Date'
        }
      }
    },
    plugins: {
      // Customize tooltip to show both values
      tooltip: {
        callbacks: {
          title: (context) => context[0].label,
          label: (context) => {
            const total = context.parsed.y;
            const newCount = context.dataset.newVisitors[context.dataIndex];
            return [
              `Total Visitors: ${total}`,
              `New Visitors: ${newCount}`
            ];
          }
        }
      },
      // Customize legend to show both metrics
      legend: {
        labels: {
          generateLabels: () => [
            {
              text: 'Total Visitors',
              fillStyle: 'rgba(54, 162, 235, 0.7)',
              strokeStyle: 'rgba(54, 162, 235, 1)'
            },
            {
              text: 'New Visitors',
              fillStyle: 'rgba(255, 99, 132, 0.7)',
              strokeStyle: 'rgba(255, 99, 132, 1)'
            }
          ]
        }
      }
    },
    // Add a custom plugin to draw new visitor counts on bars
    plugins: [
      {
        afterDraw: (chart) => {
          const ctx = chart.ctx;
          chart.data.datasets.forEach((dataset) => {
            const meta = chart.getDatasetMeta(0);
            meta.data.forEach((bar, index) => {
              const newCount = dataset.newVisitors[index];
              // Draw text in the middle of the bar
              ctx.fillStyle = '#222';
              ctx.font = '12px sans-serif';
              ctx.textAlign = 'center';
              ctx.fillText(`New: ${newCount}`, bar.x, bar.y + 20);
            });
          });
        }
      }
    ]
  }
});

3. Key Features Explained

  • Bar Height Control: The primary dataset uses only total visitor numbers, so bars will always match the total count (no stacking).
  • Custom Tooltip: The tooltip.callbacks.label function pulls both total and new visitor data to display in the tooltip.
  • On-Bar Labels: The custom afterDraw plugin draws the new visitor count directly on each bar—you can adjust the position, font, or color by modifying the fillText parameters.
  • Custom Legend: We generate a legend that includes both metrics, even though we only have one dataset.

Should You Switch to D3.js?

For this specific use case, Chart.js is more than sufficient. It’s faster to set up, requires less code, and handles responsive design and basic interactions out of the box.

D3.js is a better choice if you need highly customized, non-standard visualizations (like complex interactive maps, network graphs, or custom animations) that Chart.js doesn’t support natively. But for your bar chart requirement, sticking with Chart.js will save you time and effort.

内容的提问来源于stack exchange,提问作者Marius Slovikas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 18:12:49