D3: Panning along date x axis - javascript

I'm trying to display dates in the x axis and at the same time zoom it when you scroll.
So, I have this code:
<script type="text/javascript">
var data = [
[{'x':20111001,'y':1},{'x':20111002,'y':6},{'x':20111003,'y':11},{'x':20111004,'y':1},{'x':20111005,'y':2},{'x':20111006,'y':12},{'x':20111007,'y':2},{'x':20111008,'y':3},{'x':20111009,'y':13},{'x':20111010,'y':3}],
[{'x':20111001,'y':2},{'x':20111002,'y':2},{'x':20111003,'y':12},{'x':20111004,'y':2},{'x':20111005,'y':3},{'x':20111006,'y':1},{'x':20111007,'y':2},{'x':20111008,'y':7},{'x':20111009,'y':2},{'x':20111010,'y':7}],
[{'x':20111001,'y':3},{'x':20111002,'y':10},{'x':20111003,'y':13},{'x':20111004,'y':3},{'x':20111005,'y':12},{'x':20111006,'y':14},{'x':20111007,'y':6},{'x':20111008,'y':1},{'x':20111009,'y':7},{'x':20111010,'y':9}],
[{'x':20111001,'y':4},{'x':20111002,'y':4},{'x':20111003,'y':14},{'x':20111004,'y':14},{'x':20111005,'y':10},{'x':20111006,'y':15},{'x':20111007,'y':3},{'x':20111008,'y':0},{'x':20111009,'y':3},{'x':20111010,'y':12}]
];
var colors = [
'steelblue',
'green',
'red',
'purple'
]
var b =[];
var parseDate = d3.time.format("%Y%m%d").parse;
data.forEach(function (d) {
f = d;
f.forEach(function(f){
b.push(parseDate(String(f.x)));
})
})
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([d3.extent(b)])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 16])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.style("text-anchor", "end")
.text("Ventas (Miles €)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.transition()
.attr("clip-path", "url(#clip)")
.attr('stroke', function(d,i){
return colors[i%colors.length];
})
.attr("d", line);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var points = svg.selectAll('.dots')
.data(data)
.enter()
.append("g")
.attr("class", "dots")
.attr("clip-path", "url(#clip)");
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.attr('class','dot')
.attr("r", 2.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
).on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(d.point.x + "K<br/>" + d.point.y)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
points.selectAll('circle').attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
);
}
</script>
I can make it with numbers but can't implement it with dates. I've checked other examples and how they make it but can't find the way to code it in my chart.
I'd like to know how to display dates on x axis.

Is your question how to make the axis dates instead of just numbers? Or is it how to make the axis pannable? If it's the first, use code like this:
var x=d3.time.scale()
.domain([minDate,maxDate])
The minDate and maxDate have to be javascript Date objects.

Related

D3.js: Changing the tick values on x-axis based on the screen width

