D3.js adding/removing data pie chart slices - javascript

I have an input control that should on the key up event on the control either add or subtract a slice from a pie chart depending on if you hit the left or right arrow keys. It doesn't really work as expected because it seems that the new pie slice is sometimes being taken out of existing pie slices and the entire chart is not being recalculated. I'm not sure if I'm messing up the enter or the exit selection. Help is appreciated, TIA.
fiddle http://jsfiddle.net/jaqj3usb/
pertinent code
function removeSlices(n){
var i = -1;
while(++i < n){
data.pop();
}
paths.data(pie(data)).exit().remove();
paths.data(pie(data)).attr('d',arc).attr('transform','translate(100,200)')
}
function changeSlices(){
console.log('woot');
var shouldAddSlice = d3.event.target.valueAsNumber > data.length,
numDifference = Math.abs(data.length - d3.event.target.valueAsNumber);
if(shouldAddSlice){
addSlices(numDifference);
}
else{
removeSlices(numDifference);
}
}
sliceSlider.on('keyup',changeSlices);

I am also new to D3js, trying to learn. I used jQuery for handling keyup events. I did some changes, so left arrow adds and right arrow subtracts slices.
passed jquery as in argument to self executing function
(function(d3, $) {
})(window.d3, $);
In addSlices() changed
paths
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
to
paths.data(pie([])).exit().remove();
paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i];
});
above code deletes and redraws the pie.
full code:
(function(d3,$){
var svg = d3.select('body').append('svg').attr({
height: 500,
width: 500,
id: 'mySvg'
});
var data = [10,20,30];
var sliceSlider = d3.select('body').append('input').attr({
type: 'range',
max: 10,
min: 1,
value : data.length
});
var colors=['orange','blue','steelblue','green','red','yellow','purple','pink','indigo'];
var pie = d3.layout.pie();
pie.value(function(d){ return d});
var arc = d3.svg.arc().innerRadius(10).outerRadius(100);
var paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
function addSlices(n){
var i = -1;
function randomBetween(min,max){
return Math.floor(Math.random()*(max-min+1)+min);
}
while(++i <n){
data.push(randomBetween(10,50));
}
paths.data(pie([])).exit().remove();
paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i];
});
}
function removeSlices(n){
var i = -1;
while(++i < n){
data.pop();
}
paths.data(pie(data)).exit().remove();
paths.data(pie(data)).attr('d',arc).attr('transform','translate(100,200)');
}
function changeSlices(){
console.log('woot');
var max=$("input[type='range']").attr("max")-data.length;
var shouldAddSlice = max > data.length;
if(shouldAddSlice){
addSlices(1);
}
}
$(document).keyup(function(e) {
switch(e.which) {
case 37: // left
changeSlices();
break;
case 39: // right
removeSlices(1);
break;
default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
})(window.d3,$);
example : http://jsfiddle.net/jaqj3usb/2/

Here is first variant (I think this is correct), base on this please add comments because you are not computing correctly from the start svg's added to the page.
You can remove individual pie slice like this but this will is not update correct your plate:
svg.selectAll('path')[0][pos].remove();
where pos 0 < data.length (in your original code not correct)
Adding in this way you are overlapping unmoved slices:
paths
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
Anyhow:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Eat my pie</title>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script>
<script type='text/javascript'>
window.onload=function(){
/**
* Created by cecild on 5/21/2015.
* Updated by SilentTremor 5/25/2015.
*/
(function(d3){
svg = d3.select('body').append('svg').attr({
height: 800,
width: 900,
id: 'mySvg'
});
var data = [10];
var sliceSlider = d3.select('body').append('input').attr({
type: 'range',
max: 10,
min: 1,
value : data.length
});
var colors=['orange','blue','steelblue','green','red','yellow','purple','pink','indigo'];
var pie = d3.layout.pie();
pie.value(function(d){ return d});
var arc = d3.svg.arc().innerRadius(10).outerRadius(100);
var paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
function addSlices(n){
var i = -1;
function randomBetween(min,max){
return Math.floor(Math.random()*(max-min+1)+min);
}
while(++i <n){
data.push(randomBetween(10,50));
}
svg.selectAll("path").remove();
paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
}
function removeSlices(n){
var i = -1;
while(++i < n){
data.pop();
}
svg.selectAll("path").remove()
paths = svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
.attr('d',arc)
.attr('transform','translate(100,200)')
.attr('fill',function(d,i){
return colors[i]
});
}
function changeSlices(){
var shouldAddSlice = d3.event.target.valueAsNumber > data.length,
numDifference = Math.abs(data.length - d3.event.target.valueAsNumber);
if(shouldAddSlice){
addSlices(numDifference);
}
else{
removeSlices(numDifference);
}
}
sliceSlider.on('keyup',changeSlices);
})(window.d3);
}
</script>
</head>
<body>
</body>
</html>

In the same way that you use this code:
svg.selectAll('path').append('g')
.data(pie(data))
.enter()
.append('path')
You can use:
svg.selectAll('path').append('g')
.data(pie(data))
.exit()
.remove()
This should remove pie graph elements which no longer have data associated with them.

Related

D3 Animate One Path Series At a Time

Learning Javascript and D3.
Trying to create a graph where it draws each line in a series, one at a time or on a delayed interval.
What I've got so far (relevant code at the end of this post)
https://jsfiddle.net/jimdholland/5n6xrLk0/180/
My data is structures with each series as one row, with 12 columns. When you read it in, the object approximately looks like
mydata = [
{NumDays01: "0", NumDays02: "0", NumDays03: "0", NumDays04: "0", NumDays05: "0",Numdays06: 30}
1: {NumDays01: "0", NumDays02: "0", NumDays03: "0", NumDays04: "0",...
]
I can get it to create line, but it draws all the paths at once. Likewise, I've tried a loop, but that still draws them all at once. Also tried d3.timer and similar results. But I'm having a hard time understanding the timer callback stuff and creating those functions correctly.
I haven't found another example to really study other than a chart from FlowingData which has a lot of bells and whistles out of my league.
https://flowingdata.com/2019/02/01/how-many-kids-we-have-and-when-we-have-them/
Any help or tips would be appreciated.
var svg = d3.select("#chart").select("svg"),
margin = { top: 30, right: 20, bottom: 10, left: 40 },
width = parseInt(d3.select("#chart").style('width'), 10) - margin.left - margin.right;
d3.tsv("https://s3.us-east-2.amazonaws.com/jamesdhollandwebfiles/data/improvementTest.tsv", function(error, data) {
if (error) throw error;
console.log(data);
myData = data;
var t = d3.timer(pathMaker);
}); // #end d3.tsv()
function pathMaker() {
var peeps = myData[rowToRun];
var coords = [];
var lineToRemove = [];
for (var nameIter in dayList) {
coords.push({ x: x(nameIter), y: y(peeps[dayList[nameIter]])})
}
var improvementPath = g.append("path")
.datum(coords)
.attr("id", "path" + peeps.caseid)
.attr("d", lineMaker)
.attr("stroke", "#90c6e4")
.attr("fill", "none")
.attr("stroke-width", 2);
var total_length = improvementPath.node().getTotalLength();
var startPoint = pathStartPoint(improvementPath);
improvementPath = improvementPath
.attr("stroke-dasharray", total_length + " " + total_length)
.attr("stroke-dashoffset", total_length)
.transition() // Call Transition Method
.duration(4000) // Set Duration timing (ms)
.ease(d3.easeLinear) // Set Easing option
.attr("stroke-dashoffset", 0); // Set final value of dash-offset for transition
rowToRun += 1;
if (rowToRun == 5) {rowToRun = 0;}
}
//Get path start point for placing marker
function pathStartPoint(Mypath) {
var d = Mypath.attr("d"),
dsplitted = d.split(/M|L/)[1];
return dsplitted;
}
there are a few problems. I tried to configure your code as little as I could to make it work. If you need further explanations, please let me know
d3.tsv("https://s3.us-east-2.amazonaws.com/jamesdhollandwebfiles/data/improvementTest.tsv", function(error, data) {
if (error) throw error;
console.log(data);
myData = data;
pathMaker()
}); // #end d3.tsv()
function pathMaker() {
var peeps = myData[rowToRun];
var coords_data = [];
var lineToRemove = [];
for (let i = 0; i < myData.length; i++) {
var coords = [];
for (var nameIter in dayList) {
coords.push({ x: x(nameIter), y: y(myData[i][dayList[nameIter]])})
}
coords_data.push(coords)
}
console.log(coords_data)
var improvementPath = g.selectAll("path")
.data(coords_data)
.enter()
.append("path")
.attr("d", lineMaker)
.attr("stroke", "#90c6e4")
.attr("fill", "none")
.attr("stroke-width", 2);
improvementPath = improvementPath.each(function (d,i) {
var total_length = this.getTotalLength();
var startPoint = pathStartPoint(improvementPath);
const path = d3.select(this)
.attr("stroke-dasharray", total_length + " " + total_length)
.attr("stroke-dashoffset", total_length)
.transition() // Call Transition Method
.duration(4000) // Set Duration timing (ms)
.delay(i*4000)
.ease(d3.easeLinear) // Set Easing option
.attr("stroke-dashoffset", 0); // Set final value of dash-offset for transition
})
rowToRun += 1;
if (rowToRun == 5) {rowToRun = 0;}
}

D3.js Problem rendering barchart with object data

I have the following script for rendering a simple barchart in D3.js. I have been able to render charts ok up until a point.
I have this data below which I am struggling to insert into my chart, there is no specific key I can call upon and I'm really confused how I would insert all of these into my chart.
Object { "food-environmental-science": 0, "art-media-research": 0, .....}
I have a seperate file for the HTML (only a snippet):
var barchart1 = barchart("#otherchart");
function clickScatter(d){
var unitOfAssessment = d.UoAString;
click = d.environment.topicWeights
renderTopicWeights(click)
}
function renderTopicWeights(clickedPoint){
barchart1.loadAndRenderDataset(clickedPoint)
}
When I call upon the loadAndRenderDataset function, console gives me a data.map is not a function error.
function barchart(targetDOMelement) {
//=================== PUBLIC FUNCTIONS =========================
//
barchartObject.appendedMouseOverFunction = function (callbackFunction) {
console.log("appendedMouseOverFunction called", callbackFunction)
appendedMouseOverFunction = callbackFunction;
render();
return barchartObject;
}
barchartObject.appendedMouseOutFunction = function (callbackFunction) {
appendedMouseOutFunction = callbackFunction;
render();
return barchartObject;
}
barchartObject.loadAndRenderDataset = function (data) {
dataset=data.map(d=>d); //create local copy of references so that we can sort etc.
render();
return barchartObject;
}
barchartObject.overrideDataFieldFunction = function (dataFieldFunction) {
dataField = dataFieldFunction;
return barchartObject;
}
barchartObject.overrideKeyFunction = function (keyFunction) {
//The key function is used to obtain keys for GUP rendering and
//to provide the categories for the y-axis
//These valuse should be unique
GUPkeyField = yAxisCategoryFunction = keyFunction;
return barchartObject;
}
barchartObject.overrideMouseOverFunction = function (callbackFunction) {
mouseOverFunction = callbackFunction;
render();
return barchartObject;
}
barchartObject.overrideMouseOutFunction = function (callbackFunction) {
mouseOutFunction = callbackFunction;
render(); //Needed to update DOM
return barchartObject;
}
barchartObject.overrideTooltipFunction = function (toolTipFunction) {
tooltip = toolTipFunction;
return barchartObject;
}
barchartObject.overrideMouseClickFunction = function (fn) {
mouseClick2Function = fn;
render(); //Needed to update DOM if they exist
return barchartObject;
}
barchartObject.render = function (callbackFunction) {
render(); //Needed to update DOM
return barchartObject;
}
barchartObject.setTransform = function (t) {
//Set the transform on the svg
svg.attr("transform", t)
return barchartObject;
}
barchartObject.yAxisIndent = function (indent) {
yAxisIndent=indent;
return barchartObject;
}
//=================== PRIVATE VARIABLES ====================================
//Width and height of svg canvas
var svgWidth = 900;
var svgHeight = 450;
var dataset = [];
var xScale = d3.scaleLinear();
var yScale = d3.scaleBand(); //This is an ordinal (categorical) scale
var yAxisIndent = 400; //Space for labels
var maxValueOfDataset; //For manual setting of bar length scaling (only used if .maxValueOfDataset() public method called)
//=================== INITIALISATION CODE ====================================
//Declare and append SVG element
var svg = d3
.select(targetDOMelement)
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.classed("barchart",true);
//Declare and add group for y axis
var yAxis = svg
.append("g")
.classed("yAxis", true);
//Declare and add group for x axis
var xAxis = svg
.append("g")
.classed("xAxis", true);
//===================== ACCESSOR FUNCTIONS =========================================
var dataField = function(d){return d.datafield} //The length of the bars
var tooltip = function(d){return d.key + ": "+ d.datafield} //tooltip text for bars
var yAxisCategoryFunction = function(d){return d.key} //Categories for y-axis
var GUPkeyField = yAxisCategoryFunction; //For 'keyed' GUP rendering (set to y-axis category)
//=================== OTHER PRIVATE FUNCTIONS ====================================
var maxValueOfDataField = function(){
//Find the maximum value of the data field for the x scaling function using a handy d3 max() method
//This will be used to set (normally used )
return d3.max(dataset, dataField)
};
var appendedMouseOutFunction = function(){};
var appendedMouseOverFunction = function(){};
var mouseOverFunction = function (d,i){
d3.select(this).classed("highlight", true).classed("noHighlight", false);
appendedMouseOverFunction(d,i);
}
var mouseOutFunction = function (d,i){
d3.select(this).classed("highlight", false).classed("noHighlight", true);
appendedMouseOutFunction(d,i);
}
var mouseClick2Function = function (d,i){
console.log("barchart click function = nothing at the moment, d=",d)
};
function render () {
updateScalesAndRenderAxes();
GUP_bars();
}
function updateScalesAndRenderAxes(){
//Set scales to reflect any change in svgWidth, svgHeight or the dataset size or max value
xScale
.domain([0, maxValueOfDataField()])
.range([0, svgWidth-(yAxisIndent+10)]);
yScale
.domain(dataset.map(yAxisCategoryFunction)) //Load y-axis categories into yScale
.rangeRound([25, svgHeight-40])
.padding([.1]);
//Now render the y-axis using the new yScale
var yAxisGenerator = d3.axisLeft(yScale);
svg.select(".yAxis")
.transition().duration(1000).delay(1000)
.attr("transform", "translate(" + yAxisIndent + ",0)")
.call(yAxisGenerator);
//Now render the x-axis using the new xScale
var xAxisGenerator = d3.axisTop(xScale);
svg.select(".xAxis")
.transition().duration(1000).delay(1000)
.attr("transform", "translate(" + yAxisIndent + ",20)")
.call(xAxisGenerator);
};
function GUP_bars(){
//GUP = General Update Pattern to render bars
//GUP: BIND DATA to DOM placeholders
var selection = svg
.selectAll(".bars")
.data(dataset, GUPkeyField);
//GUP: ENTER SELECTION
var enterSel = selection //Create DOM rectangles, positioned # x=yAxisIndent
.enter()
.append("rect")
.attr("x", yAxisIndent)
enterSel //Add CSS classes
.attr("class", d=>("key--"+GUPkeyField(d)))
.classed("bars enterSelection", true)
.classed("highlight", d=>d.highlight)
enterSel //Size the bars
.transition()
.duration(1000)
.delay(2000)
.attr("width", function(d) {return xScale(dataField(d));})
.attr("y", function(d, i) {return yScale(yAxisCategoryFunction(d));})
.attr("height", function(){return yScale.bandwidth()});
enterSel //Add tooltip
.append("title")
.text(tooltip)
//GUP UPDATE (anything that is already on the page)
var updateSel = selection //update CSS classes
.classed("noHighlight updateSelection", true)
.classed("highlight enterSelection exitSelection", false)
.classed("highlight", d=>d.highlight)
updateSel //update bars
.transition()
.duration(1000)
.delay(1000)
.attr("width", function(d) {return xScale(dataField(d));})
.attr("y", function(d, i) {return yScale(yAxisCategoryFunction(d));})
.attr("height", function(){return yScale.bandwidth()});
updateSel //update tool tip
.select("title") //Note that we already created a <title></title> in the Enter selection
.text(tooltip)
//GUP: Merged Enter & Update selections (so we don't write these twice)
var mergedSel = enterSel.merge(selection)
.on("mouseover", mouseOverFunction)
.on("mouseout", mouseOutFunction)
.on("click", mouseClick2Function)
//GUP EXIT selection
var exitSel = selection.exit()
.classed("highlight updateSelection enterSelection", false)
.classed("exitSelection", true)
.transition()
.duration(1000)
.attr("width",0)
.remove()
};
return barchartObject;'
}
Any help would be much appreciated, and I appolguise if what I'm asking is not clear. Thanks
format your input data into object like {key:"",value:""} and pass this into d3 so that they can understand and render chart.
var input = {'a':1,"b":2};
function parseData(input){
return Object.keys(input).reduce(function(output, key){
output.push({"key":key,"value":input[key]});
return output;
},[])
}
console.log(parseData(input));
// [{"key":"a","value":1},{"key":"b","value":2}]
jsFiddle demo - https://jsfiddle.net/1kdsoyg2/1/

d3js v5 + Topojson v3 Show/Hide element on click legend

I would like this reverse action http://bl.ocks.org/d3noob/5d621a60e2d1d02086bf. When I click on an item of my legend, I want focus all elements of the map within these class.
However, how isolate just one class compared to others?
For example in this image, just show elements where the value is included between 23500 and 29000 and hide other elements.
I suggest to 1/ filter data and 2/ fill with the same color these elements but surely it's easier.
Here is my code : https://plnkr.co/edit/ga82Syjc8zxTdAxTVNXu?p=preview
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/d3#5.0.0/dist/d3.min.js"></script>
<script src="https://unpkg.com/topojson#3.0.0/dist/topojson.min.js"></script>
</head>
<svg class="carte_evolution">
<style>
</style>
<body>
<script>
let w = 600;
let h = 600;
let view = [0,0,600,600];
//Dimension
let svgCarteEvolution = d3.select(".carte_evolution")
.attr("width", "100%")
.attr("height", h)
.attr("preserveAspectRatio","xMidYMid meet")
.attr("viewBox", `${view[0]},${view[1]},${view[2]},${view[3]}`);
//Map projection
choro = d3.map();
projection = d3.geoConicConformal()
.center([1.282743, 46.328377])
.scale(2600)
.translate([w / 2, h / 2]);
path = d3.geoPath()
.projection(projection);
//Load csv and topojson
promises1 = d3.json("ze_WGS84_UTF8.topojson");
promises2 = d3.csv("data.csv");
Promise.all([promises1, promises2]).then(function(fr){
//Join csv + topojson
let featureCollection = topojson.feature(fr[0],fr[0].objects.ze_WGS84_UTF8)
for (var i=0; i< fr[1].length;i++){
var csvId = fr[1][i].codgeo;
var csvValue0 = parseFloat(fr[1][i].value0);
var csvYear0 = fr[1][i].year0;
for (var j=0; j<featureCollection.features.length;j++){
var jsonId = featureCollection.features[j].properties.codgeo;
if (csvId === jsonId) {
featureCollection.features[j].properties.value0 = csvValue0;
featureCollection.features[j].properties.year0 = csvYear0;
break;
}
}
}
let color = d3.scaleQuantile()
.range(["#d1e0c9","#b3cea8","#8fb983","#539f53","#008d36"]);
color.domain([
12000,17500,19500,21500,23500,29000
]);
//Map
svgCarteEvolution.append("g")
.selectAll("path")
.data(featureCollection.features)
.enter()
.append("path")
.attr("class", "dep")
.attr("d", path)
.style("fill", function(d){
var value = d.properties["value0"];
return value? color(value):"#ccc";
});
//legend
let legend = svgCarteEvolution.selectAll("g.legend_entree")
.data(color.range().reverse())
.enter()
.append("g")
.attr("class","legend_entree");
legend
.append('rect')
.attr("x", 30)
.attr("y", function(d, i) {
return 65 + i * 20;
})
.attr("width", 20)
.attr("height", 10)
.style("stroke", "black")
.style("stroke-width", 0.1)
.style("fill", function(d){return d;});
//the data objects are the fill colors
legend
.append('text')
.attr("x", 55) //leave 5 pixel space after the <rect>
.attr("y", function(d, i) {
return 65 + i * 20;
})
.attr("dy", "0.8em") //place text one line *below* the x,y point
.style("font-family","latomedium")
.style("font-size","0.9em")
.text(function(d,i) {
var extent = color.invertExtent(d);
//extent will be a two-element array, format it however you want:
var format = d3.format("");
return `${format(+extent[0])} - ${format(+extent[1])}`
});
});
</script>
</body>
</html>
data.csv
"codgeo","year0","value0","year1","value1"
"0050",2012,19162,2014,19698.8
"0051",2012,18501.125,2014,19125.5
"0052",2012,18684.6666666667,2014,19454
"0053",2012,19826,2014,20573.9
"0054",2012,18881.1111111111,2014,19513
"0055",2012,17942.5,2014,18657.3
"0056",2012,19299.0476190476,2014,19703.9
"0057",2012,18873.8095238095,2014,19539.3
"0059",2012,18199,2014,18719
"0060",2012,18921,2014,19563.2
"0061",2012,21259.5238095238,2014,21748.3
"0101",2012,,2014,
"0102",2012,,2014,
"0103",2012,,2014,
"0106",2012,,2014,
"0201",2012,,2014,17250
"0202",2012,,2014,17246.7
"0203",2012,,2014,14972
"0204",2012,,2014,14612.6
"0205",2012,,2014,15617.3
"0206",2012,,2014,13369
"0301",2012,,2014,
"0302",2012,,2014,
"0303",2012,,2014,
"0401",2012,,2014,12522.3
"0402",2012,,2014,15483.8
"0403",2012,,2014,14344.6
"0404",2012,,2014,13134
"0601",2012,,2014,
"1101",2012,23144.7619047619,2014,23464
"1102",2012,22223.5,2014,22729.1
"1103",2012,20637.2222222222,2014,21088
"1104",2012,20402,2014,20901
"1105",2012,21782.7777777778,2014,22274.4
"1106",2012,18304.375,2014,18918
"1107",2012,20038.6666666667,2014,20406.5
"1108",2012,19493,2014,19936.5
"1109",2012,28156.8901098901,2014,28660
"1110",2012,20294.8,2014,20639.5
"1111",2012,22490.6666666667,2014,22812.4
"1112",2012,25996.6666666667,2014,26503.5
"1113",2012,25301.7391304348,2014,25639.6
"1114",2012,21184,2014,21611.9
"1115",2012,20586,2014,20954
"1116",2012,25449.5,2014,25742.4
"1117",2012,22279.3333333333,2014,22665
"1118",2012,19040,2014,19307.2
"1119",2012,22059.0909090909,2014,22519
"2101",2012,17416,2014,18133.9
"2102",2012,18721,2014,19275.4
"2103",2012,19554.7826086957,2014,20204
"2104",2012,20352.8571428571,2014,20892.8
"2105",2012,19630.5555555556,2014,20157.6
"2106",2012,18689,2014,19445.2
"2107",2012,17676.6666666667,2014,18309.1
"2201",2012,19209.5238095238,2014,19791
"2202",2012,17090,2014,17820
"2203",2012,16258.6666666667,2014,17014
"2204",2012,17987.619047619,2014,18675.2
"2205",2012,17320.8333333333,2014,18056
"2206",2012,18163.2,2014,18851
"2207",2012,19732.1428571429,2014,20284.7
"2208",2012,19973.3333333333,2014,20690
"2209",2012,17625,2014,18402
"2210",2012,18778.0952380952,2014,19447.6
"2211",2012,17420,2014,18158.8
"2301",2012,18978.8461538462,2014,19609.3
"2302",2012,19920,2014,20419
"2303",2012,18947,2014,19704.7
"2304",2012,20011.7391304348,2014,20639
"2305",2012,18633.4166666667,2014,19348.6
"2306",2012,19222.6666666667,2014,19937.6
"2307",2012,19716,2014,20349.3
"2401",2012,19496,2014,20116.7
"2402",2012,17587.3913043478,2014,18264.3
"2403",2012,18039.3333333333,2014,18668.9
"2404",2012,20862,2014,21386.8
"2405",2012,19088,2014,19617.5
"2406",2012,19682,2014,20246
"2407",2012,17765,2014,18244
"2408",2012,18813.3333333333,2014,19590.5
"2409",2012,18460.8695652174,2014,19134
"2410",2012,19341.3333333333,2014,20286.2
"2411",2012,18503.5,2014,19170
"2412",2012,20074.7619047619,2014,20669
"2413",2012,19886,2014,20426.5
"2414",2012,18549,2014,19111.7
"2415",2012,19298.0952380952,2014,19929
"2416",2012,19159.5833333333,2014,19763.3
"2417",2012,19013.3333333333,2014,19521.9
"2418",2012,20852,2014,21314
"2419",2012,19696.8,2014,20135.4
"2501",2012,18832.9166666667,2014,19616.7
"2502",2012,19839.6428571429,2014,20447.3
"2503",2012,19357,2014,19949.3
"2504",2012,17890,2014,18668.5
"2505",2012,17836.1904761905,2014,18619.5
"2506",2012,18373.0434782609,2014,19247.3
"2507",2012,18855,2014,19788.7
"2508",2012,18192.0833333333,2014,19076
"2509",2012,19105,2014,19896.6
"2510",2012,18837.2222222222,2014,19621.4
"2511",2012,18071.5,2014,18835
"2512",2012,18059.5,2014,18796.7
"2513",2012,17989.5652173913,2014,18533.5
"2601",2012,20356,2014,21106.7
"2602",2012,18218.4,2014,18926.7
"2603",2012,20719.6666666667,2014,21264.4
"2604",2012,18828.3333333333,2014,19445.7
"2605",2012,17496,2014,18232
"2606",2012,18618.3333333333,2014,19419.2
"2607",2012,18150,2014,18717
"2608",2012,19290,2014,20024
"2609",2012,18376,2014,19020
"2610",2012,18123.5,2014,18997.2
"2611",2012,18232,2014,19093.1
"2612",2012,19023.3962264151,2014,19581.7
"2613",2012,18402.2222222222,2014,19055
"2614",2012,19352.6666666667,2014,19970
"3110",2012,17632,2014,18171.3
"3111",2012,19872.3214285714,2014,20498.6
"3112",2012,17909.5,2014,18786
"3113",2012,19370.8695652174,2014,20029
"3114",2012,17411.6666666667,2014,18153.1
"3115",2012,16527.5,2014,17161.7
"3116",2012,17494,2014,18124.5
"3117",2012,16522.5,2014,17252.5
"3121",2012,18958.5714285714,2014,19749.5
"3122",2012,15848,2014,16471.3
"3123",2012,17325,2014,18070
"3124",2012,17319,2014,18080.7
"3125",2012,16943,2014,17776.5
"3126",2012,17054,2014,17783.8
"3127",2012,17860.6666666667,2014,18527.8
"4101",2012,19057,2014,20396.5
"4102",2012,18167.3913043478,2014,18923.8
"4103",2012,20100,2014,20734.3
"4104",2012,19253.4615384615,2014,19914.7
"4105",2012,18178,2014,18899.6
"4106",2012,18415.5555555556,2014,19180
"4107",2012,19765.3333333333,2014,20611.4
"4108",2012,17936.3043478261,2014,18670.5
"4109",2012,19220,2014,19884
"4110",2012,19699,2014,20456
"4111",2012,19975.5555555556,2014,21490
"4112",2012,18561.9047619048,2014,19239.6
"4113",2012,18533,2014,19207
"4114",2012,17932,2014,18625
"4115",2012,18513.6,2014,19304
"4201",2012,21662,2014,22259.4
"4202",2012,22121.4285714286,2014,22678
"4203",2012,20694.9743589744,2014,21249.2
"4204",2012,20996.6666666667,2014,21554
"4205",2012,20637.2,2014,20939.5
"4206",2012,22284.4,2014,22998
"4207",2012,21402,2014,21892
"4208",2012,20530.4761904762,2014,20987.7
"4209",2012,27116,2014,27578
"4301",2012,19866.7857142857,2014,20474.7
"4302",2012,19037.6923076923,2014,19688.7
"4303",2012,26342.380952381,2014,26900.4
"4304",2012,23223.3333333333,2014,24219
"4305",2012,19166.4516129032,2014,19840
"4306",2012,19092.2222222222,2014,19879.5
"4307",2012,20652,2014,21500.8
"4308",2012,18128,2014,18743
"4309",2012,18185,2014,18844.7
"5201",2012,18881.4814814815,2014,19667.6
"5202",2012,17665.6,2014,18286
"5203",2012,20616,2014,21241
"5204",2012,19844.8,2014,20508
"5205",2012,19443,2014,20094.4
"5206",2012,18905.7142857143,2014,19605
"5207",2012,17964.6666666667,2014,18666
"5208",2012,18107.3333333333,2014,18734.4
"5209",2012,18951.7857142857,2014,19703.8
"5210",2012,18635.7142857143,2014,19332
"5211",2012,18973.2258064516,2014,19556.5
"5212",2012,18178.6666666667,2014,18824
"5213",2012,19304.6666666667,2014,19966.7
"5214",2012,18363.3333333333,2014,19098.9
"5215",2012,19146.6666666667,2014,19786.7
"5216",2012,18103.3333333333,2014,18876.7
"5217",2012,18984,2014,19686
"5218",2012,19186.1904761905,2014,19813.8
"5219",2012,20042.380952381,2014,20712.9
"5301",2012,19939.2,2014,20655.3
"5302",2012,18221.4285714286,2014,18960
"5303",2012,20016,2014,20691.3
"5304",2012,18641.5,2014,19282.2
"5305",2012,19581.3333333333,2014,20232.9
"5306",2012,19916.0869565217,2014,20649.4
"5307",2012,17941.3333333333,2014,18671
"5308",2012,19373.3333333333,2014,19991.9
"5309",2012,19634.347826087,2014,20377.6
"5310",2012,18645.3846153846,2014,19283.8
"5311",2012,18720,2014,19397.2
"5312",2012,20578,2014,21143.8
"5313",2012,19380.6666666667,2014,20159.3
"5314",2012,19439,2014,20248.1
"5315",2012,19573,2014,20304.3
"5316",2012,18751.25,2014,19417.2
"5317",2012,18940,2014,19701.3
"5318",2012,20075.4166666667,2014,20740
"5401",2012,17907.5,2014,18522.9
"5402",2012,18704.6666666667,2014,19349
"5403",2012,18580.3846153846,2014,19280
"5404",2012,17407,2014,18222
"5405",2012,19327.5,2014,20055.3
"5406",2012,18512.4,2014,19128
"5407",2012,19217.6,2014,19903.5
"5408",2012,18673,2014,19379.3
"5409",2012,20270,2014,20855.6
"5410",2012,19489.1666666667,2014,20238.1
"5411",2012,17890,2014,18620.5
"5412",2012,18078.0952380952,2014,18834
"5413",2012,19446.5,2014,20043
"7201",2012,18008.4637681159,2014,18697.3
"7202",2012,18425,2014,19159
"7203",2012,18106.6666666667,2014,18658.7
"7204",2012,20667,2014,21249.5
"7205",2012,18035.3333333333,2014,18711.3
"7206",2012,18450.9523809524,2014,19101.3
"7207",2012,20320.8695652174,2014,20948
"7208",2012,19536,2014,20100
"7209",2012,18869.3333333333,2014,19480.7
"7210",2012,17737.5,2014,18362
"7211",2012,17410,2014,17987.6
"7212",2012,20164.6666666667,2014,20683.9
"7213",2012,19245,2014,19834
"7214",2012,20302,2014,20867.6
"7301",2012,18256,2014,18876.3
"7302",2012,17957,2014,18514
"7303",2012,18034.6666666667,2014,18724.8
"7304",2012,19017.2222222222,2014,19799.3
"7305",2012,17916.1904761905,2014,18698
"7306",2012,18578,2014,19336.7
"7307",2012,18857.619047619,2014,19230
"7308",2012,18793.3333333333,2014,19457.6
"7309",2012,19058.6956521739,2014,19787.6
"7310",2012,18895.3333333333,2014,19429.5
"7311",2012,18878.1780538302,2014,19430.7
"7312",2012,18183.8461538462,2014,18879.2
"7313",2012,18197.3333333333,2014,18632
"7401",2012,19040,2014,19716
"7402",2012,18143.3333333333,2014,18897.2
"7403",2012,17301.3043478261,2014,17984
"7404",2012,19118,2014,19698
"8201",2012,20643.8095238095,2014,21227.1
"8202",2012,20174.6666666667,2014,20682.4
"8203",2012,18474.4444444444,2014,19119.6
"8204",2012,18964.6153846154,2014,19694
"8205",2012,17833.8461538462,2014,18486
"8206",2012,18796,2014,19433
"8207",2012,18750.4347826087,2014,19414.5
"8208",2012,19158.8,2014,19833.1
"8209",2012,20058.9655172414,2014,20741.1
"8210",2012,21119.1153846154,2014,21684.5
"8211",2012,19926,2014,20499.3
"8212",2012,18585.7142857143,2014,19272
"8213",2012,21155,2014,21768
"8214",2012,20965,2014,21470
"8215",2012,20356.9230769231,2014,20849.2
"8216",2012,21009.6,2014,21576.5
"8217",2012,20380.7692307692,2014,20996
"8218",2012,23005.2173913043,2014,23712.7
"8219",2012,27201.9230769231,2014,27749.3
"8220",2012,21017,2014,21626.5
"8221",2012,21245.0909090909,2014,21706.7
"8222",2012,23036.0869565217,2014,23862.9
"8301",2012,18453.9393939394,2014,19023.3
"8302",2012,18534.3333333333,2014,19190
"8303",2012,18492,2014,19091.3
"8304",2012,18855.7142857143,2014,19606.7
"8305",2012,17307.5595238095,2014,18159
"8306",2012,17459.1666666667,2014,18457
"8307",2012,17890.4761904762,2014,18484.8
"8308",2012,18963,2014,19466.1
"8309",2012,18347.1428571429,2014,19084
"8310",2012,20412,2014,21071.7
"8311",2012,19008.5,2014,19795.7
"8312",2012,18111.6666666667,2014,18856.5
"9101",2012,17408.5714285714,2014,17945.3
"9102",2012,16617.3333333333,2014,17173
"9103",2012,17123.3333333333,2014,17661
"9104",2012,16840,2014,17349.6
"9105",2012,18586,2014,19386.7
"9106",2012,18106.6666666667,2014,18625
"9107",2012,17128.4615384615,2014,17763
"9108",2012,16940.8695652174,2014,17503.5
"9109",2012,17352,2014,17867.5
"9110",2012,16858,2014,17391.3
"9111",2012,19566.6666666667,2014,20024.4
"9112",2012,17690.4,2014,18320.7
"9113",2012,18336.5217391304,2014,19110
"9114",2012,18100.4545454545,2014,18640.7
"9115",2012,17447.2222222222,2014,17903.9
"9116",2012,17108,2014,17654.6
"9301",2012,18502,2014,19034.2
"9302",2012,18934.8,2014,19401.5
"9303",2012,18952.3076923077,2014,19365.3
"9304",2012,18794.7619047619,2014,19335
"9305",2012,20466.1111111111,2014,20830.8
"9306",2012,20292.8,2014,20668.7
"9307",2012,19959,2014,20333.3
"9308",2012,21603.3333333333,2014,22211.1
"9309",2012,18084,2014,18679.5
"9310",2012,19009,2014,19507
"9311",2012,19514.6666666667,2014,20090
"9312",2012,19813.6,2014,20490.6
"9313",2012,18840,2014,19254.8
"9314",2012,19946.0357142857,2014,20238
"9315",2012,19492,2014,20070.5
"9316",2012,17739.1304347826,2014,18245.7
"9317",2012,17904,2014,18510.6
"9401",2012,19633.8461538462,2014,20418.3
"9402",2012,17570,2014,17890
"9403",2012,17200.8333333333,2014,17640.5
"9404",2012,17777.2666666667,2014,18376.4
"9405",2012,17254.5,2014,17473.5
"9406",2012,17553.3333333333,2014,18426
"9407",2012,16885,2014,17577.7
Your instincts will work - filter the path data according to the color:
features.filter(function(feature) {
return color(feature.properties["value0"]) == d;
})
I saved your feature paths in the variable features in the plunkrs below
As the datum of each legend entry is a color, we can just filter the paths based on which datum would produce the same color when scaled. We could alternatively give class names or apply other indicators to filter.
Color the filtered paths on the event, revert all paths on some sort anti-event. Since you haven't said what will reset the map, I'll assume if you click on the same legend entry twice in a row the map should reset (this lets you toggle between each legend entry). To do so we'll need to keep track of which legend entry is currently in focus:
var highlighted = "";
Then we just listen for a click event on the legend entry and:
.on("click",function(d,i) {
highlighted = ""; //reset
// revert map back to default state
}
else {
highlighted = d;
// filter features to highlight certain ones.
})
Altogether that might look like:
.on("click",function(d,i) {
// clicking an active entry: reset:
if(highlighted == d) {
// reset opacity on each path:
features.style("opacity",1);
// reset legend entries' fills:
legend.selectAll("rect")
.style("fill",function(d) { return d; });
// reset highlight variable since nothing is highlighted
highlighted = "";
}
// clicking a different entry: highlight that entry:
else {
//update highlighted variable
highlighted = d;
// set opacity low for all features, filter for chosen features and style accordingly:
features.style("opacity",0.2)
.filter(function(f) {
return color(f.properties["value0"]) == d;
})
.style("opacity",1);
// hollow legend entries
legend.selectAll("rect")
.style("fill","white")
// fill selected option:
d3.select(this).select("rect")
.style("fill",function(d) { return d;});
}
})
Which looks something like:
(I'm formatting the legend entries to show what is highlighted - I changed your stroke to accomodate this)
Here's an updated plunkr.
If you want to be able to toggle multiple legend items at once, then the logic gets a bit more detailed and the highlighted variable becomes an array
As an alternative with mouseover/off events rather than clicks (so no need to track what is actively shown), here's a slightly different approach using the same principles: plunkr

Display Data from JSON .on("mouseover", How?

What I'm trying to do is get a function that when I move my mouse over the Map(USA) that is drawn with a d3.json file that this will show it's data which is stored in a CSV file.
What I'm having trouble with is that I don't know how to implement the mouseover function, because I don't know where I should reference towards.
This is my code. I have no idea how to do this. Any tips would be really appreciated.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Applying a projection to SVG paths</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
//Define map projection
var projection = d3.geo.albersUsa()
.translate([w/2, h/2])
.scale([500]);
//Define path generator
var path = d3.geo.path()
.projection(projection);
//Define quantize scale to sort data values into buckets of color
var color = d3.scale.quantize()
.range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]);
//Colors taken from colorbrewer.js, included in the D3 download
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load in agriculture data
d3.csv("us-ag-productivity-2004.csv", function(data) {
//Set input domain for color scale
color.domain([
d3.min(data, function(d) { return d.value; }),
d3.max(data, function(d) { return d.value; })
]);
//Load in GeoJSON data
d3.json("us-states.json", function(json) {
//Merge the ag. data and GeoJSON
//Loop through once for each ag. data value
for (var i = 0; i < data.length; i++) {
//Grab state name
var dataState = data[i].state;
//Grab data value, and convert from string to float
var dataValue = parseFloat(data[i].value);
//Find the corresponding state inside the GeoJSON
for (var j = 0; j < json.features.length; j++) {
var jsonState = json.features[j].properties.name;
if (dataState == jsonState) {
//Copy the data value into the JSON
json.features[j].properties.value = dataValue;
//Stop looking through the JSON
break;
}
}
}
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("fill", function(d) {
//Get data value
var value = d.properties.value;
if (value <1.15) {
//If value exists…
return color(value);
} else if (value >1.15) {
return "red"; }
else {
//If value is undefined…
return "#ccc";
}
});
});
});
</script>
</body>
</html>
You must add 3 events mousedown, mousemove, mouseup
const target = document.getElementsByTagName("SVG");
// or by id
const target = document.getElementsById("someid");
target.addEventListener('mousedown', () => {
console.log('mousedown');
});
target.addEventListener('mousemove', () => {
console.log('mousemove');
});
target.addEventListener('mouseup', () => {
console.log('mouseup');
});
but I thing d3.js handle all this, check the official documentation.

how to do a simple looping carousel of svg:g elements with D3.js

I am trying to make a scrollable list that is part of a bigger d3.js generated chart. clicking on list item acivates changes in the rest of the chart.
How would you make a simple animated looping carousel of svg:g elements with D3.js using the reusable chart pattern ?
Wired to jQuery-mousewheel or some forward and back buttons for example.
http://jsbin.com/igopix/2/edit
NameLoop = function () {
var scroll = 0;
function chart(selection) {
selection.each(function (data) {
var len = data.length,
scroll = scroll % len + len; // keep scroll between 0 <-> len
var nameNodes = d3.select(this).selectAll("g")
.data(data, function(d){return d.ID;} );
var nameNodesEnter = nameNodes.enter().append("g")
.attr("class", "nameNode")
.attr("transform", function(d, i) {
// implement scroll here ??
return "translate(30," + (i+1)*20 + ")";
})
.append("text")
.text(function(d){return d.ID;});
});
return chart;
}
chart.scroll = function(_) {
if (!arguments.length) return scroll;
scroll = _;
return chart;
};
return chart;
};
data = [{ID:"A"},{ID:"B"},{ID:"C"},{ID:"D"},{ID:"E"}];
var svg = d3.select("body").append("svg")
.attr("width", 200)
.attr("height",200)
.attr("id","svg");
var nameloop = NameLoop();
d3.select("#svg").datum(data).call(nameloop);
var body = d3.select("body").append("div");
body.append("span").on("click",function(d){ scroll(1) }).html("forward ");
body.append("span").on("click",function(d){ scroll(-1) }).html("back");

Categories