我正在使用应该使用给定数据创建散点图的Web工具。由于我不熟悉可视化(也不是JavaScript专家),所以我决定使用D3。
在学习了教程之后,观察示例并尝试一些东西,我得到了一个与笔刷选择相关的散点图(尚不执行任何操作)。现在,由于目标正在绘制基因,因此它们中的许多在x和y坐标上都非常接近。所以我想实现的东西像这样的,但在X和Y方向上。基本上放大刷过的部分。
到目前为止,我无法创建此行为,这时我的轴确实发生了变化,但是不再显示值并且没有缩放发生。您可以在我的玩具子域中看到它。我不确定哪里出了问题,因此可以提供任何帮助。
玩具域上使用的javascript:
// General variables
var svg, width, height;
var padding = 30;
var dataset = [
[ 5, 20 ],
[ 480, 90 ],
[ 250, 50 ],
[ 100, 33 ],
[ 330, 95 ],
[ 410, 12 ],
[ 475, 44 ],
[ 25, 67 ],
[ 85, 21 ],
[ 220, 88 ]
];
function drawGraph(){
scatterplot_area_size = $("#scatterplot").width();
width = scatterplot_area_size;
height = scatterplot_area_size * 0.75;
console.log(width);
// Retrieve the interval of the x and y data
var maxX = d3.max(dataset, function(d) {
return d[0]; //References first value in each sub-array
});
var minX = d3.min(dataset, function(d) {
return d[0]; //References first value in each sub-array
});
var maxY = d3.max(dataset, function(d) {
return d[1]; //References second value in each sub-array
});
var minY = d3.min(dataset, function(d) {
return d[1]; //References second value in each sub-array
});
// Create a (square) scatterplot area in the div with id scatterplot
// which spans the entire div in width
svg = d3.select("#scatterplot")
.append("svg")
.attr("width", width)
.attr("height", height);
// plot all points
var points = svg.append("g")
.attr("class", "point")
.selectAll("point")
.data(dataset)
.enter()
.append("circle");
console.log(minX + " " + minY);
// Create x and y scales
var x = d3.scale.linear()
.domain([minX, maxX])
.range([padding, (width-padding)]);
var y = d3.scale.linear()
.domain([minY, maxY])
.range([(height-padding), padding]); // Reverse the scale to let high values show at the top and low values at the bottom
// Set the x and y positions as well as the radius (hard coded 5)
points.attr("cx", function(d) {
return x(d[0]);
})
.attr("cy", function(d) {
return y(d[1]);
})
.attr("r", 5);
// Create the x and y axes
var xAxis = d3.svg.axis()
.scale(x)
.ticks(10)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.ticks(10)
.orient("left");
// Add the axes to the scatterplot
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height-padding) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
// Allow for brushing (selection of points)
var brush = d3.svg.brush()
.x(x)
.y(y)
.on("brush", brushmove)
.on("brushend", brushend);
svg.append("g")
.attr("class", "brush")
.call(brush)
.selectAll('rect')
.attr('height', height);
function brushmove() {
var extent = brush.extent();
points.classed("selected", function(d) {
return extent[0][0] <= d[0] && d[0] <= extent[1][0]
&& extent[0][1] <= d[1] && d[1] <= extent[1][1];
});
}
function brushend() {
x.domain(brush.extent());
y.domain(brush.extent());
transition_data();
reset_axis();
points.classed("selected", false);
d3.select(".brush").call(brush.clear());
}
function transition_data() {
console.log("transistion data called");
d3.selectAll("point")
.transition()
.duration(500)
.attr("cx", function(d) { console.log(d[0]); return x(d[0]); })
.attr("cy", function(d) { return y(d[1]); });
}
function reset_axis() {
svg.transition().duration(500)
.select(".x.axis")
.call(xAxis);
svg.transition().duration(500)
.select(".y.axis")
.call(yAxis);
}
}
// Wait until the document is loaded, then draw the graph.
$( document ).ready(function() {
drawGraph();
});
// If the window is resized, redraw graph to make it fit again.
$( window ).resize(function() {
if(typeof svg != 'undefined'){
$("#scatterplot").empty();
}
drawGraph();
});
Run Code Online (Sandbox Code Playgroud)
您的代码中有两个错误:
在您的函数中,brushend()您都使用这brush.extent()两种情况的返回值来设置秤的域。但是请注意,笔刷返回的范围是像的二维数组[[xMin,yMin],[xMax,yMax]]。您必须使用
var extent = brush.extent();
x.domain([extent[0][0],extent[1][0]]); // x.domain([xMin,xMax])
y.domain([extent[0][1],extent[1][1]]); // y.domain([yMin,yMax])
Run Code Online (Sandbox Code Playgroud)
这些调整将使您的轴正确缩放,而点仍然固定。
您正在插入和处理您的数据点,d3.selectAll("point")这些数据点将它们称为类型svg:point。但是,没有这种类型的svg元素。尽管您对的调用d3.selectAll("point")仍然有效,但由于没有要选择的元素,因此始终会产生一个空选择。因此,在设置svg时,您对函数的第一次调用确实有效,因为它将所有绑定到enter选择的数据提供所需的结果。为了正确起见,您应该将其更正为
// plot all points
var points = svg.append("g")
.attr("class", "point")
// .selectAll("point")
.selectAll("circle") // <-- This will work
.data(dataset)
.enter()
.append("circle");
Run Code Online (Sandbox Code Playgroud)
设置比例尺的域后尝试更新点时,错误代码将不起作用,因为在这种情况下,空选择是没有意义的,并且不会对任何元素产生影响。由于在上面引用的语句中,您已经存储了对所选内容的引用,var points因此无需再次选择它们。您可以按如下所示重写您的更新:
function transition_data() {
// d3.selectAll("point") // Instead of this...
points // <-- ...use the reference to your selection
.transition()
.duration(500)
.attr("cx", function(d) { return x(d[0]); })
.attr("cy", function(d) { return y(d[1]); });
}
Run Code Online (Sandbox Code Playgroud)我整理了一个工作的JSFiddle来演示该解决方案。
| 归档时间: |
|
| 查看次数: |
939 次 |
| 最近记录: |