I am making a responsive D3.js Bar Chart, by setting the height to clientWidth. Though the chart resizes after reloading in a new size, when the size is small the x-axis values overlap. I need to avoid this, how can i do it?
Script:
clientw = document.body.clientWidth;
var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = clientw - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
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");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10)
.tickFormat(d3.format("s"));
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Hola:</strong> <span style='color:red'>" + d.hola+ "°C"+"</span>";
})
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 + ")");
svg.call(tip);
d3.tsv("data.tsv", type, function(error, data) {
x.domain(data.map(function(d) { return d.hermanos; }));
y.domain([0, 45]);
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("Hola");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("width", x)
.attr("fill","grey")
.attr("class", "bar")
.attr("x", function(d) { return x(d.hermanos); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.hola); })
.attr("height", function(d) { return height- y(d.hola); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
});
function type(d) {
d.hola= +d.hola;
return d;
}

use img instead of text label in d3.js line chart

Fiddle Example
I couldn't get ordinal scales to work with zooming and panning to achieve horizontally scroll-able effect so I have settled for scale.linear() to use numeric values for axis ticks. I was wondering if it is possible to superimpose the text label in g.tick with an image element. I have come up with this code after .call(xAxis)
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll(".tick text").each(function(k,i){
console.log(data[k]["img"]);
var r = document.createElement('image')
r.setAttribute('x',0)
r.setAttribute('y',9)
r.setAttribute('xlink:href',data[k]["img"])
r.setAttribute('width',50)
r.setAttribute('height',50)
this.parentNode.insertBefore(r,this);
})
I saw that the elements are prepended in g.tick but the images are nowhere to be seen. Is it because of the x and y values? Also, how can I bind the image links from the JSON data to the image element? I have tried data[k]["img"] but it gave me Cannot read property 'img' of undefined.
var img = "https://www.gravatar.com/avatar/904fd39461599f72d580fadf3a73115b?s=128&d=identicon&r=PG&f=1";
var data = [{"item":1,"diameter":"15.00","img":img},{"item":2,"diameter":"10.00","img":img},
{"item":3,"diameter":"25.00","img":img},{"item":4,"diameter":"7.00","img":img},
{"item":5,"diameter":"35.00","img":img},{"item":6,"diameter":"15.00","img":img},
{"item":7,"diameter":"12.00","img":img},{"item":8,"diameter":"10.00","img":img},
{"item":9,"diameter":"17.00","img":img},{"item":10,"diameter":"13.00","img":img},
{"item":11,"diameter":"5.00","img":img},{"item":12,"diameter":"10.00","img":img},
];
function line_chart(field,el){
margin = {
top: 20,
right: 20,
bottom: 20,
left: 45
},
tickno = 10,
width = 960 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom,
x = d3.scale.linear().domain(d3.extent(data, function (d) {
return d.item;
})).range([0, width]),
ymax = d3.max(data,function(d){
return (parseInt(d[field])+1);
}),
ymin = d3.min(data,function(d){
return d[field];
}),
xmax = d3.max(data,function(d){
return d.name;
}),
y = d3.scale.linear()
.domain([ymin,ymax])
.range([height, 0]);
var line = d3.svg.line()
.x(function (d) {
return x(d.item);
})
.y(function (d) {
return y(d[field]);
});
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([1, 1])
.y(y)
.on("zoom", zoomed);
svg = d3.select(el)
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var make_x_axis = function () {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(tickno);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(tickno);
};
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(tickno);
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll(".tick text").each(function(data){
var r = document.createElement('image')
r.setAttribute('x',0)
r.setAttribute('y',9)
r.setAttribute('xlink:href','https://www.gravatar.com/avatar/904fd39461599f72d580fadf3a73115b?s=32&d=identicon&r=PG&f=1')
r.setAttribute('width',50)
r.setAttribute('height',50)
this.parentNode.insertBefore(r,this);
})
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(tickno);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
svg.append('g').attr('class','dots').selectAll(".dot").data(data).enter().append("circle").attr("r",3.5)
.attr("cx",function(d){return x(d.item);})
.attr("cy",function(d){return y(d[field]);})
function zoomed() {
console.log(d3.event.translate);
console.log(d3.event.scale);
svg.select(".dots")
.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
svg.selectAll(".dots circle").attr("r", function(){
return (3.5 * d3.event.scale);
});
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.select(".x.grid")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.select(".y.grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
svg.select(".line")
.attr("class", "line")
.attr("d", line);
svg.selectAll(".dots circle").attr("r", function(){
return (3.5 * d3.event.scale);
});
}
}
line_chart('diameter','#area')
Your image doesn't display because your width is too small.
Also, it's a bit cleaner if you append the images the d3 way:
.selectAll(".tick").each(function(d,i){
d3.select(this)
.append('image')
.attr('xlink:href', data[i].img)
.attr('x',0)
.attr('width',128)
.attr('height',128);
})
Updated fiddle.

Path not showing d3 (binding issue?)

I've been working on a project using fake data and sketches I've found online to create a line graph. However, I can't display paths with a JSON file containing numerical data. This is not the final data but I'm using the field "Id" as numerical value.
I should be able to see a diagonal line, but nothing shows on the graph.
<body>
<script>
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
a = 3.779528*5,
f = width/height,
ticksX = 1+ (width/a),
ticksY = 1+ (height/a*f)
c = 1 + (width/a*10);
var x = d3.scale.linear()
.domain([194, 2229])
.range([0, width]);
var y = d3.scale.linear()
.domain([194, 2229])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.ticks(ticksX)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.ticks(ticksY)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
//.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("pacientes.json", function(error, data) {
data.forEach(function(d) {
d.Id = +d.Id;
d.Edad = +d.Edad;
console.log(d.Id);
});
x.domain(d3.extent(data, function(d) { return d.Id; }));
y.domain(d3.extent(data, function(d) { return d.Id; }));
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.Id); })
.y(function(d) { return y(d.Edad); });
svg.selectAll('svg-path')
.data(data)
.enter()
.append("path")
.attr("x", function(d) { return x(d.Id); })
.attr("y", function(d) { return x(d.Id); })
.style("stroke-width", 10)
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('stroke', 'blue')
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.text('mV');
}); // closing line
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
);
}
</script>
</body>
</html>
I'm pretty convinced that my error is here
svg.selectAll('svg-path')
.data(data)
.enter()
.append("path")
.attr("x", function(d) { return x(d.Id); })
.attr("y", function(d) { return x(d.Id); })
.style("stroke-width", 10)
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('stroke', 'blue')
.attr("d", line);
The data is being loaded correctly and the SVGs are being created (as you can see from the pictures). Any help will be appreciated.
I did not add the CSS, but it should be a blue line.
Thank you!

