line chart with mouseover tooltip is not working in d3.js - javascript

I've created a line chart using this http://bl.ocks.org/d3noob/6eb506b129f585ce5c8a code example. I've managed to recreate it.
that code is
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse,
formatDate = d3.time.format("%d-%b"),
bisectDate = d3.bisector(function(d) { return d.date; }).left;
// Set the ranges
// var x = d3.time.scale().range([0, width]);
var x = d3.scale.ordinal().rangePoints([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.interpolate('basis')
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var lineSvg = svg.append("g");
var focus = svg.append("g")
.style("display", "none");
// Get the data
var data = [
{
"date": "w1",
"close": 629.32
},
{
"date": "w2",
"close": 124.31
},
{
"date": "w3",
"close": 333.68
},
{
"date": "w4",
"close": 236.23
}
]
// data.forEach(function(d) {
// // d.date = parseDate(d.date);
// d.date = +d.date;
// d.close = +d.close;
// });
// Scale the range of the data
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// append the x line
focus.append("line")
.attr("class", "x")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("y1", 0)
.attr("y2", height);
// append the y line
focus.append("line")
.attr("class", "y")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("x1", width)
.attr("x2", width);
// append the circle at the intersection
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "blue")
.attr("r", 4);
// place the value at the intersection
focus.append("text")
.attr("class", "y1")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "-.3em");
focus.append("text")
.attr("class", "y2")
.attr("dx", 8)
.attr("dy", "-.3em");
// place the date at the intersection
focus.append("text")
.attr("class", "y3")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "1em");
focus.append("text")
.attr("class", "y4")
.attr("dx", 8)
.attr("dy", "1em");
// append the rectangle to capture mouse
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select("circle.y")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")");
focus.select("text.y1")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y2")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y3")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select("text.y4")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select(".x")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.attr("y2", height - y(d.close));
focus.select(".y")
.attr("transform",
"translate(" + width * -1 + "," +
y(d.close) + ")")
.attr("x2", width + width);
}
</script>
</body>
line is coming correctly but i m not able to set mouseover tooltip like above example..
I m facing error like invert fuction is not defined...

In the chart you linked to, he is using a time-scale for the x-axis (which has an invert-function). You are using an ordinal-scale (which do not have an invert-function).The invert-function is used to calculate the value on the x-axis for a given mouse-position.
A time-scale always has a corresponding x-value for each mouse-position (since it is continous, so no matter where your mouse is, you have a date-time for that position) while an ordinal scale does not have a corresponding x-value for all mouse-positions since it is discrete, i.e. what is the x-value when you have the mouse in-beteen for example w1 and w2?
So your solution would be to change to a time-scale (in which case you have to convert w1,w2,w3 e.t.c. to a date-time object).
Or, if you want to stick with your ordinal-scale, you have to remove the invert function. Since the invert-function is used to calculate the x-value for a given mouse-position, you have to create this logic by your self. Inspiration can be found in Inversion with ordinal scale. So replace var x0 = x.invert(d3.mouse(this)[0]) with
var xPos = d3.mouse(this)[0];
console.log("hovering at " + xPos);
var leftEdges = x.range();
var width = x.rangeBand();
var j;
for(j=0; xPos > (leftEdges[j] + width); j++) {}
//do nothing, just increment j until case fails
console.log("Clicked on " + x.domain()[j]);
var x0 = x.domain()[j];

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.

D3.js line chart with dates on x axes

