简体   繁体   English

在d3 v4实现中d3-brush的JS错误

[英]JS error for d3-brush in d3 v4 implementation

This sample worked fine for d3 v3 version. 此示例适用于d3 v3版本。 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. 其实我只是试图做使用D3 V4版本。

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 d3.v4.js:12632未捕获TypeError:group.property不是函数

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. 有没有人有预感是什么新的API来解决点击这个小提琴中的按钮的错误如果一个人可以更新它的小提琴将是很棒的。 Or just atleast let me know of the modified APIs because the samples worked fine for v3. 或者至少让我知道修改后的API,因为样本适用于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. 由于您的小提琴不能正常工作(无法访问CSV),我无法确认我的答案是否适合您。 But it worked locally for me. 但它在我本地工作。

It is made incredibly easy on v4. 它在v4上变得异常简单。 Simply call brush.move(group, selection) to programmatically move the brush selection. 只需调用brush.move(group,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. 但是,参数selection似乎是基于画笔范围的相对坐标,因此如果您的轴是日期/时间,则可能必须将日期转换为坐标编号。

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(): 然后我修改了drawBrush()函数,只使用了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. 不幸的是,这个解决方案将打破drawBrush()函数的两步转换,并将其合并为一个动画。 You have to make other modifications on your own. 您必须自己进行其他修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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