简体   繁体   中英

JS error for d3-brush in d3 v4 implementation

This sample worked fine for d3 v3 version. Its a trimmed version of this sample where on interaction with the buttons the brush gets animated in its new position.

I am actually trying to do this using d3 v4 version.

The trimming is done to identify the area of concern. The trimmed code is

 var margin = { top: 10, right: 10, bottom: 100, left: 40 }, margin2 = { top: 430, right: 10, bottom: 20, left: 40 }, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom, height2 = 500 - margin2.top - margin2.bottom; var parseDate = d3.timeParse("%b %Y"); var x = d3.scaleTime().range([0, width]), x2 = d3.scaleTime().range([0, width]), y = d3.scaleLinear().range([height, 0]), y2 = d3.scaleLinear().range([height2, 0]); var xAxis = d3.axisBottom(x), xAxis2 = d3.axisBottom(x2), yAxis = d3.axisLeft(y); var brush = d3.brushX(x2) .on("brush end", brushed); var area1 = d3.area() .curve(d3.curveMonotoneX) .x(function(d) { return x(d.date); }) .y0(height) .y1(function(d) { return y(d.price); }); var area2 = d3.area() .curve(d3.curveMonotoneX) .x(function(d) { return x2(d.date); }) .y0(height2) .y1(function(d) { return y2(d.price); }); // make some buttons to drive our zoom d3.select("body").append("div") .attr("id","btnDiv") .style('font-size','75%') .style("width","250px") .style("position","absolute") .style("left","5%") .style("top","200px") var btns = d3.select("#btnDiv").selectAll("button").data([2001, 2002, 2003, 2004]) btns = btns.enter().append("button").style("display","inline-block") // fill the buttons with the year from the data assigned to them btns.each(function (d) { this.innerText = d; }) btns.on("click", drawBrush); function drawBrush() { // define our brush extent to be begin and end of the year brush.extent([new Date(this.innerText + '-01-01'), new Date(this.innerText + '-12-31')]) // now draw the brush to match our extent // use transition to slow it down so we can see what is happening // remove transition so just d3.select(".brush") to just draw brush(d3.select(".brush").transition()); // now fire the brushstart, brushmove, and brushend events // remove transition so just d3.select(".brush") to just draw brush.event(d3.select(".brush").transition().delay(1000)) } var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); svg.append("defs").append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", height); var focus = svg.append("g") .attr("class", "focus") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var context = svg.append("g") .attr("class", "context") .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); d3.csv("sp500.csv", type, function(error, data) { if (error) throw error; x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([0, d3.max(data, function(d) { return d.price; })]); x2.domain(x.domain()); y2.domain(y.domain()); context.append("g") .attr("class", "x brush") .call(brush) .selectAll("rect") .attr("y", -6) .attr("height", height2 + 7); }); function brushed() { x.domain(brush.empty() ? x2.domain() : brush.extent()); } function type(d) { d.date = parseDate(d.date); d.price = +d.price; return d; } 
 svg { font: 10px sans-serif; } .area { fill: steelblue; clip-path: url(#clip); } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .brush .extent { stroke: #fff; fill-opacity: .125; shape-rendering: crispEdges; } 
 <!DOCTYPE html> <meta charset="utf-8"> <style> svg { font: 10px sans-serif; } .area { fill: steelblue; clip-path: url(#clip); } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .brush .extent { stroke: #fff; fill-opacity: .125; shape-rendering: crispEdges; } </style> <body> <script src="http://d3js.org/d3.v4.js"></script> </body> 

Please refer the fiddle for correct error. The error is different when attached in the snippet

Any help is highly appreciable.

Update: The error is

d3.v4.js:12632 Uncaught TypeError: group.property is not a function

Does anyone have a hunch whats the new API to resolve the error on clicking the buttons in this fiddle It would be awesome if one can update a fiddle for it. Or just atleast let me know of the modified APIs because the samples worked fine for v3.

I encountered the same error following said example and found your question. Since your fiddle isn't quite working (unable to access the CSV), I can't confirm if my answer would work for you. But it worked locally for me.

It is made incredibly easy on v4. Simply call brush.move(group, selection) to programmatically move the brush selection. However, the parameter selection seems to be relative coordinates based on brush extent, so if your axis is date/time, you may have to convert the date into coordinate numbers.

For example, I passed in an argument for extent while defining the brush.

let width  = 200;
let height = 80;
let x      = d3.scaleTime().range([0, width]);
let brush  = d3.brushX()
    .extent([[0, 0], [width, height]])
    .on("brush end", brushed);

context.append("g")
    .attr("class", "brush")
    .call(brush)
    .call(brush.move, x.range());

Then I modified the drawBrush() function to use only brush.move():

function drawBrush() {
    // Convert your dates to pixels along the brush's width.
    let start = x(new Date(this.innerText + '-01-01'));
    let end   = x(new Date(this.innerText + '-12-31'));

    // Alternatively, let's say the coordinates of your year is from 20% to 40% of your graph.
    // let start = 0.2 * width;
    // let end   = 0.4 * width;

    brush.move(context.select("g.brush").transition().delay(1000).duration(500), [start, end]);
}

Unfortunately, this solution will break the two-step transition of the drawBrush() function, and combine it into one animation. You have to make other modifications on your own.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM