D3.js 带序号交叉过滤器比例的画笔控件
D3.js Brush controls with Ordinal Crossfilter Scales
我的目标是像 this wonderful example. I've reviewed the API documentation and Mike's Ordinal Brushing example 那样对我的等值线进行子集化。
不幸的是,我仍然不明白画笔应该如何工作。
这些示例很复杂,对于新手来说有些难以理解(很多车削运算符和图表对象数组等)。
我选择不使用 dc.js,因为缺乏对我稍后必须处理的事情的支持。干得好,支持 Nick Qi Zhu。
有人可以检查一下我的(原生 d3)方法并告诉我我做错了什么吗?
我已经设置了我的条形图,它呈现得很好。基本上是正态分布中的值计数。
// Setup Crossfilter dimensions and groups
var nation = crossfilter(MSPB),
byScr = nation.dimension(function(d){ return d.score; }),
byScrGrp = byScr.group().reduceCount(),
byHosp = nation.dimension(function(d){ return d.FIPS; });
// Histogram X-Axis ordinal scale
var x = d3.scale.ordinal()
.domain(d3.range(0,2,0.1))
.rangeBands([0, width, 0.5, 0.5 ]);
// Histogram Y-Axis linear scale
var y = d3.scale.linear()
.domain([0, d3.max(byScrGrp.all(), function(d){ return d.value; })])
.range([height/2, 0]);
// Histogram SVG containiner
var svg = d3.select("#histogram").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height/2 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Histogram bars
svg.selectAll("rect")
.data(byScrGrp.all())
.enter().append("rect")
.attr("x", function(d,i){ return i * (width / byScrGrp.size() ); })
.attr("width", width / byScrGrp.size() - barPadding )
.attr("y", function(d){ return y(d.value) ; })
.attr("height", function(d){ return ((height/2) -y(d.value)); })
.attr("fill", function(d){ return color(d.key); })
.on("mouseover", function(d){ d3.select(this).attr("fill", "teal"); })
.on("mouseout", function(d) { d3.select(this).attr("fill", function(d){return color(d.key);}) } );
紧接着,我尝试像这样添加画笔控件。最初我只想让拖动选择在条形图上工作。我会担心获取 xAxis 范围值以便稍后过滤等值线。
var brush = d3.svg.brush()
.x(x)
.on("brushstart", brushstart)
.on("brush", brushmove)
.on("brushend", brushend)
var brushg = svg.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height/2)
.attr("width", width);
function brushstart() {
svg.classed("selecting", true);
}
function brushmove() {
var s = brush.extent();
brushg.classed("selected", function(d) { return s[0] <= (d = x(d)) && d <= s[1]; });
}
function brushend() {
svg.classed("selecting", !d3.event.target.empty());
}
我看到了十字线拖动手柄,但没有看到我期望的效果,当然也没有达到预期的效果。
在这个网络服务器上速度很慢,但是 full js file is here and partially working example here。
编辑:我试图创建一个 JSFiddle here.
任何指点将不胜感激。
谢谢
如果不进行实验很难说(是否有机会创建 JSfiddle 或类似工具?)。我怀疑问题是您正在设置画笔中所有矩形的宽度。我相信你只需要设置高度。这可能是导致您的范围变得疯狂的原因。
弄清楚这一点后,您需要根据笔刷范围过滤交叉过滤器维度。
此外,Crossfilter 的 group.reduceCount 函数不带参数,如果可能丢失数据,您需要确保 test/cast 维度访问器中的数据以确保他们总是 return 自然排序的数字或字符串。
我的目标是像 this wonderful example. I've reviewed the API documentation and Mike's Ordinal Brushing example 那样对我的等值线进行子集化。
不幸的是,我仍然不明白画笔应该如何工作。
这些示例很复杂,对于新手来说有些难以理解(很多车削运算符和图表对象数组等)。
我选择不使用 dc.js,因为缺乏对我稍后必须处理的事情的支持。干得好,支持 Nick Qi Zhu。
有人可以检查一下我的(原生 d3)方法并告诉我我做错了什么吗?
我已经设置了我的条形图,它呈现得很好。基本上是正态分布中的值计数。
// Setup Crossfilter dimensions and groups
var nation = crossfilter(MSPB),
byScr = nation.dimension(function(d){ return d.score; }),
byScrGrp = byScr.group().reduceCount(),
byHosp = nation.dimension(function(d){ return d.FIPS; });
// Histogram X-Axis ordinal scale
var x = d3.scale.ordinal()
.domain(d3.range(0,2,0.1))
.rangeBands([0, width, 0.5, 0.5 ]);
// Histogram Y-Axis linear scale
var y = d3.scale.linear()
.domain([0, d3.max(byScrGrp.all(), function(d){ return d.value; })])
.range([height/2, 0]);
// Histogram SVG containiner
var svg = d3.select("#histogram").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height/2 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Histogram bars
svg.selectAll("rect")
.data(byScrGrp.all())
.enter().append("rect")
.attr("x", function(d,i){ return i * (width / byScrGrp.size() ); })
.attr("width", width / byScrGrp.size() - barPadding )
.attr("y", function(d){ return y(d.value) ; })
.attr("height", function(d){ return ((height/2) -y(d.value)); })
.attr("fill", function(d){ return color(d.key); })
.on("mouseover", function(d){ d3.select(this).attr("fill", "teal"); })
.on("mouseout", function(d) { d3.select(this).attr("fill", function(d){return color(d.key);}) } );
紧接着,我尝试像这样添加画笔控件。最初我只想让拖动选择在条形图上工作。我会担心获取 xAxis 范围值以便稍后过滤等值线。
var brush = d3.svg.brush()
.x(x)
.on("brushstart", brushstart)
.on("brush", brushmove)
.on("brushend", brushend)
var brushg = svg.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height/2)
.attr("width", width);
function brushstart() {
svg.classed("selecting", true);
}
function brushmove() {
var s = brush.extent();
brushg.classed("selected", function(d) { return s[0] <= (d = x(d)) && d <= s[1]; });
}
function brushend() {
svg.classed("selecting", !d3.event.target.empty());
}
我看到了十字线拖动手柄,但没有看到我期望的效果,当然也没有达到预期的效果。
在这个网络服务器上速度很慢,但是 full js file is here and partially working example here。
编辑:我试图创建一个 JSFiddle here.
任何指点将不胜感激。
谢谢
如果不进行实验很难说(是否有机会创建 JSfiddle 或类似工具?)。我怀疑问题是您正在设置画笔中所有矩形的宽度。我相信你只需要设置高度。这可能是导致您的范围变得疯狂的原因。
弄清楚这一点后,您需要根据笔刷范围过滤交叉过滤器维度。
此外,Crossfilter 的 group.reduceCount 函数不带参数,如果可能丢失数据,您需要确保 test/cast 维度访问器中的数据以确保他们总是 return 自然排序的数字或字符串。