I'm working on this line chart with d3.js .
I have a problem formatting the dates and as much I change the parseDate field, there is no way I can find to get for example "15 June".
If I change .tickformat in the x axis on %d I will just have "01 Oct" and not the exact date.
Here is the JS fiddle
http://jsfiddle.net/w0d4t1n5/
<script async src="//jsfiddle.net/w0d4t1n5/embed/"></script>
Thanks for your help!
If I understand, you want every datapoint's date displayed on the x axis, instead of just a time division.
For that, you need to create an ordinal scale and call that in the X axis:
fiddle is here:
http://jsfiddle.net/z94uzc0L/1/
var margin = {
top: 30,
right: 100,
bottom: 30,
left: 50
},
width = 365 - margin.left - margin.right,
height = 280 - margin.top - margin.bottom,
padding = 1;
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale()
.range([10, width - 15]);
//ordinal scale
var x2 = d3.scale.ordinal().rangePoints([0, width ], .25)
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis().scale(x2)
.orient("bottom")
.tickFormat(d3.time.format("%b %d"))
.ticks(4)
.tickPadding(2);
var yAxis = d3.svg.axis().scale(y)
.orient("left");
var valueline = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.trump);
});
var valueline2 = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.clinton);
});
//florida
var chart1 = d3.select("#florida")
.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 + ")");
//needed for the grid
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
}
data1 = [{
"date": "15-Jun-16",
"trump": 43.4,
"clinton": 44
}, {
"date": "15-Jul-16",
"trump": 43.4,
"clinton": 44
}, {
"date": "15-Aug-16",
"trump": 42,
"clinton": 45.6
}, {
"date": "15-Sep-16",
"trump": 45.1,
"clinton": 44.4
}, {
"date": "06-Oct-16",
"trump": 43.3,
"clinton": 46.2
}, {
"date": "10-Oct-16",
"trump": 49.3,
"clinton": 49.2
}];
var color = d3.scale.ordinal().range(["#004ecc", "#cc0000"]);
//d3.csv("data.csv", function(error, data) {
data1.forEach(function(d) {
d.date = parseDate(d.date);
d.trump = +d.trump;
d.clinton = +d.clinton;
});
// Scale the range of the data
x.domain(d3.extent(data1, function(d) {
return d.date;
}));
y.domain([36, 50]);
//update ordinal scale domain
x2.domain(data1.map(function(d) { return d.date; }));
//add the grid
chart1.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
)
chart1.append("path")
.attr("class", "line")
.attr("stroke", "red")
.attr("d", valueline(data1));
chart1.append("path")
.attr("class", "line2")
.attr("d", valueline2(data1));
// Add the X Axis
chart1.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
chart1.append("g")
.attr("class", "y axis")
.call(yAxis);
chart1.append("text")
.attr("transform", "translate(" + (width + 3) + "," + y(data1[0].clinton) + ")")
.attr("x", ".1em")
.attr("y", "-40")
.attr("text-anchor", "start")
.style("fill", "red")
.style("font-size", "15")
.style("font-weight", "bold")
.text("Clinton 46.2%");
chart1.append("text")
.attr("transform", "translate(" + (width + 3) + "," + y(data1[0].trump) + ")")
.attr("x", ".1em")
.attr("y", "10")
.attr("text-anchor", "start")
.style("fill", "steelblue")
.style("font-size", "15")
.style("font-weight", "bold")
.text("Trump 43.3%");
//plus 1: animation
var curtain = chart1.append('rect')
.attr('x', -1 * width)
.attr('y', -1 * height)
.attr('height', height)
.attr('width', width)
.attr('class', 'curtain')
.attr('transform', 'rotate(180)')
.style('fill', '#ffffff')
/* Optionally add a guideline */
var guideline = chart1.append('line')
.attr('stroke', '#333')
.attr('stroke-width', 0.4)
.attr('class', 'guide')
.attr('x1', 1)
.attr('y1', 1)
.attr('x2', 1)
.attr('y2', height)
var t = chart1.transition()
.delay(120)
.duration(500)
.ease('linear')
.each('end', function() {
d3.select('line.guide')
.transition()
.style('opacity', 0)
.remove()
});
t.select('rect.curtain')
.attr('width', 0);
t.select('line.guide')
.attr('transform', 'translate(' + width + ', 0)')
d3.select("#show_guideline").on("change", function(e) {
guideline.attr('stroke-width', this.checked ? 1 : 0);
curtain.attr("opacity", this.checked ? 0.75 : 1);
});

Plot multiple lines and scatter points on the same chart using d3, and use the mouseover function to calculate distance

