dc.js v3.0.7绘制rangeChart报错:'focusChart'未定义
Let's break down what's causing this error and how to fix it step by step:
1. Missing Range Chart Initialization
The core issue here is that you haven't properly initialized your volumeChart as a dc.js bar chart. Right now you're calling methods on volumeChart but never defining what it is first—dc.js needs to know this is a bar chart tied to a DOM element before you can link it as a range chart.
Add this line before configuring the volumeChart:
const volumeChart = dc.barChart("#volume-chart", groupname);
Make sure #volume-chart exists in your HTML (a div with that ID), and initialize this before setting it as the range chart on your timeChart. The order matters—dc.js needs the range chart instance to exist before linking it to the focus chart.
2. Broken Month Dimension Calculation
Your current month dimension is broken:
d.month = d3.timeFormat("%m")
This assigns the formatting function itself to d.month, not the formatted month string. You need to invoke the function with the parsed date:
d.month = d3.timeFormat("%m")(d.dd);
Even better—using a string for month can cause sorting issues (e.g., "10" comes before "2"). Instead, use a time-based value for the dimension by flooring to the start of the month:
moveMonths = xf.dimension(function(d) { return d3.timeMonth.floor(d.dd); }); numRecordsByMonth = moveMonths.group().reduceCount();
This keeps the dimension as a Date object, which d3's time scale will handle correctly.
3. Duplicate & Out-of-Order Configuration
- You've set
.elasticY(true)twice on your timeChart—remove one, they're redundant. - Configure the range chart fully first, then assign it to the focus chart. dc.js needs the range chart to be initialized before establishing the link.
Fixed Full Code
Here's the revised code with all fixes applied:
d3.tsv("demo.tsv").then(function(someData) { drawMarkerSelectsome(someData); }); function drawMarkerSelectsome(someData) { const parseDate = d3.timeParse("%m/%d/%Y"); someData.forEach(function(d) { d.dd = parseDate(d.txndatetime); // Fix: Invoke the format function with the parsed date d.month = d3.timeFormat("%m")(d.dd); }); const xf = crossfilter(someData); const all = xf.groupAll(); // Dimension by full date const dateDim = xf.dimension(function(d) { return d.dd; }); // Fix: Use time-based month dimension for reliable sorting const moveMonths = xf.dimension(function (d) { return d3.timeMonth.floor(d.dd); }); const numRecordsByDate = dateDim.group().reduceCount(); const numRecordsByMonth = moveMonths.group().reduceCount(); const minDate = dateDim.bottom(1)[0].dd; const maxDate = dateDim.top(1)[0].dd; // Step 1: Initialize and configure range chart first const volumeChart = dc.barChart("#volume-chart", groupname); volumeChart.width(940) .height(60) .margins({top: 5, right: 50, bottom: 20, left: 40}) .dimension(dateDim) .group(numRecordsByMonth) .centerBar(true) .gap(1) .alwaysUseRounding(true) .colors(['#D62728']) .x(d3.scaleTime().domain([minDate, maxDate])) .round(d3.time.month.round) .xUnits(d3.time.months); // Step 2: Configure focus chart and link the range chart const timeChart = dc.lineChart("#time-chart", groupname) .renderArea(true) .width(940) .height(200) .transitionDuration(3000) .margins({top: 10, right: 50, bottom: 20, left: 40}) .dimension(dateDim) .mouseZoomable(true) .rangeChart(volumeChart) .elasticY(true) .renderHorizontalGridLines(true) .renderVerticalGridLines(true) .brushOn(false) .group(numRecordsByDate) .x(d3.scaleTime().domain([minDate, maxDate])) .round(d3.time.day.round) .xUnits(d3.time.days); // Don't forget to render all charts! dc.renderAll(); }
Final Checks
- Ensure your HTML has both
#time-chartand#volume-chartdiv elements for the charts to attach to. - Using time-based values (not strings) for date dimensions avoids unexpected sorting or scaling bugs.
- Initializing the range chart first eliminates the "'focusChart' of undefined" error by letting dc.js establish the proper link between the two charts.
内容的提问来源于stack exchange,提问作者Shaibal Ahmed

