How to put two 1D frequency distribution charts next to each other? - javascript

I want to create two 1D frequency distribution charts (see this example) and put them one next to other (in a single row).
Here is my fiddle.
The problem is that only the first 1D chart appears, while the second one is invisible.
Should I create a separate svg element for each bar or can I add different bars to the same svg?
var bar1 = svg1.selectAll(".bar")
.data(data1)
.enter().append("g")
.attr("class", "bar1")
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });
var bar2 = svg2.selectAll(".bar")
.data(data2)
.enter().append("g")
.attr("class", "bar1")
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });

This line:
.attr("transform", "translate(" + 100+margin.left + "," + margin.top + ")");
is causing you troubles. JavaScript parses this left to right and it treates the whole thing as string concatenation, so it evaluates to:
<g transform="translate(10030,10)">
What you probably meant is:
.attr("transform", "translate(" + (100+margin.left) + "," + margin.top + ")");
That will evaluate (100+margin.left) as a numerical expression before the string concatenation.
Cleaned up example:
var values1 = [48,119,92,53,58,84,56,54,141,176,23,78,55,32,53,71,45,85,41,74,80]
var values2 = [18,19,12,13,18,14,16,14,14,16,23,18,15,12,13,11,15,15,11,14,8]
// A formatter for counts.
var formatCount = d3.format(",.0f");
var margin = {top: 10, right: 30, bottom: 30, left: 30},
width = 300 - margin.left - margin.right,
height = 100 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 150])
.range([0, width]);
// Generate a histogram using sixty uniformly-spaced bins.
var data1 = d3.layout.histogram()
.bins(x.ticks(60))
(values1);
var data2 = d3.layout.histogram()
.bins(x.ticks(60))
(values2);
var opacity = d3.scale.linear()
.domain([0, d3.max(data1, function(d) { return d.y; })])
.range(["white", "blue"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
<!-- The 1st 1D histogram -->
var svg1 = d3.select("body").append("svg").style('float','left')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var bar1 = svg1.selectAll(".bar")
.data(data1)
.enter().append("g")
.attr("class", "bar1")
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });
bar1.append("rect")
.attr("x", 0)
.attr("width", x(data1[0].dx) )
.attr("height", 50)
.style("fill", function(d){ return opacity(d.y)})
svg1.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
<!-- The 2nd 1D histogram -->
var svg2 = d3.select("body").append('div').append("svg").style('float','left')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var bar2 = svg2.selectAll(".bar")
.data(data2)
.enter().append("g")
.attr("class", "bar2")
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });
bar2.append("rect")
.attr("x", 0)
.attr("width", x(data2[0].dx) )
.attr("height", 50)
.style("fill", function(d){ return opacity(d.y)})
svg2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
body {
font: 10px sans-serif;
}
.bar rect {
fill: steelblue;
shape-rendering: crispEdges;
}
.bar text {
fill: #fff;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<body></body>
<script src="https://d3js.org/d3.v3.min.js"></script>

Related

Prevent D3 graph from scaling

I am using this as my base project which is scrollable and scalable in both x and y axis. I have modified it to only be scrollable and scalable in x axis. Now, I want to prevent it from being scalable (i.e the x-scale should not change) while keeping it scrollable (i.e click the graph and dragging it slides it to the left or right)
I have tried doing scale(1) where there's transformation to keep the scale from not changing but that doesn't help. Here's the snippet for that:
g.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
And here's the full code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simpe Single Axis Zoom</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
var ex_chart = example().zoom(true);
var data = [];
for (var i = 0; i < 100; i++) {
data.push([Math.random(), Math.random()]);
}
d3.select('#chart')
.append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
.datum(data).call(ex_chart);
function example() {
var svg;
var margin = {
top: 60,
bottom: 80,
left: 60,
right: 0
};
var width = 500;
var height = 400;
var xaxis = d3.svg.axis();
var yaxis = d3.svg.axis();
var xscale = d3.scale.linear();
var yscale = d3.scale.linear();
var zoomable = true;
var xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
function chart(selection) {
selection.each(function(data) {
svg = d3.select(this).selectAll('svg').data([data]);
svg.enter().append('svg');
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
g.append("svg:rect")
.attr("class", "border")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("stroke", "black")
.style("fill", "none");
g.append("g").attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");
g.append("g").attr("class", "y axis");
g.append("g")
.attr("class", "scatter")
.attr("clip-path", "url(#clip)");
g
.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
// Update the x-axis
xscale.domain(d3.extent(data, function(d) {
return d[0];
}))
.range([0, width - margin.left - margin.right]);
xaxis.scale(xscale)
.orient('bottom')
.tickPadding(10);
svg.select('g.x.axis').call(xaxis);
// Update the y-scale.
yscale.domain(d3.extent(data, function(d) {
return d[1];
}))
.range([height - margin.top - margin.bottom, 0]);
yaxis.scale(yscale)
.orient('left')
.tickPadding(10);
svg.select('g.y.axis').call(yaxis);
draw();
});
return chart;
}
function update() {
var gs = svg.select("g.scatter");
var circle = gs.selectAll("circle")
.data(function(d) {
return d;
});
circle.enter().append("svg:circle")
.attr("class", "points")
.style("fill", "steelblue")
.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
})
.attr("r", 4);
circle.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
});
circle.exit().remove();
}
function zoom_update() {
xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
svg.select('rect.zoom.x.box').call(xzoom);
}
function draw() {
svg.select('g.x.axis').call(xaxis);
//svg.select('g.y.axis').call(yaxis);
update();
zoom_update();
};
// X value to scale
function X(d) {
return xscale(d[0]);
}
// Y value to scale
function Y(d) {
return yscale(d[1]);
}
chart.zoom = function (_){
if (!arguments.length) return zoomable;
zoomable = _;
return chart;
}
return chart;
}
</script>
</body>
</html>
Any sort of help is greatly appreciated. Thanks.
I found out that there was an easy fix for this. In the d3.behaviour.zoom() function, all I needed to add was .scaleExtent([1,1]), which doesn't scale anything more than 1 and hence preventing the zoom.
An example: https://jsfiddle.net/x97k4snj/1/
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simpe Single Axis Zoom</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
var ex_chart = example().zoom(true);
var data = [];
for (var i = 0; i < 100; i++) {
data.push([Math.random(), Math.random()]);
}
d3.select('#chart')
.append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
.datum(data).call(ex_chart);
function example() {
var svg;
var margin = {
top: 60,
bottom: 80,
left: 60,
right: 0
};
var width = 500;
var height = 400;
var xaxis = d3.svg.axis();
var yaxis = d3.svg.axis();
var xscale = d3.scale.linear();
var yscale = d3.scale.linear();
var zoomable = true;
var xzoom = d3.behavior.zoom()
.scaleExtent([1,1])
.x(xscale)
.on("zoom", zoomable ? draw : null);
function chart(selection) {
selection.each(function(data) {
svg = d3.select(this).selectAll('svg').data([data]);
svg.enter().append('svg');
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
g.append("svg:rect")
.attr("class", "border")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("stroke", "black")
.style("fill", "none");
g.append("g").attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");
g.append("g").attr("class", "y axis");
g.append("g")
.attr("class", "scatter")
.attr("clip-path", "url(#clip)");
g
.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
// Update the x-axis
xscale.domain(d3.extent(data, function(d) {
return d[0];
}))
.range([0, width - margin.left - margin.right]);
xaxis.scale(xscale)
.orient('bottom')
.tickPadding(10);
svg.select('g.x.axis').call(xaxis);
// Update the y-scale.
yscale.domain(d3.extent(data, function(d) {
return d[1];
}))
.range([height - margin.top - margin.bottom, 0]);
yaxis.scale(yscale)
.orient('left')
.tickPadding(10);
svg.select('g.y.axis').call(yaxis);
draw();
});
return chart;
}
function update() {
var gs = svg.select("g.scatter");
var circle = gs.selectAll("circle")
.data(function(d) {
return d;
});
circle.enter().append("svg:circle")
.attr("class", "points")
.style("fill", "steelblue")
.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
})
.attr("r", 4);
circle.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
});
circle.exit().remove();
}
function zoom_update() {
xzoom = d3.behavior.zoom()
.scaleExtent([1,1])
.x(xscale)
.on("zoom", zoomable ? draw : null);
svg.select('rect.zoom.x.box').call(xzoom);
}
function draw() {
svg.select('g.x.axis').call(xaxis);
//svg.select('g.y.axis').call(yaxis);
update();
zoom_update();
};
// X value to scale
function X(d) {
return xscale(d[0]);
}
// Y value to scale
function Y(d) {
return yscale(d[1]);
}
chart.zoom = function (_){
if (!arguments.length) return zoomable;
zoomable = _;
return chart;
}
return chart;
}
</script>
</body>
</html>