I want to plot multiple lines and scatter plot on the same d3 chart.And I also define a mouse over function to calculate the distance between the scatter points and the line. Here is my js code:
import measurement from '../datasets/measurement';
// Parse the date / time
var parseDate = d3.time.format("%e/%_m/%Y %H");
// Get the data
d3.csv("../datasets/Book1.csv", function(error, data) {
data.forEach(function (d) {
d.date = parseDate.parse(d.dateHour);
d.estPressure = +d.x_inf;
d.lowPressure = +d.m1std;
d.upPressure = +d.p1std;
});
console.log(data);
// Set the dimensions of the canvas / graph
var margin = {top: 20, right: 50, bottom: 30, left: 66},
body_width = parseInt(d3.select('body').style('width').replace('px','')),
width = body_width - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Set the ranges
var x = d3.time.scale()
.domain([parseDate.parse("1/5/2016 00"), parseDate.parse("14/5/2016 23")])
// .domain(data.date])
.nice(d3.time.week)
/*.domain(data.map(function (d) {
return d.date;
}))*/
.range([0, width]);
//.rangeRoundBands([0, width], 0.1);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format('%B %e %H:00'));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("text")
.attr("x", 1780)
.attr("y", 940)// text label for the x axis
.style("text-anchor", "end")
.text("Time");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("pressure");
y.domain([0, d3.max(data, function (d) {
return d.upPressure;
})]);
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.estPressure);
});
// Draw line.
var linegraph = svg.selectAll("path.line").data([data], function (d) {
return d.date;
});
linegraph.attr('d', line).style("opacity", 1.0);
linegraph.enter().append("path")
.attr("class", "line")
.attr("d", line);
});
var data1 = measurement.map(function (d) {
Object.keys(d).forEach(function (key) {
d[key] = +d[key];
});
return d;
});
console.log(data1);
// Add the scatterplot
svg.selectAll(".dot")
.data(data1)
.enter().append("circle")
.attr("r", 4)
.attr("cx", function (d) {
return x(d.t);
})
.attr("cy", function (d) {
return y(d.est);
})
.on("mouseover", function (d) { //hover event
tooltip.transition()
.duration(100)
.style("opacity", .9)
.style("left", (d3.event.pageX + 20) + "px")
.style("top", (d3.event.pageY - 30) + "px");
var dist = 0, lowerbound;
data.forEach(function (n) {
if (n.t === d.t) {
dist = d.est - n.pressure ;
if (dist < 0) dist = dist * -1;
}
else if (n.time < d.t) { // linear interpolation for the t
lowerbound = n;
}
});
tooltip.html("<h1>" + "X: " + d.t + " Y: " + d.x + " distance:" + dist.toFixed(3) + "</h1>");
})
.on("mouseout", function (d) {
tooltip.transition()
.duration(200)
.style("opacity", 0);
});
And my csv data for the line chart is like this:
tHour,x_inf,p1std,m1std,dateHour
1,10,10.3,9.2,1/5/2016 00
2,12,16.8,7.2,1/5/2016 01
3,14,21.2,6.8,1/5/2016 02
4,15,19.8,10.2,1/5/2016 03
5,14.5,16.9,12.1,1/5/2016 04
6,18,22.96,13.04,1/5/2016 05
My jason data for the scatter points are like(measurement):
{
"t": 1,
"est": 1
},
{
"t": 3,
"est": 12
},
{
"t": 5,
"est": 14
},
{
Could anyone help me about the code? I am new to d3...And I just can plot only one line here using the dateHour as x and x_inf as y in the csv data. I want to use dateHour data as x and plot three lines using x_inf,p1std,m1std values. It would be so nice if you could also help me with the scatter points.

D3.js Mouseover and Focus + Context issue

I am new to D3.js
I've gone through some tutorials and have straight up jumped into my first project. I was hoping to combine the following with slight tweaks according to my needs. Currently I am having two issues
Focus+Context via Brushing
and
X-Value Mouseover
The Mouseover is wrongly displayed. It renders to the left of the chart. Could be a very small issue but I cant seem to find it.
I cant seem to figure out a way to display the "Safe Value" text outside the chart right next to the line. EDIT 2 - I've figured this out
Any help would be much appreciated.
Here is the CSS
body {
font: 10px sans-serif;
}
svg {
font: 10px sans-serif;
}
.line {
fill: none;
stroke: steelBlue;
stroke-width: 1.5px;
/*clip-path: url(#clip);*/
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.overlay {
fill: none;
pointer-events: all;
}
.xy circle {
fill: steelblue;
stroke: black;
}
JS
var margin = {top: 10, right: 15, bottom: 100, left: 60},
margin2 = {top: 430, right: 15, bottom: 20, left: 60},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%SZ").parse,
bisectDate = d3.bisector(function(d) { return d.date; }).left,
formatValue = d3.format(",.2f"),
formatData = function(d) { return formatValue(d) + " %"; };
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(d3.time.months, 1).tickFormat(d3.time.format("%m/%y")),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom").ticks(d3.time.months, 1).tickFormat(d3.time.format("%m/%y")),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
var line2 = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x2(d.date); })
.y(function(d) { return y2(d.value); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("data.csv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
data.sort(function(a, b) {
return a.date - b.date;
});
x.domain(d3.extent(data.map(function(d) { return d.date; })));
y.domain([0, d3.max(data.map(function(d) { return d.value; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
focus.append("line")
.attr("x1",x(data[0].date))
.attr("y1",y(83))
.attr("x2",x(data[data.length - 1].date))
.attr("y2",y(83))
.attr("stroke","orangered");
svg.append("text")
.attr("transform", "translate(" + (width+3) + "," + y(83) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "orangered")
.text(function(d) { return "Safe Value = 83" });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("x", 0)
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(-50,"+ height/2 + ") rotate(-90)")
.text("Dissolved Oxygen (%)");
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
var xy = svg.append("g")
.attr("class", "xy")
.style("display", "none");
xy.append("circle")
.attr("r", 4.5);
xy.append("text")
.attr("x", 9)
.attr("dy", ".35em");
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.on("mouseover", function() { xy.style("display", null); })
.on("mouseout", function() { xy.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
console.log(x0);
xy.attr("transform", "translate(" + x(d.date) + "," + y(d.value) + ")");
xy.select("text").text(formatData(d.value));
}
});
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".line").attr("d", line);
focus.select(".x.axis").call(xAxis);
}
Plunker Code
(Please refer to the code at Plunker, since I have updated a few things over there.) Thanks
Image1
Image2
For your problem #2, the code for the text is placing it out of the visible area. Just adjust your arguments to translate to something like the following:
.attr("transform", "translate(" + (width - 35) + ",30" + ")")
or something else that you prefer - note the minus on the x.

Mousmove animation for Tooltips

I'm learning D3 js and tried following example. Somehow I've managed it to a Single line chart by removing non required code.
http://bl.ocks.org/gniemetz/4618602
Now, I want to enhance this example a way that once user do brush on the smaller one chart, whatever range comes between the brush, it's line point should animate tool-tip on interval of some seconds. But I'm not able to get the start and end points of the brush.
Sorry for the long long code ....
var main_margin = {top: 20, right: 80, bottom: 100, left: 40},
mini_margin = {top: 430, right: 80, bottom: 20, left: 40},
main_width = 960 - main_margin.left - main_margin.right,
main_height = 500 - main_margin.top - main_margin.bottom,
mini_height = 500 - mini_margin.top - mini_margin.bottom,
start = 0,
end = 100,
focus;
var formatDate = d3.time.format("%H:%M"),
parseDate = formatDate.parse,
bisectDate = d3.bisector(function(d) { return d.Uhrzeit; }).left,
formatOutput0 = function(d) { return formatDate(d.Uhrzeit) + " - " + d.Durchschn + " ms"; };
var main_x = d3.time.scale()
.range([0, main_width]),
mini_x = d3.time.scale()
.range([0, main_width]);
var main_y0 = d3.scale.sqrt()
.range([main_height, 0]),
mini_y0 = d3.scale.sqrt()
.range([mini_height, 0]);
var main_xAxis = d3.svg.axis()
.scale(main_x)
.tickFormat(d3.time.format("%H:%M"))
.orient("bottom"),
mini_xAxis = d3.svg.axis()
.scale(mini_x)
.tickFormat(d3.time.format("%H:%M"))
.orient("bottom");
var main_yAxisLeft = d3.svg.axis()
.scale(main_y0)
.orient("left");
var brush = d3.svg.brush()
.x(mini_x)
.on("brushstart",function(){
console.log(brush.extent()[0]);
})
.on("brush",brushMove)
.on("brushend", function(){
console.log(brush.extent()[1]);
});
var main_line0 = d3.svg.line()
.interpolate("cardinal")
.x(function(d) { return main_x(d.Uhrzeit); })
.y(function(d) { return main_y0(d.Durchschn); });
var mini_line0 = d3.svg.line()
.x(function(d) { return mini_x(d.Uhrzeit); })
.y(function(d) { return mini_y0(d.Durchschn); });
var svg = d3.select("body").append("svg")
.attr("width", main_width + main_margin.left + main_margin.right)
.attr("height", main_height + main_margin.top + main_margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", main_width)
.attr("height", main_height);
var main = svg.append("g")
.attr("transform", "translate(" + main_margin.left + "," + main_margin.top + ")");
var mini = svg.append("g")
.attr("transform", "translate(" + mini_margin.left + "," + mini_margin.top + ")");
d3.csv("data.txt", function(error, data) {
data.forEach(function(d) {
d.Uhrzeit = parseDate(d.Uhrzeit);
d.Durchschn = +d.Durchschn;
});
data.sort(function(a, b) {
return a.Uhrzeit - b.Uhrzeit;
});
main_x.domain([data[0].Uhrzeit, data[data.length - 1].Uhrzeit]);
main_y0.domain(d3.extent(data, function(d) { return d.Durchschn; }));
mini_x.domain(main_x.domain());
mini_y0.domain(main_y0.domain());
main.append("path")
.datum(data)
.attr("clip-path", "url(#clip)")
.attr("class", "line line0")
.attr("d", main_line0);
main.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + main_height + ")")
.call(main_xAxis);
main.append("g")
.attr("class", "y axis axisLeft")
.call(main_yAxisLeft)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Ø AWZ (ms)");
mini.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + mini_height + ")")
.call(main_xAxis);
mini.append("path")
.datum(data)
.attr("class", "line")
.attr("d", mini_line0);
mini.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", mini_height + 7);
focus = main.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("line")
.attr("class", "x")
.attr("y1", main_y0(0) - 6)
.attr("y2", main_y0(0) + 6)
focus.append("line")
.attr("class", "y0")
.attr("x1", main_width - 6) // nach links
.attr("x2", main_width + 6); // nach rechts
focus.append("circle")
.attr("class", "y0")
.attr("r", 4);
focus.append("text")
.attr("class", "y0")
.attr("dy", "-1em");
main.append("rect")
.attr("class", "overlay")
.attr("width", main_width)
.attr("height", main_height)
.on("mouseover", showToolTip)
.on("mouseout", hideToolTip)
.on("mousemove", mousemove);
function mousemove() {
var x0 = main_x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.Uhrzeit > d1.Uhrzeit - x0 ? i : (i-1);
showToolTipForIndex(d);
}
function showToolTipForIndex(i){
var d = data[i];
focus.select("circle.y0").attr("transform", "translate(" + main_x(d.Uhrzeit) + "," + main_y0(d.Durchschn) + ")");
focus.select("text.y0").attr("transform", "translate(" + main_x(d.Uhrzeit) + "," + main_y0(d.Durchschn) + ")").text(formatOutput0(d));
focus.select(".x").attr("transform", "translate(" + main_x(d.Uhrzeit) + ",0)");
focus.select(".y0").attr("transform", "translate(" + main_width * -1 + ", " + main_y0(d.Durchschn) + ")").attr("x2", main_width + main_x(d.Uhrzeit));
}
// set default brush on mini xAxis
defaultBrush(data,start,end);
// bind event listeners
document.getElementById('play').addEventListener('click',function(){
if( !brush.empty() ){
// here I want to get brush's start and end points.. I mean the range
}
});
});
function showToolTip(){
focus.style("display", null);
}
function hideToolTip(){
focus.style("display", "none");
}
function defaultBrush(data,start,end){
svg.select(".x.brush").call(brush.extent([data[start].Uhrzeit,data[end].Uhrzeit]));
main_x.domain([data[start].Uhrzeit,data[end].Uhrzeit]);
main.select(".line0").attr("d", main_line0);
main.select(".x.axis").call(main_xAxis);
}
function brushMove() {
main_x.domain(brush.empty() ? mini_x.domain() : brush.extent());
main.select(".line0").attr("d", main_line0);
main.select(".x.axis").call(main_xAxis);
}
function brushStart(){
}
function brushEnd(){
}
});
The start and end points of the selected region are contained in brush.extent(). This function returns an array of two points, start and end. So if you wanted to get start and end x coordinates, you would do something like this.
var extent = brush.extent(),
start = extent[0][0],
end = extent[1][0];

Categories

Resources