Add text on top of bar in d3js chart -- no <text> elements added

I am creating a bar chart with d3.js from data stored in tsv file. I want to insert a text in each bar. How I can do?
I have tried even this solution, but doesn't work.
Here is the code of my function:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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 + ")");
function visualize(file){
d3.tsv(file, function(error, data) {
data.forEach(function(d) {
d.weight = +d.weight;
});
x.domain(data.map(function(d) { return d.concept; }));
y.domain([0, d3.max(data, function(d) { return d.weight; })]);
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("weight");
svg.selectAll(".bar")
.data(data)
.enter().append("rect").style("fill", function (d){return d.color;})
.attr("class", "bar")
.attr("x", function(d) { return x(d.concept); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.weight); })
.attr("height", function(d) { return height - y(d.weight); });
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.concept;
})
.attr("text-anchor", "middle")
.attr("x", x)
.attr("y",y)
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
});
}
All my code with the files tsv are here: full code
AmeliaBR is right as usual, and I am only putting this answer because while I was working on it, I saw myself changing the code so that it really makes use of the Enter, Update, Exit selection paradigm. I have made quite a few changes in that regard. Here is the code, FWIW:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
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 + ")");
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("weight");
var g = svg.append("g");
function update(file){
d3.tsv(file, function(error, data) {
data.forEach(function(d) {
d.weight = +d.weight;
});
x.domain(data.map(function(d) { return d.concept; }));
y.domain([0, d3.max(data, function(d) { return d.weight; })]);
var bar = g.selectAll(".bar")
.data(data);
bar.enter()
.append("rect")
.attr("class","bar");
bar
.style("fill", function (d){return d.color;})
.attr("class", "bar")
.attr("x", function(d) { return x(d.concept); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.weight); })
.attr("height", function(d) { return height - y(d.weight); });
bar.exit().remove();
var text = g.selectAll(".text")
.data(data);
text.enter()
.append("text")
.attr("class","text");
text
.attr("text-anchor", "right")
.attr("x", function(d) { return x(d.concept); })
.attr("y", function(d) { return y(d.weight) + 22;})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white")
.text(function(d) {
return d.concept;
});
text.exit().remove();
});
}
And you call it like by doing update("data16.tsv") and then update("data15.tsv").
When you draw an axis, it creates separate <text> elements for each label inside the axis group inside the SVG. So if you then try to select all the <text> elements in the SVG, you're going to select all your axis labels. If you have more axis labels than data for text elements, your enter() selection will be empty and nothing will happen.
To be sure you're only selecting the correct <text> elements, give your text labels a class to distinguish them from the axis labels. And then use that class to narrow-down your selector:
svg.selectAll("text.bar-label")
.data(data)
.enter()
.append("text")
.attr("class", "bar-label")

how to plot data from JSON object on .svg file using D3.js