how do i clear my visualization in order to make space for the updated visualization using svg?

here's my d3.js function to visualize a bar graph:
function barGraph(data1)
{
// console(data1.count);
var i = 0;
data1.forEach(function(d){
while(i>0){
d.avspeed= +d.avspeed;
d.duration = +d.duration;
i--;
}
})
//console.log(data1.avspeed);
// console.log(data1.avspeed);
var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//console.log(data1.avspeed);
console.log("hey1");
var formatPercent = d3.format("");
console.log("hey2");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
console.log("hey");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
console.log("hey3");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Avg Speed:</strong> <span style='color:red'>" + d.avspeed + "</span>";
})
var svg = d3.select("#rightside").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.call(tip);
console.log("heyllo ");
x.domain(data1.map(function(d) { return d.tripid; }));
y.domain([0, d3.max(data1, function(d) { return d.avspeed; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Avg Speed");
svg.selectAll(".bar")
.data(data1)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.tripid); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.avspeed); })
.attr("height", function(d) { return height - y(d.avspeed); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
console.log(d.avspeed);
console.log("hello234");
function type(d) {
d.avspeed = +d.avspeed;
return d;
}
}
It displays a graph based on the selected region on the map dynamically. If i select new region, another graph is being created below the old graph. I want the old graph to clear and new graph to be in place of old graph. How do I achieve that.
I am new to d3.js
Thanks in advance.
You can clear away anything inside of the parent container with .html("") while creating your svg:
var svg = d3.select("#rightside").html("").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
remove also works but I prefer this slightly terser way of doing it.
Before appending the new avg, just call d3.select('svg').remove(); That will remove the first svg on the page (I'm assuming you only have one). If you don't have an svg, it won't fail, so you can always call it.

Aligning the label in d3 line chart

Following is the data file : myStData.csv
xindex,mylabel
40,23
41,13
42,12
43,21
44,40
45,50
Following is my code snippet, and currently, the label is shown at "start" (text-anchor is set to start). It is placed at the start value of my csv file. But, I want the label to be placed at the end value.
I tried replacing the start text anchor to be end, but it didn't work in my case. Any help in this is highly appreciated.
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body { font: 13px Helvetica;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.legend {
font-size: 16px;
text-anchor: start;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 30, right: 40, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
//var x = d3.time.scale().range([0, width]);
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(14);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.xindex); })
.y(function(d) { return y(d.mylabel); });
var chart1 = d3.select("body")
.append("svg")
.attr("width", width + margin.left + (margin.right * 2))
.attr("height", height + margin.top + (margin.bottom * 2))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Get the data
d3.csv("myStData.csv", function(error, data) {
data.forEach(function(d) {
d.xindex = +d.xindex;
d.mylabel = +d.mylabel;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.xindex; }));
y.domain([0, d3.max(data, function(d) { return d.mylabel; })]);
chart1.append("path") // Add the valueline path.
.attr("class", "line")
.attr("d", valueline(data));
chart1.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart1.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[0].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");
// Add the text label for the Y axis
chart1.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Y-Axis Label");
// Add the text label for the x axis
chart1.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + (margin.bottom * 1.5)) + ")")
.style("text-anchor", "middle")
.text("X-Axis Label");
});
Finally, I got the solution. Simple, as it was!
So, to re-iterate, what I wanted to achieve was to move the location of the 'MyLabel' label to the position where the line ends. Here's how it needs to be done:
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[0].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");
This states that the y-axis position of the label needs to be at data[0] element's y value. We simply need to replace, data[0] by data[data.length-1] so that the y- value of the last data element is taken into consideration for positioning the label.
chart1.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(data[data.length-1].mylabel) + ")")
.attr("dy", ".35em")
.attr("class","legend")
.attr("text-anchor", "start")
.style("fill", "red")
.text("MyLabel");

