D3.js heatmap with color - javascript
Hi I am trying to add in a color scale for my heat map. I Specifically want to use d3.schemeRdYlBu this color scheme but I am having a hard time implementing it. At the moment it just does black. I also have a hover feature with this so I would like that to still work but i am more concerned with just getting the color to work. Obviously having the lower numbers be blue and the higher numbers be red to indicate temp
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = {top: 80, right: 25, bottom: 30, left: 40},
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv", function(data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3.map(data, function(d){return d.group;}).keys()
var myVars = d3.map(data, function(d){return d.variable;}).keys()
// Build X scales and axis:
var x = d3.scaleBand()
.range([ 0, width ])
.domain(myGroups)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain").remove()
// Build Y scales and axis:
var y = d3.scaleBand()
.range([ height, 0 ])
.domain(myVars)
.padding(0.05);
svg.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain").remove()
// Build color scale
var myColor = (d3.schemeRdYlBu[2])
// create a tooltip
var tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px")
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function(d) {
tooltip
.style("opacity", 1)
d3.select(this)
.style("stroke", "green")
.style("opacity", 1)
}
var mousemove = function(d) {
tooltip
.html("The exact value of this cell is: " + d.value, )
.style("left", (d3.mouse(this)[0]+70) + "px")
.style("top", (d3.mouse(this)[1]) + "px")
}
var mouseleave = function(d) {
tooltip
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 0.8)
}
// add the squares
svg.selectAll()
.data(data, function(d) {return d.group+':'+d.variable;})
.enter()
.append("rect")
.attr("x", function(d) { return x(d.group) })
.attr("y", function(d) { return y(d.variable) })
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth() )
.attr("height", y.bandwidth() )
.style("fill", function(d) { return myColor(d.value)} )
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
})
// Add title to graph
svg.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>
You can use arrow function instead of the regular function to use your own binding of this for accessing myColor variable.
<!DOCTYPE html>
<meta charset="utf-8" />
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<!-- Load color palettes -->
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = { top: 80, right: 25, bottom: 30, left: 40 },
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3
.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv(
"https://raw.githubusercontent.com/Nataliemcg18/Data/master/NASA_Surface_Temperature.csv",
function (data) {
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable'
var myGroups = d3
.map(data, function (d) {
return d.group;
})
.keys();
var myVars = d3
.map(data, function (d) {
return d.variable;
})
.keys();
// Build X scales and axis:
var x = d3.scaleBand().range([0, width]).domain(myGroups).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0))
.select(".domain")
.remove();
// Build Y scales and axis:
var y = d3.scaleBand().range([height, 0]).domain(myVars).padding(0.05);
svg
.append("g")
.style("font-size", 15)
.call(d3.axisLeft(y).tickSize(0))
.select(".domain")
.remove();
// Build color scale
var myColor = d3.schemeRdYlBu[3][2];
// create a tooltip
var tooltip = d3
.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "2px")
.style("border-radius", "5px")
.style("padding", "5px");
// Three function that change the tooltip when user hover / move / leave a cell
var mouseover = function (d) {
tooltip.style("opacity", 1);
d3.select(this).style("stroke", "green").style("opacity", 1);
};
var mousemove = function (d) {
tooltip
.html("The exact value of this cell is: " + d.value)
.style("left", d3.mouse(this)[0] + 70 + "px")
.style("top", d3.mouse(this)[1] + "px");
};
var mouseleave = function (d) {
tooltip.style("opacity", 0);
d3.select(this).style("stroke", "none").style("opacity", 0.8);
};
// add the squares
svg
.selectAll()
.data(data, function (d) {
return d.group + ":" + d.variable;
})
.enter()
.append("rect")
.attr("x", function (d) {
return x(d.group);
})
.attr("y", function (d) {
return y(d.variable);
})
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", (d) => {
return myColor;
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave);
}
);
// Add title to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -50)
.attr("text-anchor", "left")
.style("font-size", "22px")
.text("A d3.js heatmap");
// Add subtitle to graph
svg
.append("text")
.attr("x", 0)
.attr("y", -20)
.attr("text-anchor", "left")
.style("font-size", "14px")
.style("fill", "grey")
.style("max-width", 400)
.text("A short description of the take-away message of this chart.");
</script>
This is another way to get the desired results
var myColor = d3.scaleSequential()
.interpolator( d3.interpolateRdYlBu)
.domain([1.37, -.81])
Related
How do I plot a scatterplot with this kind of dataset?
I am a complete beginner of Javascript and D3. Currently I have been trying to create a scatterplot with x-axis showing the years and percentiles for every year and y-axis showing the values for 3 variables. But I cannot seem to get my code running. Please help. This is the excerpt of the dataset I have now: country_code,year,welfare_type,percentile,avg_welfare,pop_share,welfare_share AUS,2014,income,1,2.706183088,0.009969853,4.13E-04 AUS,2014,income,2,11.03834646,0.010027236,0.001695224 AUS,2014,income,3,15.21296516,0.009923341,0.002312137 AUS,2014,income,4,17.78666642,0.009876024,0.00269041 AUS,2014,income,5,19.65899193,0.009817937,0.002956128 AUS,2014,income,6,21.23338101,0.010270198,0.003339948 AUS,2014,income,7,22.71642933,0.010107506,0.003516624 AUS,2014,income,8,23.88424149,0.010001223,0.003658528 AUS,2014,income,9,24.95633096,0.009820398,0.003753631 AUS,2014,income,10,25.78625374,0.010083031,0.003982182 AUS,2014,income,11,26.61719414,0.00994973,0.004056163 AUS,2014,income,12,27.43463276,0.010096198,0.004242275 AUS,2014,income,13,28.31720791,0.010045165,0.004356616 AUS,2014,income,14,29.23106771,0.009896533,0.004430671 AUS,2014,income,16,30.55067193,0.009863549,0.004615256 AUS,2014,income,15,29.89843511,0.010094814,0.004622624 AUS,2014,income,17,31.20316268,0.010020247,0.004788713 AUS,2014,income,19,32.38771182,0.009888694,0.004905248 AUS,2014,income,18,31.82871304,0.010124787,0.004935677 AUS,2014,income,20,32.95847038,0.00998462,0.005040114 AUS,2014,income,21,33.6474718,0.010047902,0.00517809 AUS,2014,income,22,34.33875307,0.010052882,0.005287092 AUS,2014,income,23,35.01464846,0.0099175,0.005318556 AUS,2014,income,24,35.63748207,0.010094145,0.005509578 AUS,2014,income,26,37.03581494,0.009755934,0.005533916 AUS,2014,income,25,36.26642742,0.009996408,0.005552525 AUS,2014,income,28,38.23585461,0.009992649,0.00585185 AUS,2014,income,29,38.94099912,0.009912763,0.005912125 AUS,2014,income,27,37.61468566,0.010266587,0.005914599 AUS,2014,income,30,39.66490264,0.010092823,0.006131417 AUS,2014,income,31,40.37644593,0.009921456,0.006135434 AUS,2014,income,32,41.02135057,0.00998833,0.006275446 AUS,2014,income,34,42.01105027,0.009758772,0.006279145 AUS,2014,income,33,41.62407432,0.010037465,0.006398975 AUS,2014,income,36,43.03352375,0.010044596,0.006620354 AUS,2014,income,37,43.59007717,0.009950045,0.00664285 AUS,2014,income,35,42.4723306,0.010237364,0.006659414 AUS,2014,income,38,44.05401838,0.009974684,0.006730177 AUS,2014,income,39,44.59078719,0.010080713,0.006884592 AUS,2014,income,40,45.22011959,0.010009614,0.006932515 AUS,2014,income,41,45.78335857,0.009937155,0.006968054 AUS,2014,income,42,46.49121536,0.010059652,0.007163011 AUS,2014,income,44,47.72893726,0.009855791,0.007204686 AUS,2014,income,43,47.10222632,0.010004851,0.007217617 AUS,2014,income,46,48.96673209,0.009786594,0.007339635 AUS,2014,income,45,48.31298287,0.010139416,0.007502717 AUS,2014,income,47,49.62708527,0.010060983,0.007647174 AUS,2014,income,49,51.09694646,0.009849214,0.00770794 AUS,2014,income,48,50.38862979,0.010149339,0.007832711 AUS,2014,income,50,51.83564211,0.010094099,0.008013788 AUS,2014,income,51,52.57598103,0.01003079,0.008077265 AUS,2014,income,52,53.44639201,0.010033813,0.00821346 AUS,2014,income,53,54.36172111,0.009865484,0.008213976 AUS,2014,income,54,55.3113642,0.01011584,0.008569552 AUS,2014,income,55,56.25654416,0.009960817,0.008582421 AUS,2014,income,56,57.0291785,0.009991576,0.008727159 AUS,2014,income,57,57.94137541,0.009839134,0.008731472 AUS,2014,income,58,58.59715086,0.009916506,0.008899733 AUS,2014,income,60,60.15320318,0.010046913,0.00925621 AUS,2014,income,59,59.28244241,0.01025988,0.009315586 AUS,2014,income,61,61.24756855,0.009985114,0.009366636 AUS,2014,income,62,62.45605758,0.010001891,0.0095675 AUS,2014,income,63,63.53518536,0.010014243,0.009744829 AUS,2014,income,64,64.52243794,0.00991656,0.009799718 AUS,2014,income,66,66.6700305,0.009775673,0.009982036 AUS,2014,income,65,65.58589209,0.010078047,0.010123451 AUS,2014,income,68,68.73954583,0.010002134,0.010530309 AUS,2014,income,67,67.67139554,0.010204008,0.01057591 AUS,2014,income,69,69.68166938,0.009959784,0.010629437 AUS,2014,income,70,70.78054852,0.009890164,0.01072159 AUS,2014,income,72,73.10381941,0.009986389,0.011181249 AUS,2014,income,71,71.82035176,0.010175222,0.011192657 AUS,2014,income,73,74.50528527,0.010016861,0.011430376 AUS,2014,income,74,75.81199845,0.009955876,0.011560037 AUS,2014,income,75,77.04250182,0.010042825,0.011850264 AUS,2014,income,76,78.565506,0.009955459,0.011979398 AUS,2014,income,77,80.40478014,0.009977753,0.012287298 AUS,2014,income,78,82.12333785,0.010043796,0.012632993 AUS,2014,income,79,83.79248925,0.009988891,0.012819295 AUS,2014,income,80,85.55768023,0.009991496,0.013092763 AUS,2014,income,81,87.47915,0.010038706,0.013450056 AUS,2014,income,82,89.38254022,0.009986228,0.013670864 AUS,2014,income,83,91.63481485,0.009953002,0.013968713 AUS,2014,income,84,93.91744067,0.010000544,0.01438506 AUS,2014,income,85,96.41946083,0.01005068,0.014842324 AUS,2014,income,86,99.54540544,0.009921946,0.015127246 AUS,2014,income,87,102.9654549,0.010061255,0.015866659 AUS,2014,income,88,105.971401,0.010025493,0.016271822 AUS,2014,income,89,109.1419537,0.009901563,0.016551497 AUS,2014,income,90,112.514213,0.009965222,0.017172604 AUS,2014,income,91,116.3289357,0.010076984,0.017953955 AUS,2014,income,92,120.6459775,0.01006046,0.018589704 AUS,2014,income,93,125.5685177,0.009956968,0.019149158 AUS,2014,income,94,131.9060045,0.010046029,0.020295548 AUS,2014,income,95,139.9451658,0.009996381,0.021426068 AUS,2014,income,96,148.6943539,0.009975502,0.022718048 AUS,2014,income,97,161.3097917,0.009998721,0.024702846 AUS,2014,income,98,181.7236599,0.010022054,0.027893949 AUS,2014,income,99,217.7250904,0.009993702,0.033325498 AUS,2014,income,100,419.3771126,0.010014813,0.064326418 AUS,2016,income,1,2.921344881,0.009891044,4.53E-04 AUS,2016,income,2,10.86946963,0.009887197,0.001684881 AUS,2016,income,3,14.96556705,0.010220573,0.002398038 AUS,2016,income,4,17.41174479,0.009960163,0.00271892 AUS,2016,income,5,18.84613732,0.009949316,0.002939701 AUS,2016,income,6,20.38088749,0.010060453,0.00321461 AUS,2016,income,7,21.94488945,0.009988179,0.003436429 AUS,2016,income,8,22.9706105,0.010022147,0.003609283 AUS,2016,income,10,25.00293992,0.009354153,0.003666766 AUS,2016,income,9,24.0096397,0.009995351,0.003762455 AUS,2016,income,12,26.62725434,0.009971033,0.004162499 AUS,2016,income,13,27.3528324,0.010032514,0.00430229 AUS,2016,income,11,25.76408298,0.010652475,0.004302817 AUS,2016,income,14,28.17373116,0.009973422,0.004405307 AUS,2016,income,15,29.05679359,0.00986932,0.004495961 AUS,2016,income,16,29.93744756,0.010155514,0.004766551 AUS,2016,income,17,30.59293397,0.010010156,0.004801197 AUS,2016,income,18,31.20220578,0.010001867,0.004892761 AUS,2016,income,19,31.63021913,0.009993163,0.00495556 AUS,2016,income,20,32.32867948,0.010001634,0.005069283 AUS,2016,income,21,33.06058859,0.01000566,0.005186136 AUS,2016,income,22,33.67194926,0.009929743,0.005241962 AUS,2016,income,23,34.30940692,0.010074751,0.005419199 AUS,2016,income,24,34.84748724,0.009926655,0.005423279 AUS,2016,income,25,35.29368138,0.009943476,0.005502028 AUS,2016,income,27,36.74800232,0.009728971,0.005605163 AUS,2016,income,26,35.97401424,0.010091598,0.005691627 AUS,2016,income,29,38.19577669,0.009894985,0.005925406 AUS,2016,income,28,37.45386648,0.010306717,0.006052079 AUS,2016,income,30,38.83223624,0.010107443,0.006153488 AUS,2016,income,31,39.40745425,0.009980666,0.006166312 AUS,2016,income,32,40.10945618,0.009983972,0.006278238 AUS,2016,income,33,40.78564161,0.00995818,0.006367587 AUS,2016,income,35,41.63865286,0.009996976,0.006526088 AUS,2016,income,34,41.39825541,0.010074415,0.006538671 AUS,2016,income,36,42.02093891,0.009971631,0.006569307 AUS,2016,income,37,42.62393647,0.010025866,0.006699819 AUS,2016,income,38,43.26897405,0.009984334,0.006773034 AUS,2016,income,39,43.95228489,0.009974039,0.006872902 AUS,2016,income,40,44.61490953,0.010040435,0.007022959 AUS,2016,income,41,45.37646989,0.009964403,0.007088749 AUS,2016,income,42,45.97395005,0.010033745,0.007232068 AUS,2016,income,43,46.65105029,0.009968655,0.007290975 AUS,2016,income,46,48.73932332,0.009553738,0.007300295 AUS,2016,income,44,47.42866471,0.010030614,0.007458578 AUS,2016,income,45,48.02211222,0.009979524,0.007513438 AUS,2016,income,48,50.01934665,0.009986286,0.007831224 AUS,2016,income,49,50.72917496,0.010008305,0.007959869 AUS,2016,income,50,51.46537181,0.010003591,0.008071582 AUS,2016,income,47,49.36311865,0.010466048,0.008099774 AUS,2016,income,51,52.29708356,0.009965039,0.008170414 AUS,2016,income,52,53.21992628,0.009944834,0.008297732 AUS,2016,income,53,53.94076603,0.010028668,0.008481017 AUS,2016,income,54,54.73058001,0.010073508,0.008643675 AUS,2016,income,55,55.66432548,0.009998435,0.008725626 AUS,2016,income,56,56.71593196,0.009997721,0.008889835 AUS,2016,income,58,58.50555862,0.009824501,0.009011461 AUS,2016,income,57,57.57195448,0.009994539,0.009021138 AUS,2016,income,59,59.45792769,0.010138709,0.009451049 AUS,2016,income,60,60.62677419,0.01000758,0.009512204 AUS,2016,income,61,61.80787097,0.00992854,0.009620924 AUS,2016,income,63,63.43629548,0.009874096,0.009820255 AUS,2016,income,62,62.54525396,0.010092093,0.009896081 AUS,2016,income,64,64.60173999,0.010140293,0.010270281 AUS,2016,income,65,65.60493276,0.009991716,0.010276948 AUS,2016,income,66,66.72095274,0.0100073,0.010468074 AUS,2016,income,67,67.93312637,0.009973639,0.010622405 AUS,2016,income,68,69.29769991,0.009953586,0.010813991 AUS,2016,income,69,70.61850675,0.010067056,0.011145732 AUS,2016,income,70,71.88259924,0.010003244,0.01127333 AUS,2016,income,71,73.1759581,0.009903166,0.011361353 AUS,2016,income,73,75.68829689,0.009855145,0.011694438 AUS,2016,income,72,74.49065685,0.010101602,0.01179722 AUS,2016,income,74,76.93036571,0.009955659,0.012007578 AUS,2016,income,77,81.22701085,0.009611704,0.012240199 AUS,2016,income,75,78.2816762,0.010156349,0.012464801 AUS,2016,income,76,79.70407585,0.01002164,0.012522958 AUS,2016,income,79,84.38656413,0.009776858,0.012934814 AUS,2016,income,78,82.90435259,0.010162592,0.013208984 AUS,2016,income,81,88.14204825,0.009881302,0.013654787 AUS,2016,income,80,85.99034668,0.010424978,0.014054405 AUS,2016,income,82,89.83042069,0.010017994,0.014108856 AUS,2016,income,83,91.3544176,0.010030154,0.014365632 AUS,2016,income,84,93.16756247,0.010100337,0.014753267 AUS,2016,income,85,95.15888443,0.009933997,0.014820436 AUS,2016,income,86,97.77003411,0.010059915,0.015420118 AUS,2016,income,87,100.7484106,0.009970617,0.015748813 AUS,2016,income,88,103.3231109,0.010040767,0.016264921 AUS,2016,income,89,106.4835939,0.009997772,0.016690661 AUS,2016,income,90,109.9008807,0.009943091,0.017132083 AUS,2016,income,91,113.327115,0.01006132,0.01787625 AUS,2016,income,92,117.2869678,0.009933027,0.01826497 AUS,2016,income,93,121.4394061,0.009984393,0.019009422 AUS,2016,income,94,126.5037933,0.010056994,0.019946163 AUS,2016,income,95,133.7253411,0.010013734,0.020994106 AUS,2016,income,96,142.5918642,0.009978695,0.022307768 AUS,2016,income,97,153.5144822,0.009931858,0.023903829 AUS,2016,income,98,170.2017432,0.010084885,0.026910549 AUS,2016,income,99,208.2369816,0.010000861,0.032649976 AUS,2016,income,100,360.2167398,0.010018403,0.056578312 AUS,2018,income,1,2.595366313,0.009842698,3.95E-04 AUS,2018,income,2,9.823911429,0.010133857,0.001540855 AUS,2018,income,3,14.02903825,0.010019847,0.002175663 AUS,2018,income,4,16.20475069,0.00999557,0.00250699 AUS,2018,income,5,18.10915852,0.00998426,0.002798445 AUS,2018,income,6,19.9508763,0.00993849,0.003068916 AUS,2018,income,7,21.28037443,0.009700865,0.003195158 AUS,2018,income,8,22.46745331,0.010256684,0.003566674 AUS,2018,income,9,23.58626711,0.010043957,0.003666627 AUS,2018,income,10,24.56020059,0.009778468,0.00371711 AUS,2018,income,11,25.42979959,0.010202929,0.004015785 AUS,2018,income,12,26.33331407,0.010042599,0.004093118 AUS,2018,income,13,27.40014618,0.010006882,0.004243794 AUS,2018,income,14,28.52270694,0.009951873,0.004393375 AUS,2018,income,15,29.52728239,0.010003639,0.004571767 AUS,2018,income,16,30.26886102,0.009941065,0.004657272 AUS,2018,income,17,31.05298971,0.010123957,0.004865824 AUS,2018,income,18,31.98053166,0.010029435,0.004964377 AUS,2018,income,20,33.22802717,0.009797099,0.00503854 AUS,2018,income,19,32.66549084,0.009992269,0.005051914 AUS,2018,income,21,33.63693313,0.010003789,0.005208151 AUS,2018,income,25,36.01406074,0.009539114,0.005317198 AUS,2018,income,22,34.17025041,0.010130968,0.005357988 AUS,2018,income,23,34.82676969,0.010063973,0.00542482 AUS,2018,income,24,35.36869964,0.010013115,0.005481393 AUS,2018,income,27,37.20731631,0.009821302,0.005655879 AUS,2018,income,33,40.87633985,0.009210976,0.005827474 AUS,2018,income,26,36.50531459,0.01045545,0.005907469 AUS,2018,income,28,37.85771532,0.010182103,0.005966155 AUS,2018,income,29,38.61389827,0.010002608,0.00597805 AUS,2018,income,30,39.23941491,0.009962674,0.006050637 AUS,2018,income,31,39.93717676,0.010022552,0.006195243 AUS,2018,income,32,40.47103984,0.009980693,0.006251838 AUS,2018,income,36,42.40615011,0.009803519,0.006434481 AUS,2018,income,35,41.79732628,0.010157682,0.006571216 AUS,2018,income,39,44.29336043,0.009680314,0.006636372 AUS,2018,income,38,43.63415757,0.010038815,0.006779719 AUS,2018,income,37,43.06505422,0.010175109,0.00678214 AUS,2018,income,34,41.19537868,0.010642366,0.006785617 AUS,2018,income,41,45.31986066,0.009964569,0.006989558 AUS,2018,income,40,44.78770392,0.010220832,0.007085128 AUS,2018,income,42,45.98918996,0.010131453,0.007211575 AUS,2018,income,43,46.75184156,0.009979741,0.007221388 AUS,2018,income,44,47.49359156,0.009980116,0.007336236 AUS,2018,income,45,48.33259569,0.010048654,0.007517106 AUS,2018,income,46,49.07601632,0.009919118,0.007534337 AUS,2018,income,47,49.90985642,0.0100312,0.007748932 AUS,2018,income,48,50.82979576,0.010008184,0.007873654 AUS,2018,income,49,51.65939593,0.009968356,0.007970316 AUS,2018,income,50,52.49251803,0.009898442,0.008042053 AUS,2018,income,52,53.87597193,0.0099824,0.008324013 AUS,2018,income,51,53.27500401,0.010125596,0.008349236 AUS,2018,income,53,54.62220616,0.009877231,0.008350397 AUS,2018,income,54,55.47221646,0.009776907,0.008394207 AUS,2018,income,55,56.23253556,0.010238282,0.008910815 AUS,2018,income,56,57.24371642,0.010085894,0.008936035 AUS,2018,income,58,59.10520774,0.009834502,0.008996649 AUS,2018,income,57,58.16688376,0.010051726,0.009049385 AUS,2018,income,60,60.91533476,0.009875512,0.009310841 AUS,2018,income,59,59.90437715,0.010183559,0.009441931 AUS,2018,income,61,61.75432927,0.009958307,0.009518217 AUS,2018,income,62,62.61595691,0.010139702,0.009826817 AUS,2018,income,63,63.64261438,0.010040373,0.009890097 AUS,2018,income,64,64.68995889,0.00999147,0.01000389 AUS,2018,income,65,65.87401702,0.009953768,0.010148557 AUS,2018,income,68,68.91650916,0.009713594,0.0103611 AUS,2018,income,66,66.8617044,0.01005883,0.010409445 AUS,2018,income,67,67.79991077,0.009982134,0.010475027 AUS,2018,income,70,70.96026521,0.009908804,0.010882762 AUS,2018,income,69,70.000275,0.010239873,0.011094225 AUS,2018,income,71,72.26105558,0.010004988,0.011189831 AUS,2018,income,72,73.60416061,0.010107856,0.011515003 AUS,2018,income,73,74.84108522,0.010028489,0.011616578 AUS,2018,income,74,76.30553539,0.009972862,0.011778189 AUS,2018,income,75,77.63277599,0.009953914,0.011960288 AUS,2018,income,76,78.97379055,0.010069723,0.012308445 AUS,2018,income,77,80.61337965,0.00997618,0.012447268 AUS,2018,income,78,82.35020384,0.010030576,0.012784779 AUS,2018,income,79,83.8521037,0.009943725,0.012905229 AUS,2018,income,80,85.3092945,0.010001952,0.013206379 AUS,2018,income,81,86.82983593,0.009983915,0.013417528 AUS,2018,income,82,88.95395683,0.009973547,0.013731487 AUS,2018,income,83,90.96324283,0.009967333,0.014032905 AUS,2018,income,84,93.16888148,0.010097804,0.01456131 I want the year and percentile attributes on the x-axis and divide the y-axis into three sections: avg_welfare, welfare_share and pop_share. This is the current code I have, but nothing is showing on my browser. What is wrong with the code? <!DOCTYPE html> <html lang="en"> <body> <svg width="1000" height="1000"></svg> <script src="https://d3js.org/d3.v4.js" charset="utf-8"> var margin = {top:100, right:80, bottom:80, left:80}; //Setting attributes of SVG var svg = d3.select("body") .append("svg") //Setting attribute width and height as numbers instead of strings var width = parseInt(svg.attr('width')); var height = parseInt(svg.attr("height")); svg.attr("width", width + margin.left + margin.right); svg.attr("height", height + margin.top + margin.bottom); //Setting attributes of x-axis var xaxis = d3.append("g") .attr("transform", "translate(0, " + height + ")") .scaleBand() //Setting attributes of y-axis var yaxis = d3.append("g") .scaleLinear() //Extracting data d3.csv("data/programmingassignment1data.csv", function(error, data){ if (error) throw error; data.forEach(function(d){ d.year = +d.year d.percentile = +d.percentile d.avg_welfare = +d.avg_welfare d.pop_share = +d.pop_share d.welfare_share = +d.welfare_share }) //Drawing x-axis var x1 = xaxis.domain(data.map(function(d) {return d.year})) .range([margin.left, width]).padding(0.4) .call(d3.axisBottom(x1)) var x2 = xaxis.domain(data.map(function(d) {return d.percentile})) .range([margin.left, width/5]).padding(0.4) .call(d3.axisBottom(x2)) var x3 = xaxis.domain(data.map(function(d) {return d.percentile})) .range([width/5, width*2/5]).padding(0.4) .call(d3.axisBottom(x3)) var x4 = xaxis.domain(data.map(function(d) {return d.percentile})) .range([width*2/5, width*3/5]).padding(0.4) .call(d3.axisBottom(x4)) var x5 = xaxis.domain(data.map(function(d) {return d.percentile})) .range([width*3/5, width*4/5]).padding(0.4) .call(d3.axisBottom(x5)) var x6 = xaxis.domain(data.map(function(d) {return d.percentile})) .range([width*4/5, width]).padding(0.4) .call(d3.axisBottom(x6)) //Drawing y-axis var y1 = yaxis.domain([d3.max(data, function(d) {return d.avg_welfare}), 0]) .range([height, height/3]).padding(0.4) .call(d3.axisLeft(y1)) var y2 = yaxis.domain([d3.max(data, function(d) {return d.welfare_share}), 0]) .range([height/3, height*2/3]).padding(0.4) .call(d3.axisLeft(y2)) var y3 = yaxis.domain([d3.max(data, function(d) {return d.pop_share}), 0]) .range([height*2/3, 0]).padding(0.4) .call(d3.axisLeft(y3)) //Setting scatterplot attributes var g = svg.append("g") .selectAll("dot") .data(data) .enter() .append("circle") //Plotting scatterplots var g1 = g.attr("cx", function(d) {return x1(d.year); }) .attr("cy", function(d) {return y1(d.avg_welfare); }) .attr("r", 5) .style("fill", "green") var g2 = g.attr("cx", function(d) {return x1(d.year); }) .attr("cy", function(d) {return y2(d.welfare_share); }) .attr("r", 5) .style("fill", "blue") var g3 = g.attr("cx", function(d) {return x1(d.year); }) .attr("cy", function(d) {return y3(d.pop_share); }) .attr("r", 5) .style("fill", "yellow") //Adding chart title svg.append("text") .attr("transform", "translate(300,0)") .attr("x", 50) .attr("y", 50) .attr("font-size", "40px") .text("Distribution of wealth from 2014-2018"); //Adding data and axis labels var gxLabels = svg.append("g") .attr("transform", "translate(0, " + (height + margin.top + 40) + ")") .append("text") .attr("y", 20) .attr("x", margin.left + width/2) .attr("text-anchor", "end") .attr("stroke", "black") .text("Year"); var gyLabels = svg.append("g") .append("text") .attr("transform", "rotate(-90)") .attr("y", 30) .attr("dy", "-5.1em") .attr("text-anchor", "end") .attr("stroke", "black"); gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 0 * height / 3) + ')') .text("Average Wealth"); gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 1 * height / 3) + ')') .text("Share of Wealth"); gyLabels.attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 2 * height / 3) + ')') .text("Population Share") }); </script> </body>
Here is a working version that produces a stacked scatter plot. <!DOCTYPE html> <html lang="en"> <body> <!-- CORRECTION: you cannot place your SVG inside the script tag --> <svg width="1000" height="1000"></svg> <script src="https://d3js.org/d3.v4.js" charset="utf-8"> </script> <script> // CORRECTION: Added more margin to fit all axes var margin = {top:100, right:30, bottom:80, left:80} var svg = d3.select("svg") // CORRECTION: you were trying to access width before setting it. Attributes come as strings - convert to number var width = parseInt(svg.attr('width')); svg.attr("width", width + margin.left + margin.right); // CORRECTION: also add height margin var height = parseInt(svg.attr("height")); svg.attr('height', height + margin.top + margin.bottom); var g =svg.append("g") d3.csv("Data/programmingassignment1data.csv", function(error, data){ if (error) throw error; data.forEach(function(d){ d.year = +d.year d.percentile = +d.percentile d.avg_welfare = +d.avg_welfare d.pop_share = +d.pop_share d.welfare_share = +d.welfare_share }); var xAxis1 = d3.scaleBand() .domain(data.map(function(d) {return d.year})) .range([margin.left, width]).padding(0.4); var xAxis2 = d3.scaleBand() .domain(data.map(function(d) {return d.percentile})) // CORRECTION: this need to be the same as the other x-Axis. Range is the area of the viewport .range([margin.left, width]).padding(0.4); var yAxis1 = d3.scaleLinear() .domain([0, d3.max(data, function(d) {return d.avg_welfare})]) .range([margin.top + 0 * height / 3, margin.top + 1 * height / 3]); var yAxis2 = d3.scaleLinear() .domain([0, d3.max(data, function(d) {return d.welfare_share})]) .range([margin.top + 1 * height / 3, margin.top + 2 * height / 3]); var yAxis3 = d3.scaleLinear() .domain([0, d3.max(data, function(d) {return d.pop_share})]) .range([margin.top + 2 * height / 3, margin.top + 3 * height / 3]); g.append("g") .attr("transform", "translate(0, " + (height + margin.top + 0) + ")") .call(d3.axisBottom(xAxis1)) g.append("g") .attr("transform", "translate(0, " + (height + margin.top + 20) + ")") .call(d3.axisBottom(xAxis2)) g.append("g") // CORRECTION: move axis by margin .attr('transform', 'translate(' + margin.left + ' 0)') .call(d3.axisLeft(yAxis1)) g.append("g") // CORRECTION: move axis by margin .attr('transform', 'translate(' + margin.left + ' 0)') .call(d3.axisLeft(yAxis2)) g.append("g") // CORRECTION: move axis by margin .attr('transform', 'translate(' + margin.left + ' 0)') .call(d3.axisLeft(yAxis3)) g.selectAll("dot") .data(data) .enter().append("circle") .attr("cx", function(d) {return xAxis1(d.year); }) .attr("cy", function(d) {return yAxis1(d.avg_welfare); }) .attr("r", 5) .style("fill", "green") g.selectAll("dot") .data(data) .enter().append("circle") .attr("cx", function(d) {return xAxis1(d.year); }) .attr("cy", function(d) {return yAxis2(d.welfare_share); }) .attr("r", 5) .style("fill", "blue") g.selectAll("dot") .data(data) .enter().append("circle") .attr("cx", function(d) {return xAxis1(d.year); }) .attr("cy", function(d) {return yAxis3(d.pop_share); }) .attr("r", 5) .style("fill", "yellow") svg.append("text") .attr("transform", "translate(300,0)") .attr("x", 50) .attr("y", 50) .attr("font-size", "40px") .text("Distribution of wealth from 2014-2018"); g.append("g") .attr("transform", "translate(0, " + (height + margin.top + 40) + ")") // .call(d3.axisBottom(xAxis1)) - CORRECTION: This draws the actual axes. You have done this already .append("text") // CORRECTION: the x/y of the text is added to the existing translation of the group .attr("y", 20) .attr("x", margin.left + width) .attr("text-anchor", "end") .attr("stroke", "black") .text("Year"); g.append("g") // CORRECTION: - transform into view (margins) .attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 0 * height / 3) + ')') // .call(d3.axisLeft(yAxis1)) - CORRECTION: This draws the actual axes. You have done this already .append("text") .attr("transform", "rotate(-90)") // CORRECTION: - moved into view - horizontal placement after rotation .attr("y", 30) .attr("dy", "-5.1em") .attr("text-anchor", "end") .attr("stroke", "black") .text("Average Wealth"); g.append("g") // CORRECTION: - transform into view (margins) .attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 1 * height / 3) + ')') // .call(d3.axisLeft(yAxis2)) - CORRECTION: This draws the actual axes. You have done this already .append("text") .attr("transform", "rotate(-90)") // CORRECTION: - moved into view - horizontal placement after rotation .attr("y", 30) .attr("dy", "-5.1em") .attr("text-anchor", "end") .attr("stroke", "black") .text("Share of Wealth"); g.append("g")// CORRECTION: - transform into view (margins) .attr('transform', 'translate(' + margin.left + ', ' + (margin.top + 2 * height / 3) + ')') // .call(d3.axisLeft(yAxis3)) - CORRECTION: This draws the actual axes. You have done this already .append("text") .attr("transform", "rotate(-90)") // CORRECTION: - moved into view - horizontal placement after rotation .attr("y", 30) .attr("dy", "-5.1em") .attr("text-anchor", "end") .attr("stroke", "black") .text("Population Share") }); </script> </body> There were some errors in the script tags. For further improving the solution I would suggest: Do not call you scale functions (i.e. scaleLinear()) 'axis'. An axis is a way of visualizing a scale. Just call them x1, x2, y1, etc. d3.axisLeft() is the command for drawing the axes for a given scale. Work with SVG groups (g). When you transform a g element, the placement of all children will be relative to its origin. You could create a single SVG g element for all three stacked charts and translate them vertically. Have a look at this example of stacking charts.
D3js: How do I make my tooltip appear next to the selection?
I am trying to have a tooltip for each square on my heatmap visualization. However, I am not able to position it next to the cursor correctly. This is what happens: My code is this: const margin = { top: 20, right: 20, bottom: 30, left: 150, }; const width = 960 - margin.left - margin.right; const height = 2500 - margin.top - margin.bottom; let chart = d3 .select("#chart2") .append("div") // Set id to chartArea .attr("id", "chartArea") .classed("chart", true) .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 + ")"); // Make sure to create a separate SVG for the XAxis let axis = d3 .select("#chart2") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", 40) .append("g") .attr("transform", "translate(" + margin.left + ", 0)"); // Load the data d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) { // console.log(data); const years = Array.from(new Set(data.map((d) => d.year))); const countries = Array.from(new Set(data.map((d) => d.entity))); countries.reverse(); const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01); // create a tooltip var tooltip = d3 // Select all boxes in the chart .select("#chart2") .append("div") .classed("tooltip", true) .style("opacity", 0) .attr("class", "tooltip") .style("background-color", "white") .style("border", "solid") .style("border-width", "2px") .style("border-radius", "5px") .style("padding", "5px"); const mouseover = function(event, d) { tooltip.style("opacity", 1); d3.select(this).style("stroke", "black").style("opacity", 1); }; const mousemove = function(event, d) { tooltip .html("The exact value of<br>this cell is: " + d.value) // Position the tooltip next to the cursor .style("left", event.x + "px") .style("top", event.y / 2 + "px"); }; const mouseleave = function(event, d) { tooltip.style("opacity", 0); d3.select(this).style("stroke", "none").style("opacity", 0.8); }; const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01); // Only 10 years axis .call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10)))) .selectAll("text") .style("color", "black") .style("position", "fixed") .attr("transform", "translate(-10,10)rotate(-45)") .style("text-anchor", "end"); chart .append("g") .call(d3.axisLeft(y)) .selectAll("text") .style("color", "black") .attr("transform", "translate(-10,0)") .style("text-anchor", "end"); const colorScale = d3 .scaleSequential() .domain([0, d3.max(data, (d) => d.change)]) .interpolator(d3.interpolateInferno); // add the squares chart .selectAll() .data(data, function(d) { return d.year + ":" + d.entity; }) .join("rect") // Add id-s .attr("id", function(d) { return d.year + ":" + d.entity; }) .attr("x", function(d) { return x(d.year); }) .attr("y", function(d) { return y(d.entity); }) .attr("width", x.bandwidth()) .attr("height", y.bandwidth()) .style("fill", function(d) { return colorScale(d.change); console.log(d.change); }) .style("stroke-width", 4) .style("stroke", "none") .style("opacity", 0.8) .on("mouseover", mouseover) .on("mousemove", mousemove) .on("mouseleave", mouseleave); }); #chart2 .chart { width: 960px; max-height: 900px; overflow-y: scroll; overflow-x: hidden; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <div id="chart2" class="mx-auto"></div> I think I have some idea of why this is happening. Since I am appending the tooltip iv to chart2 div like this, all positioning is happening relative to that div, which means it'll inevitably be below the entire chart and not on top of it: // create a tooltip var tooltip = d3 // Select all boxes in the chart .select("#chart2") .append("div") .classed("tooltip", true) .style("opacity", 0) .attr("class", "tooltip") .style("background-color", "white") .style("border", "solid") .style("border-width", "2px") .style("border-radius", "5px") .style("padding", "5px"); const mousemove = function(event, d) { tooltip .html("The exact value of<br>this cell is: " + d.value) // Position the tooltip next to the cursor .style("left", event.x + "px") .style("top", event.y / 2 + "px"); }; But how else would I do this? I have tried trying to select by the hovered-on rect element but that hasn't been working. I am trying to do something like this. How can I fix this? A live version can be found here
Just add in the mousemove function .style("position","absolute"); and change top style to .style("top", event.y + "px") const margin = { top: 20, right: 20, bottom: 30, left: 150, }; const width = 960 - margin.left - margin.right; const height = 2500 - margin.top - margin.bottom; let chart = d3 .select("#chart2") .append("div") // Set id to chartArea .attr("id", "chartArea") .classed("chart", true) .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 + ")"); // Make sure to create a separate SVG for the XAxis let axis = d3 .select("#chart2") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", 40) .append("g") .attr("transform", "translate(" + margin.left + ", 0)"); // Load the data d3.csv("https://raw.githubusercontent.com/thedivtagguy/files/main/land_use.csv").then(function(data) { // console.log(data); const years = Array.from(new Set(data.map((d) => d.year))); const countries = Array.from(new Set(data.map((d) => d.entity))); countries.reverse(); const x = d3.scaleBand().range([0, width]).domain(years).padding(0.01); // create a tooltip var tooltip = d3 // Select all boxes in the chart .select("#chart2") .append("div") .classed("tooltip", true) .style("opacity", 0) .attr("class", "tooltip") .style("background-color", "white") .style("border", "solid") .style("border-width", "2px") .style("border-radius", "5px") .style("padding", "5px"); const mouseover = function(event, d) { tooltip.style("opacity", 1); d3.select(this).style("stroke", "black").style("opacity", 1); }; const mousemove = function(event, d) { tooltip .html("The exact value of<br>this cell is: " + d.value) // Position the tooltip next to the cursor .style("left", event.x + "px") .style("top", event.y + "px") .style("position","absolute"); }; const mouseleave = function(event, d) { tooltip.style("opacity", 0); d3.select(this).style("stroke", "none").style("opacity", 0.8); }; const y = d3.scaleBand().range([height, 0]).domain(countries).padding(0.01); // Only 10 years axis .call(d3.axisBottom(x).tickValues(years.filter((d, i) => !(i % 10)))) .selectAll("text") .style("color", "black") .style("position", "fixed") .attr("transform", "translate(-10,10)rotate(-45)") .style("text-anchor", "end"); chart .append("g") .call(d3.axisLeft(y)) .selectAll("text") .style("color", "black") .attr("transform", "translate(-10,0)") .style("text-anchor", "end"); const colorScale = d3 .scaleSequential() .domain([0, d3.max(data, (d) => d.change)]) .interpolator(d3.interpolateInferno); // add the squares chart .selectAll() .data(data, function(d) { return d.year + ":" + d.entity; }) .join("rect") // Add id-s .attr("id", function(d) { return d.year + ":" + d.entity; }) .attr("x", function(d) { return x(d.year); }) .attr("y", function(d) { return y(d.entity); }) .attr("width", x.bandwidth()) .attr("height", y.bandwidth()) .style("fill", function(d) { return colorScale(d.change); console.log(d.change); }) .style("stroke-width", 4) .style("stroke", "none") .style("opacity", 0.8) .on("mouseover", mouseover) .on("mousemove", mousemove) .on("mouseleave", mouseleave); }); #chart2 .chart { width: 960px; max-height: 900px; overflow-y: scroll; overflow-x: hidden; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <div id="chart2" class="mx-auto"></div>
Page displaying only 1 of 2 charts
In this codepen I am trying to create 2 treemaps with D3.js but only the second treemap gets displayed. When I check the elements in the console I can see the 2 different svg's are created and written to the DOM but only the second "g" tag is populated with the SVG rect elements. There are 2 distinct div tags with distinct id's. How can I draw 2 D3.sj treemaps on side by side? Thank you. D3.js code var margin = {top: 10, right: 10, bottom: 10, left: 10}, width = 445 - margin.left - margin.right, height = 445 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select("#my_dataviz1") .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 + ")"); // read json data d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) { // Give the data to this cluster layout: var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data // Then d3.treemap computes the position of each element of the hierarchy d3.treemap() .size([width, height]) .paddingTop(28) .paddingRight(7) .paddingInner(3) // Padding between each rectangle //.paddingOuter(6) //.padding(20) (root) // prepare a color scale var color = d3.scaleOrdinal() .domain(["source1", "source2", "source3"]) .range([ "#402D54", "#D18975", "#8FD175"]) // And a opacity scale var opacity = d3.scaleLinear() .domain([10, 30]) .range([.5,1]) // use this information to add rectangles: svg .selectAll("rect") .data(root.leaves()) .enter() .append("rect") .attr('x', function (d) { return d.x0; }) .attr('y', function (d) { return d.y0; }) .attr('width', function (d) { return d.x1 - d.x0; }) .attr('height', function (d) { return d.y1 - d.y0; }) .style("stroke", "black") .style("fill", function(d){ return color(d.parent.data.name)} ) .style("opacity", function(d){ return opacity(d.data.value)}) // and to add the text labels svg .selectAll("text") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower) .text(function(d){ return d.data.name.replace('mister_','') }) .attr("font-size", "19px") .attr("fill", "white") // and to add the text labels svg .selectAll("vals") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower) .text(function(d){ return d.data.value }) .attr("font-size", "11px") .attr("fill", "white") // Add title for the 3 groups svg .selectAll("titles") .data(root.descendants().filter(function(d){return d.depth==1})) .enter() .append("text") .attr("x", function(d){ return d.x0}) .attr("y", function(d){ return d.y0+21}) .text(function(d){ return d.data.name }) .attr("font-size", "19px") .attr("fill", function(d){ return color(d.data.name)} ) // Add title for the 3 groups svg .append("text") .attr("x", 0) .attr("y", 14) // +20 to adjust position (lower) .text("Three group sources") .attr("font-size", "19px") .attr("fill", "grey" ) }) var margin = {top: 10, right: 10, bottom: 10, left: 10}, width = 445 - margin.left - margin.right, height = 445 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select("#my_dataviz2") .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 + ")"); // read json data d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) { // Give the data to this cluster layout: var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data // Then d3.treemap computes the position of each element of the hierarchy d3.treemap() .size([width, height]) .paddingTop(28) .paddingRight(7) .paddingInner(3) // Padding between each rectangle //.paddingOuter(6) //.padding(20) (root) // prepare a color scale var color = d3.scaleOrdinal() .domain(["source1", "source2", "source3"]) .range([ "#402D54", "#D18975", "#8FD175"]) // And a opacity scale var opacity = d3.scaleLinear() .domain([10, 30]) .range([.5,1]) // use this information to add rectangles: svg .selectAll("rect") .data(root.leaves()) .enter() .append("rect") .attr('x', function (d) { return d.x0; }) .attr('y', function (d) { return d.y0; }) .attr('width', function (d) { return d.x1 - d.x0; }) .attr('height', function (d) { return d.y1 - d.y0; }) .style("stroke", "black") .style("fill", function(d){ return color(d.parent.data.name)} ) .style("opacity", function(d){ return opacity(d.data.value)}) // and to add the text labels svg .selectAll("text") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower) .text(function(d){ return d.data.name.replace('mister_','') }) .attr("font-size", "19px") .attr("fill", "white") // and to add the text labels svg .selectAll("vals") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower) .text(function(d){ return d.data.value }) .attr("font-size", "11px") .attr("fill", "white") // Add title for the 3 groups svg .selectAll("titles") .data(root.descendants().filter(function(d){return d.depth==1})) .enter() .append("text") .attr("x", function(d){ return d.x0}) .attr("y", function(d){ return d.y0+21}) .text(function(d){ return d.data.name }) .attr("font-size", "19px") .attr("fill", function(d){ return color(d.data.name)} ) // Add title for the 3 groups svg .append("text") .attr("x", 0) .attr("y", 14) // +20 to adjust position (lower) .text("Three group sources") .attr("font-size", "19px") .attr("fill", "grey" ) }) .dataviz { display: inline-block; } <script src="https://d3js.org/d3.v4.js"></script> <div> <div class="dataviz" id="my_dataviz1"></div> <div class="dataviz" id="my_dataviz2"></div> </div>
You have the same name for the two SVG selections: var svg = d3.select("#my_dataviz1")//etc... var svg = d3.select("#my_dataviz2")//etc.. The solution is quite simple, give them different names: var svg = d3.select("#my_dataviz1")//etc... var svg2 = d3.select("#my_dataviz2")//etc... Finally, considering that both drawing functions do the same, consider creating a single function to which you pass the SVG selection and the data. That way, you can substantially reduce the size of your code. Here is your code with the changes: var margin = {top: 10, right: 10, bottom: 10, left: 10}, width = 445 - margin.left - margin.right, height = 445 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select("#my_dataviz1") .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 + ")"); // read json data d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) { // Give the data to this cluster layout: var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data // Then d3.treemap computes the position of each element of the hierarchy d3.treemap() .size([width, height]) .paddingTop(28) .paddingRight(7) .paddingInner(3) // Padding between each rectangle //.paddingOuter(6) //.padding(20) (root) // prepare a color scale var color = d3.scaleOrdinal() .domain(["source1", "source2", "source3"]) .range([ "#402D54", "#D18975", "#8FD175"]) // And a opacity scale var opacity = d3.scaleLinear() .domain([10, 30]) .range([.5,1]) // use this information to add rectangles: svg .selectAll("rect") .data(root.leaves()) .enter() .append("rect") .attr('x', function (d) { return d.x0; }) .attr('y', function (d) { return d.y0; }) .attr('width', function (d) { return d.x1 - d.x0; }) .attr('height', function (d) { return d.y1 - d.y0; }) .style("stroke", "black") .style("fill", function(d){ return color(d.parent.data.name)} ) .style("opacity", function(d){ return opacity(d.data.value)}) // and to add the text labels svg .selectAll("text") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower) .text(function(d){ return d.data.name.replace('mister_','') }) .attr("font-size", "19px") .attr("fill", "white") // and to add the text labels svg .selectAll("vals") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower) .text(function(d){ return d.data.value }) .attr("font-size", "11px") .attr("fill", "white") // Add title for the 3 groups svg .selectAll("titles") .data(root.descendants().filter(function(d){return d.depth==1})) .enter() .append("text") .attr("x", function(d){ return d.x0}) .attr("y", function(d){ return d.y0+21}) .text(function(d){ return d.data.name }) .attr("font-size", "19px") .attr("fill", function(d){ return color(d.data.name)} ) // Add title for the 3 groups svg .append("text") .attr("x", 0) .attr("y", 14) // +20 to adjust position (lower) .text("Three group sources") .attr("font-size", "19px") .attr("fill", "grey" ) }) var margin = {top: 10, right: 10, bottom: 10, left: 10}, width = 445 - margin.left - margin.right, height = 445 - margin.top - margin.bottom; // append the svg object to the body of the page var svg2 = d3.select("#my_dataviz2") .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 + ")"); // read json data d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_dendrogram_full.json", function(data) { // Give the data to this cluster layout: var root = d3.hierarchy(data).sum(function(d){ return d.value}) // Here the size of each leave is given in the 'value' field in input data // Then d3.treemap computes the position of each element of the hierarchy d3.treemap() .size([width, height]) .paddingTop(28) .paddingRight(7) .paddingInner(3) // Padding between each rectangle //.paddingOuter(6) //.padding(20) (root) // prepare a color scale var color = d3.scaleOrdinal() .domain(["source1", "source2", "source3"]) .range([ "#402D54", "#D18975", "#8FD175"]) // And a opacity scale var opacity = d3.scaleLinear() .domain([10, 30]) .range([.5,1]) // use this information to add rectangles: svg2 .selectAll("rect") .data(root.leaves()) .enter() .append("rect") .attr('x', function (d) { return d.x0; }) .attr('y', function (d) { return d.y0; }) .attr('width', function (d) { return d.x1 - d.x0; }) .attr('height', function (d) { return d.y1 - d.y0; }) .style("stroke", "black") .style("fill", function(d){ return color(d.parent.data.name)} ) .style("opacity", function(d){ return opacity(d.data.value)}) // and to add the text labels svg2 .selectAll("text") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+20}) // +20 to adjust position (lower) .text(function(d){ return d.data.name.replace('mister_','') }) .attr("font-size", "19px") .attr("fill", "white") // and to add the text labels svg2 .selectAll("vals") .data(root.leaves()) .enter() .append("text") .attr("x", function(d){ return d.x0+5}) // +10 to adjust position (more right) .attr("y", function(d){ return d.y0+35}) // +20 to adjust position (lower) .text(function(d){ return d.data.value }) .attr("font-size", "11px") .attr("fill", "white") // Add title for the 3 groups svg2 .selectAll("titles") .data(root.descendants().filter(function(d){return d.depth==1})) .enter() .append("text") .attr("x", function(d){ return d.x0}) .attr("y", function(d){ return d.y0+21}) .text(function(d){ return d.data.name }) .attr("font-size", "19px") .attr("fill", function(d){ return color(d.data.name)} ) // Add title for the 3 groups svg2 .append("text") .attr("x", 0) .attr("y", 14) // +20 to adjust position (lower) .text("Three group sources") .attr("font-size", "19px") .attr("fill", "grey" ) }) .dataviz { display: inline-block; } <script src="https://d3js.org/d3.v4.js"></script> <div> <div class="dataviz" id="my_dataviz1"></div> <div class="dataviz" id="my_dataviz2"></div> </div>
D3.js how to add grid boxes for value ranges
I'm trying to find a way to add grid boxes to my D3.js scatterplot. The boxes should have a certain color depending on in which value range they reside. For example the box that is between x value 0-20 and y value 0-20 should be green. What I have now: What I want - Illustration: I know that I could add a background image for the svg, but that doesn't seem to be a viable solution. My code so far: var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 1200 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; // setup x var xValue = function(d) { return d.Impact;}, // data -> value xScale = d3.scale.linear().range([0, width]), // value -> display xMap = function(d) { return xScale(xValue(d));}, // data -> display xAxis = d3.svg.axis().scale(xScale).orient("bottom"); // setup y var yValue = function(d) { return d.Likelihood;}, // data -> value yScale = d3.scale.linear().range([height, 0]), // value -> display yMap = function(d) { return yScale(yValue(d));}, // data -> display yAxis = d3.svg.axis().scale(yScale).orient("left"); // setup fill color var cValue = function(d) { return d.Conf;}, color = d3.scale.category20(); // add the graph canvas to the body of the webpage var svg = d3.select("#chart").append("svg") .attr("width", width + margin.left + margin.right + 400) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // add the tooltip area to the webpage var tooltip = d3.select("#chart").append("div") .attr("class", "tooltip") .style("opacity", 0); // change string (from CSV) into number format data.forEach(function(d) { d,Impact = +d.Impact; d.Likelihood = +d.Likelihood; }); // don't want dots overlapping axis, so add in buffer to data domain xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]); yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]); // scales w/o extra padding xScale.domain([d3.min(data, xValue), d3.max(data, xValue)]); yScale.domain([d3.min(data, yValue), d3.max(data, yValue)]); // x-axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .attr("class", "grid") .append("text") .attr("class", "label") .attr("x", width) .attr("y", -6) .style("text-anchor", "end") .text("Likelihood"); // y-axis svg.append("g") .attr("class", "y axis") .call(yAxis) .attr("class", "grid") .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Impact"); // draw dots svg.selectAll(".dot") .data(data) .enter().append("circle") .attr("class", "dot") .attr("r", 5.5) .attr("cx", xMap) .attr("cy", yMap) .style("fill", function(d) { return color(d.CategoryMain);}) .on("mouseover", function(d) { tooltip.transition() .duration(200) .style("opacity", .9); tooltip.html(d.CategoryMain + "<br/> " + d.CategorySub1 + "<br/>(" + xValue(d) + ", " + yValue(d) + ")") .style("left", (d3.event.pageX + 10) + "px") .style("top", (d3.event.pageY - 10) + "px"); }) .on("mouseout", function(d) { tooltip.transition() .duration(500) .style("opacity", 0); }); // draw legend var legend = svg.selectAll(".legend") .data(color.domain()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(160," + (i+7) * 20 + ")"; }); // draw legend colored rectangles legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", color); // draw legend text legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d;}) }) Any suggestions how this could be done?
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)");