Image is appending as a background which is not clear.
Able to plot data on svg element which is created in this code.
But want to plot json data on image/.svg file with the following..
Will appreciate if any references...
$(function(){
makePlot();
// $('#zoomReset').on('click',function(e){
// e.preventDefault();
// //$('#chart').empty();
// console.log("sadf");
// makePlot();
// });
});
var makePlot = function() {
d3.json("scatter-data-2010.json", function(dataset) {
//Width and height
var margin = {top: 80, right: 10, bottom: 60, left: 80},
width = 600 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var centered = undefined;
//Create SVG element
tooltip = d3.select("body").append("div")
.attr("class", "plan_tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("");
var svg = d3.select("#vis")
.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.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
/// Set Scales and Distortions
var xScale = d3.scale.linear()
.domain([d3.min(dataset, function(d) { return d['n_workers_change']; }), d3.max(dataset, function(d) { return d['n_workers_change']; })])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([d3.min(dataset, function(d) { return d['earnings_change']; }), d3.max(dataset, function(d) { return d['earnings_change']; })])
.range([height,0]);
var color_scale = d3.scale.category20();
//Add 2 more colors to category 20 because there are 22 parent industry categories
var color_scale_range = color_scale.range();
color_scale_range.push("#e6550d","#6baed6")
radiusScale = d3.scale.sqrt()
.domain([d3.min(dataset, function(d) { return d['n_workers_y']; }), d3.max(dataset, function(d) { return d['n_workers_y']; }) ])
.range([3, 15]);
svg.append("defs")
.append("pattern")
.attr("id", "background")
.attr("width", width)
.attr("height", height)
.append("image")
.attr("xlink:href", "http://www.e-pint.com/epint.jpg")
.attr("width", width)
.attr("height", height);
var rect = svg.append("rect")
.attr("class", "background")
.attr("pointer-events", "all")
//.attr("fill","none")
.attr("fill","url(#background)")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().x(xScale).y(yScale).on("zoom", redraw));
// Tooltips for Dots
set_tooltip_label = function (d) {
var company_name;
tooltip.html(d.category + "<br><strong>N Workers in 2010 (thousands)</strong>: " + d['n_workers_y'] + "<br><strong>Med. Wkly Earnings in 2010 ($)</strong>: " + d.earnings_y + "<br><strong> Category</strong>: " + d.parent_name );
if (!(event === undefined)) {
tooltip.style("top", (event.pageY - 10) + "px").style("left", (event.pageX + 10) + "px")
}
};
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("clip-path", "url(#clip)")
// Set cx, cy in the redraw function
.attr("r", function(d) {
return radiusScale(d['n_workers_y']);
})
.attr("fill", function(d) {
return color_scale(d.parent_id)
})
.on("mouseover", function () {
return tooltip.style("visibility", "visible")
}).on("mousemove", function (d) {
set_tooltip_label(d);
}).on("mouseout", function () {
tooltip.style("visibility", "hidden");
});
// Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5)
.tickSize(-height)
.tickFormat(d3.format("s"));
// Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(10)
.tickFormat(function(d) { return d + " %"; })
.tickSize(-width);
// Create X axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
// Create Y axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + 0 + ",0)")
.call(yAxis);
// Add Label to X Axis
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "middle")
.attr("x", width - width/2)
.attr("y", height + margin.bottom/2)
.text("Percent Change in Number of Workers in Industry");
// Add label to Y Axis
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "middle")
.attr("y", -margin.left + 5)
.attr("x", 0 - (height/2))
.attr("dy", "1em")
.attr("transform", "rotate(-90)")
.text("Percent Change in Inflation Adjusted Median Weekly Earnings");
// Add title
svg.append("text")
.attr("class", " title")
.attr("text-anchor","middle")
.attr("x", width/2)
.attr("y", -margin.top/2)
.text("Changes in Employment and Salary by Industry, 2003 - 2010");
// Add subtitle
svg.append("text")
.attr("class", "subtitle")
.attr("text-anchor","middle")
.attr("x", width/2)
.attr("y", -margin.top/2 + 15)
.text("Scroll and drag to zoom/pan, hover for details.");
var objects = svg.append("svg")
.attr("class", "objects")
.attr("width", width)
.attr("height", height);
//Create main 0,0 axis lines:
hAxisLine = objects.append("svg:line")
.attr("class", "axisLine hAxisLine");
vAxisLine = objects.append("svg:line")
.attr("class", "axisLine vAxisLine");
// Zoom/pan behavior:
function redraw(duration) {
var duration = typeof duration !== 'undefined' ? duration : 0;
if (d3.event){
//console.log("In the zoom function now");
//console.log(d3.event.scale);
//console.log(d3.event.translate);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
}
hAxisLine.transition().duration(duration)
.attr("x1",0)
.attr("y1",0)
.attr("x2",width)
.attr("y2",0)
.attr("transform", "translate(0," + (yScale(0)) + ")");
vAxisLine.transition().duration(duration)
.attr("x1",xScale(0))
.attr("y1",yScale(height))
.attr("x2",xScale(0))
.attr("y2",yScale(-height));
circles.transition().duration(duration)
.attr("cx", function(d) {
return xScale(d['n_workers_change']);
})
.attr("cy", function(d) {
return yScale(d['earnings_change']);
})
}; // <-------- End of zoom function
redraw(0); // call zoom to place elements
}); // end of json loading section
};
You need to define the background image as a pattern and then fill the rect with that pattern:
svg.append("defs")
.append("pattern")
.attr("id", "background")
.attr("width", width)
.attr("height", height)
.append("image")
.attr("xlink:href", "http://www.e-pint.com/epint.jpg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("fill", "url(#background)");

Categories

Resources