Unable to perform brushing on ordinal data (strings) in d3.js

I want to performing brushing along the x axis in focus+context scatter plot where both x and y axis are ordinal scale with strings. The link is provided here
http://jsfiddle.net/qYh9w/
The brushing which works for numeric data but stopped working in this context. Kindly tell me how to make brushing work on this data.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var x_data = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar"];
var y_data = ["boy","girl","lady","man","woman","boy","boy","girl","woman","girl","boy","lady","girl","boy","girl","woman","lady","boy","lady","boy","man","man","girl","girl","boy","man","boy"];
function getData( )
{
var dataset = [];
var num_of_items = x_data.length;
for (var i = 0; i < num_of_items; i++) {
dataset.push( { date: x_data[i], price: y_data[i] } );
}
return dataset;
}
var data = getData( );
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 x = d3.scale.ordinal(),
x2 = d3.scale.ordinal(),
y = d3.scale.ordinal(),
y2 = d3.scale.ordinal();
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
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 + ")");
x.domain(x_data);
y.domain(y_data);
x.rangeRoundBands([0, width], 0);
y.rangeRoundBands([height, 0], 0);
x2.domain(x.domain());
y2.domain(y.domain());
x2.rangeRoundBands([0, width], 0);
y2.rangeRoundBands([height2, 0], 0);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", 0)
.attr("height", height2 + 7);
// draw dots
focus.selectAll(".dot")
.data(data)
.enter().append("path")
.attr("class", "dot")
.attr("d", d3.svg.symbol().type("triangle-up"))
.attr("transform", function(d) {
console.log( x(d.date) + "," + y(d.price) );
return "translate(" + x(d.date) + "," + y(d.price) + ") " + "rotate(90)"; })
.style("fill", "blue");
context.selectAll(".dot")
.data(data)
.enter().append("path")
.attr("class", "dot")
.attr("d", d3.svg.symbol().type("triangle-up"))
.attr("transform", function(d) { return "translate(" + x2(d.date) + "," + y2(d.price) + ") " + "rotate(90)"; })
.style("fill", "blue");
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".x.axis").call(xAxis);
focus.selectAll(".dot").attr("d", d3.svg.symbol().type("triangle-up")).attr("transform", function(d) { return "translate(" + x(d.date) + "," + y(d.price) + ") " + "rotate(90)"; });
}
</script>
Alternatively, the source can be found here (https://www.dropbox.com/s/52fnzp87vxvfsli/ex11.html).
I figured out that the solution can be done by modifying the brushed function
function brushed() {
var extent = brush.extent();
//if (!x2.invert) {
var d = x2.domain(),
r = x2.range();
extent = extent.map(function(e) { return d[d3.bisect(r, e) - 1]; });
x.domain(brush.empty() ? d : extent);
focus.select(".x.axis").call(xAxis);
focus.selectAll(".dot").attr("d", d3.svg.symbol().type("triangle-up")).attr("transform", function(d) { return "translate(" + x(d.date) + "," + y(d.price) + ") " + "rotate(90)"; });
//}
}
The solution was found from from Jason Davies (https://groups.google.com/forum/#!msg/d3-js/_YTIAmDBVhM/4sitbWd6C2oJ)

The use of a data array in the d3.js scatter file instead of an external data file

I have the javascript of the scatter d3.js library:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.point {
fill: steelblue;
stroke: #000;
}
</style>
<body>
<script src="http://d3js.org/d3.v2.js?2.9.6"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(data) {
// Coerce the strings to numbers.
data.forEach(function(d) {
d.x = +d.x;
d.y = +d.y;
});
// Compute the scales’ domains.
x.domain(d3.extent(data, function(d) { return d.x; })).nice();
y.domain(d3.extent(data, function(d) { return d.y; })).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".point")
.data(data)
.enter().append("path")
.attr("class", "point")
.attr("d", d3.svg.symbol().type("triangle-up"))
.attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });
});
</script>
The file:data.cvs
x,y
5,90
25,30
45,50
65,55
85,25
Instead of reading the data from a cvs file I added an array to the javascript and tried to extract x and y values directly from this array:
var rows = new array(
array(0,0),
array(90,90),
array(59,70),
array(65,77),
array(85,66)
);
How can I use the array rows in order to obtain the same result ??
You can use array of hash:
var data = [{"x":"5","y":"90"},{"x":"25","y":"30"},{"x":"45","y":"50"},
{"x":"65","y":"55"},{"x":"85","y":"25"}];
Or write a function to convert your array of arrays to this array of hash.
var rows = new Array(
Array(0,0),
Array(90,90),
Array(59,70),
Array(65,77),
Array(85,66)
);
for (var i = 0; i < rows.length; i++) {
data.push({x: rows[i][0], y: rows[i][1]});
}
// Coerce the strings to numbers.
data.forEach(function(d) {
d.x = +d.x;
d.y = +d.y;
});
Here's the live code:
http://vida.io/documents/THpmgQDARSWPJqGG5

Categories

Resources