The lines of my chart are drawing off my chart. I've tried to replace this code:
yE.domain(d3.extent(data, function(E) { return E.close;}));
With this:
yE.domain([0,d3.max(data, function(E) {
return Math.max(E.close, E.Map1, EMap2, E.MapII);
})]);
Based on the answer from Bill: d3.js: dataset array w/ multiple y-axis values
Mine doesn't work.
My entire code:
var marginE = {top: 30, right: 20, bottom: 30, left: 50},
widthE = 400 - marginE.left - marginE.right,
heightE = 270 - marginE.top - marginE.bottom;
// Parse the date / time
var parseDateTimeE = d3.time.format("%Y-%m-%d%H:%M").parse;
// Set the ranges
var xE = d3.time.scale().range([0, widthE]);
var yE = d3.scale.linear().range([heightE, 0]);
// Define the axEs
var xAxisE = d3.svg.axis().scale(xE)
.orient("bottom").ticks(6);
var yAxisE = d3.svg.axis().scale(yE)
.orient("left").ticks(6);
var areaE = d3.svg.area()
.interpolate("bundle")
.x(function(e) { return xE(e.date); })
.y0(heightE)
.y1(function(e) { return yE(e.close); });
// Adds the svg canvas
var svgE = d3.select(".eur")
.append("svg")
.attr("width", widthE + marginE.left + marginE.right)
.attr("height", heightE + marginE.top + marginE.bottom)
.attr('id', 'charteur')
.attr('viewBox', '0 0 400 270')
.attr('perserveAspectRatio', 'xMinYMid')
.append("g")
.attr("transform",'translate(' + marginE.left + ',' + marginE.top + ')')
.attr('width', widthE)
.attr('height', heightE)
.style("font-size","12px");
// Get the data
d3.json("php/downl_EUR.php", function(error, data) {
data.forEach(function(E) {
E.date = parseDateTimeE(E.date +E.time);
E.close = +E.close;
E.MaP1 = +E.MaP1;
E.MaP2 = +E.MaP2;
E.MaPII = +E.MaPII; });
// Define the line
var valuelineE = d3.svg.line()
.interpolate("bundle")
.x(function(E) { return xE(E.date); })
.y(function(E) { return yE(E.close); });
var valuelineE2 = d3.svg.line()
.interpolate("bundle")
.x(function(E) { return xE(E.date); })
.y(function(E) { return yE(E.MaP1); });
var valuelineE3 = d3.svg.line()
.interpolate("bundle")
.x(function(E) { return xE(E.date); })
.y(function(E) { return yE(E.MaP2); });
var valuelineE4 = d3.svg.line()
.interpolate("bundle")
.x(function(E) { return xE(E.date); })
.y(function(E) { return yE(E.MaPII); });
// Scale the range of the data
xE.domain(d3.extent(data, function(E) { return E.date; }));
yE.domain(d3.extent(data, function(E) { return E.close;})); //****
//yE.domain([0,d3.max(data, function(E) {return Math.max(E.close, E.MapII);})]); ****
svgE.append("path")
.datum(data)
.attr("class", "area")
.attr("d", areaE);
// Add the valueline path.
svgE.append("path")
.attr("class", "lineE")
.style("stroke", "steelblue")
.attr("d", valuelineE(data));
svgE.append("path")
.attr("class", "lineE")
.style("stroke", "red")
.attr("d", valuelineE2(data));
svgE.append("path")
.attr("class", "lineE")
.style("stroke", "green")
.attr("d", valuelineE3(data));
svgE.append("path")
.attr("class", "lineE")
.style("stroke-dasharray", ("3, 3"))
.attr("d", valuelineE4(data));
// Add the X Axis
svgE.append("g")
.attr("class", "XaxisE")
.attr("transform", "translate(0," + heightE + ")")
.call(xAxisE);
// Add the Y Axis
svgE.append("g")
.attr("class", "YaxisE")
.call(yAxisE); });
I found the solution myself. Instead of MaP1, Map2 & MaPII, use map1, map2 and mapii -> no capital letters !! (also in the php-file)
Everything works fine now...
Related
I am trying to create a tooltip in a D3 map. (also using DC.js). The problem is that it seems that the DC chart (mexicoChart) which holds the map is above everything or it is not compatible with the following code
(Nothing happens after adding it):
var width = 960
var height = 500
var projection = d3.geo.mercator()
.scale(1200)
.center([-102.34034978813841, 24.012062015793]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("svg")
.append("g")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("width", 600);
var g = svg.append("g");
d3.json("static/geojson/mx_tj.json", function(error, mx) {
svg.selectAll("path")
.data(topojson.feature(mx, mx.objects.municipalities))
.enter().append("path")
.attr("d", d3.geo.path().projection(projection))
.attr("fill", "transparent")
.style("stroke", "#333")
.style("stroke-width", ".2px")
.attr("class", "muns");
g.selectAll("path")
.data(topojson.feature(mx, mx.objects.states))
.enter().append("path")
.attr("d", d3.geo.path().projection(projection))
.attr("fill", "transparent")
.style("stroke", "#333");
svg.append("g")
.attr("class", "muns")
.selectAll("path")
.data(topojson.feature(mx, mx.objects.municipalities))
.enter().append("path")
.attr("d", path)
.on("mouseover", function (d) {var tip = "<h3>" + d.properties.name + "</h3>";
tooltip.html(tip)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
tooltip.transition()
.duration(500)
.style("opacity", .7); })
.on("mouseout", function (d) { tooltip.transition()
.duration(500)
.style("opacity", 0);
});
});
This is the second part of the code where the DC Charts are:
queue()
.defer(d3.json, "/homicidios/projects")
.defer(d3.json, "static/geojson/municipios.json")
.await(makeGraphs);
function makeGraphs(error, projectsJson, mx) {
//Clean projectsJson data
var homicidiosProjects = projectsJson;
var dateFormat = d3.time.format("%Y-%m-%d %H:%M:%S");
homicidiosProjects.forEach(function(d) {
d["fecha"] = dateFormat.parse(d["fecha"]);
d["fecha"].setMinutes(0);
d["fecha"].setSeconds(0);
// d["no_muertos"] = +d["no_muertos"];
});
//Create a Crossfilter instance
var ndx = crossfilter(homicidiosProjects);
//Define Dimensions
var FechaDim = ndx.dimension(function(d) {
return d["fecha"];
});
var zonaDim = ndx.dimension(function(d) {
return d["entidad_federativa"];
});
var pobrezaDim = ndx.dimension(function(d) {
return d["marginacion"];
});
var MunDim = ndx.dimension(function(d) {
return d["CVE_MUN"];
});
var noMuertosDim = ndx.dimension(function(d) {
return d["no_muertos"];
});
//Calculate metrics
var numProjectsPorFecha = FechaDim.group();
var numProjectsPorZona = zonaDim.group();
var numProjectsPorPobreza = pobrezaDim.group();
var noMuertosPorMun = MunDim.group().reduceSum(function(d) {
return d["no_muertos"];
});
var all = ndx.groupAll();
var noMuertos = ndx.groupAll().reduceSum(function(d) {
return d["no_muertos"];
});
var max_mun = noMuertosPorMun.top(1)[0].value;
//Define values (to be used in charts)
var minDate = FechaDim.bottom(1)[0]["fecha"];
var maxDate = FechaDim.top(1)[0]["fecha"];
//Charts
var timeChart = dc.barChart("#time-chart");
var zonaChart = dc.rowChart("#zona-row-chart");
var pobrezaChart = dc.rowChart("#pobreza-row-chart");
var mexicoChart = dc.geoChoroplethChart("#mexico-Chart");
var numberProjectsND = dc.numberDisplay("#number-projects-nd");
var noMuertosND = dc.numberDisplay("#no-muertos-nd");
numberProjectsND
.formatNumber(d3.format("d"))
.valueAccessor(function(d) {
return d;
})
.group(all);
noMuertosND
.formatNumber(d3.format("d"))
.valueAccessor(function(d) {
return d;
})
.group(noMuertos)
.formatNumber(d3.format(".3s"));
timeChart
.width(1000)
.height(180)
.margins({
top: 10,
right: 50,
bottom: 20,
left: 50
})
.dimension(FechaDim)
.group(numProjectsPorFecha)
.transitionDuration(500)
.x(d3.time.scale().domain([minDate, maxDate]))
.elasticY(true)
.xAxisLabel("Dia")
.yAxis().ticks(10);
zonaChart
.width(300)
.height(350)
.dimension(zonaDim)
.group(numProjectsPorZona)
.xAxis().ticks(4);
pobrezaChart
.width(300)
.height(250)
.dimension(pobrezaDim)
.group(numProjectsPorPobreza)
.xAxis().ticks(4);
d3.json("static/geojson/municipios.json", function (error, mx) {
mexicoChart.width(1000)
.height(630)
.dimension(MunDim)
.group(noMuertosPorMun)
.colors(["#FFE5EC", "#FFCCD9", "#FFB2C6", "#FF99B3", "#FF7FA0", "#FF668D", "#FF4C7A", "#FF3367", "#FF1954", "#FF0041"])
.colorDomain([0, max_mun])
.overlayGeoJson(mx.features, "municipio", function(d) {
return d.properties.CVE_MUN;
})
.projection(d3.geo.mercator()
.center([-101.45, 19.28])
.scale(1600)
.translate([490, 490]))
.title(function(p) {
return "State: " + p["key"] +
"\n" +
"Total Muertos: " + Math.round(p["value"]) + " $";
})
dc.renderAll();
});
}
I have this d3js code:
var tooltip = tooltipd3();
var svg = d3.select("svg#svg-day"),
margin = {
top: 20,
right: 30,
bottom: 30,
left: 25,
padding: 15
},
width = 700 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// parse the periodo / time
var parseTime = d3.timeParse("%Y-%m-%d");
// set the ranges
var x = d3.scaleTime().range([0, width - margin.padding]);
var y = d3.scaleLinear().range([height, 0]);
// define the area
var area = d3.area()
.x(function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.y0(height)
.y1(function(d) {
return y(d.guadagno);
});
// define the line
var valueline = d3.line()
.x(function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.y(function(d) {
return y(d.guadagno);
});
var div = d3.select("svg#svg-day")
.append("div") // declare the tooltip div
.attr("class", "tooltip") // apply the 'tooltip' class
.style("opacity", 0);
// get the data
d3.csv(base_url() + 'graph/getStatementsDaily/', function(error, data) {
if (error) throw error;
$('.graph-loading').hide();
// format the data
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
d.guadagno = +d.guadagno;
});
// scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.periodo;
}));
y.domain([0, d3.max(data, function(d) {
return d.guadagno + ((d.guadagno / 100) * 10); // 10% in più sulla scala numerica
})]);
// add the area
svg.append("path")
.data([data])
.attr("class", "area")
.attr("d", area);
// add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.periodo) + (margin.left + margin.padding);
})
.attr("cy", function(d) {
return y(d.guadagno);
})
.on('mouseover', function(d) {
var html = '<h5>' + d.guadagno + ' €</h5>';
tooltip.mouseover(html); // pass html content
})
.on('mousemove', tooltip.mousemove)
.on('mouseout', tooltip.mouseout);
// add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + (margin.left + margin.padding) + "," + (height) + ")")
//HERE IS THE DATES CODE
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")))
// add the Y Axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate (" + (margin.left + margin.padding) + " 0)")
.call(d3.axisLeft(y));
});
The dates care coming from a CSV file that has this format:
periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0
The result is fine with lots of dates, but with 7 dates I get duplicates as you can see here:
Why is this?? And how do I fix it?
This is something that bothers a lot of people new to D3: the ticks in the axis, specially when using a time scale, are automatically generated. In your case, given the date interval in your domain, it coincidentally ended up creating two ticks for each day. But pay attention to this: those ticks represent different times (hours) in the same day (you can see that if you remove the tickFormat in the axis generator).
Let's see your code generating the x axis:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0</pre>
As you can see, there are two ticks for each day (remember, for different hours).
Let's show that this is a coincidence: This is the same code, but changing the last date for 2017-05-20:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-20,0.0</pre>
Back to your code.
The solution is quite simple: using intervals. Let's set the interval for each tick:
d3.axisBottom(x).ticks(d3.timeDay)
Here is the same code with that change only:
var svg = d3.select("svg");
var data = d3.csvParse(d3.select("#csv").text());
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.periodo = parseTime(d.periodo)
});
var x = d3.scaleTime()
.range([20, 480])
.domain(d3.extent(data, function(d) {
return d.periodo;
}));
var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")).ticks(d3.timeDay)(svg.append("g").attr("transform", "translate(0,50)"));
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500"></svg>
<pre id="csv">periodo,guadagno
2017-05-08,0.0
2017-05-09,0.5385
2017-05-10,0.0
2017-05-11,0.0
2017-05-12,0.0
2017-05-13,0.5680
2017-05-14,0.0
2017-05-15,0.0</pre>
I have a line graph which looks fine. The data set is mostly random data with one big spike. The second dataset is just the log2 of each value. I can transition between the two and it looks great. The y axis is transitioning too. But the scale of the line is not transitioning. Not sure how to get the line to update with the right scale.
$(function() {
var margin = { top: 300, right: 100, bottom: 100, left: 100 },
width = 1400 - margin.right - margin.left,
height = 1080 - margin.top - margin.bottom;
var parseTime = d3.timeParse("%H:%M:%S");
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var log2y = d3.scaleLinear().range([height, 0]);
var valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
var log2valueline = d3.line()
.x(function (d) { return x(d.date); })
.y(function (d) { return y(Math.log2(d.value)); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.select("body").attr("align", "center");
d3.csv("data.csv", function (error, data) {
if (error) {
throw error;
}
var log2data = [];
var log10data = [];
data.forEach(function (d, index) {
d.date = parseTime(d.date);
d.value = +d.value;
log2data[index] = { "date": d.date, "value": Math.log2(+d.value) };
log10data[index] = { "date": d.date, "value": Math.log10(+d.value) };
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
log2y.domain([0, d3.max(log2data, function (d) { return d.value; }) ]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
svg.append("g")
.attr("class", "xaxis")
.attr("class", "chart")
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeMinute.every(10)));
var yaxis = svg.append("g")
.attr("class", "yaxis")
.attr("class", "chart")
.call(d3.axisLeft(y).ticks(5));
yaxis
.transition().duration(500).delay(2000)
.call(d3.axisLeft(log2y).ticks(4));
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", valueline);
});
});
So here is the chart before the transition:
And here is the chart after the transition:
Adding the update from Harpal, I see this:
It's because the new line is still using the old scale (valueline)
Change this:
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", valueline);
to this:
svg.selectAll("path")
.data([log2data])
.transition().duration(500).delay(2000)
.attr("d", log2valueline);
So the solution, as with so many things, is to go for a walk, get something to eat, and return with a fresh look. I rewrote it, based on what I learned thus far and have a working solution:
$(function () {
var margin = { top: 300, right: 100, bottom: 100, left: 100 },
winwidth = $(window).width(),
winheight = $(window).height(),
width = winwidth - margin.right - margin.left,
height = winheight - margin.top - margin.bottom,
x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]);
var parseTime = d3.timeParse("%H:%M:%S");
var valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
var svg = d3.select('body').append('svg')
.attr("width", winwidth)
.attr("height", winheight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var path = svg.append("path");
var xaxis = svg.append("g")
.attr("class", "xaxis")
.attr("class", "chart")
.attr("transform", "translate(0, " + height + ")");
var yaxis = svg.append("g")
.attr("class", "yaxis")
.attr("class", "chart");
function step1(sourcedata) {
var data = sourcedata.data;
var y = d3.scaleLinear().range([height, 0]);
y.domain([0, d3.max(data, function (d) { return Math.log2(d.value); })]);
valueline = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) { return x(d.date); })
.y(function (d) { return y(Math.log2(d.value)); });
path
.data([data])
.transition()
.attr("class", "line")
.attr("d", valueline);
yaxis
.transition()
.call(d3.axisLeft(y).ticks(4));
}
d3.select("body").attr("align", "center");
d3.csv("data.csv", function (error, data) {
if (error) {
throw error;
}
data.forEach(function (d) {
d.date = parseTime(d.date);
d.value = +d.value;
});
x.domain(d3.extent(data, function (d) { return d.date; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
path
.data([data])
.attr("class", "line")
.attr("d", valueline);
xaxis
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeMinute.every(10)));
yaxis.call(d3.axisLeft(y).ticks(5));
$("#rescale").click(data, step1);
});
});
And the graph works as follows:
I'm trying to get 2 completely different d3 charts (2 line charts but totally different data - one with several lines and negative data, other with one line positive data) on the same page.
Right now, I only get the first one to be generated and shown correctly on the HTML page, the second chart doesn't show at all (not even svg container is generated).
Here is my code:
(function() {
// Get the data
d3.json("../assets/js/json/temperature.json", function(data) {
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 25},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
// Set the ranges
var x = d3.time.scale().range([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()
.x(function(d) { return x(d.temps); })
.y(function(d) { return y(d.temperature); });
// prepare data
data.forEach(function(d) {
d.temps = parseDate(d.temps);
d.temperature = +d.temperature;
});
// Adds the svg canvas
var svg = d3.select("#graphTemp")
.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 + ")");
// Scale the range of the data on domain
x.domain(d3.extent(data, function(d) { return d.temps; }));
y.domain([0, d3.max(data, function(d) { return d.temperature; })]);
// Add the valueline path.
svg.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("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperatures");
});
})();
(function(){
// loads the data and loads it into chart - main function
d3.json("../assets/js/json/maitrise.json", function(data) {
var m = {top: 20, right: 5, bottom: 30, left: 40},
w = 70 - m.left - m.right,
h = 30 - m.top - m.bottom;
var x = d3.scale.linear().domain([0, data.length]).range([0 + m.left, w - m.right]);
var y = d3.scale.linear()
.rangeRound([h, 0]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) { return x(i); })
.y(function (d) { return y(d.value); });
var color = d3.scale.ordinal()
.range(["#28c6af","#ffd837","#e6443c","#9c8305","#d3c47c"]);
var svg2 = d3.select("#maitrisee").append("svg")
.attr("width", w + m.left + m.right)
.attr("height", h + m.top + m.bottom)
.append("g")
.attr("transform", "translate(" + m.left + "," + m.top + ")");
// prep axis variables
var xAxis2 = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis2 = d3.svg.axis()
.scale(y)
.orient("left");
//console.log("Inital Data", data);
var labelVar = 'id'; //A
var varNames = d3.keys(data[0])
.filter(function (key) { return key !== labelVar;}); //B
color.domain(varNames); //C
var seriesData = varNames.map(function (name) { //D
return {
name: name,
values: data.map(function (d) {
return {name: name, label: d[labelVar], value: +d[name]};
})
};
});
console.log("seriesData", seriesData);
y.domain([
d3.min(seriesData, function (c) {
return d3.min(c.values, function (d) { return d.value; });
}),
d3.max(seriesData, function (c) {
return d3.max(c.values, function (d) { return d.value; });
})
]);
var series = svg2.selectAll(".series")
.data(seriesData)
.enter().append("g")
.attr("class", function (d) { return d.name; });
series.append("path")
.attr("class", "line")
.attr("d", function (d) { return line(d.values); })
.style("stroke", function (d) { return color(d.name); })
.style("stroke-width", "2px")
.style("fill", "none");
});
})();
OK, I found where the error was coming from. There was a piece of javascript in the middle of the HTML page that stopped d3 to generate the second graph further down in the page.
Thanks for all the help!
I am having a problem with my code where the circle nodes that I have created do not seem to be appending themselves to the graph. The debugger isn't pulling up any errors, so it seems like it's a logic issue.
Here's what is looks like:
(dot)
|
|
|
|
|
| <--(where dot should be)
|
__________________________________________
^
|
graph
And here's my code:
<script>
var slider = $("#myRange").val();;
var xtwo;
var xone;
var xzero;
var firstx = -1;
var firsty = 1;
var secondx = 2;
var secondy = 4;
var lineData = [];
var nodes = [];
//updates coefficients
function updateXs() {
xtwo = (75 - slider) / 50;
xone = (slider - 25) / 50;
xzero = (slider - 25) / 25;
}
//gets corresponding y from x and coefficients
function getY(xval) {
return (xval * xval * xtwo + xval * xone + xzero);
}
function displayVals() {
document.getElementById("demo").innerHTML = slider + " " + xtwo + " " + xone + " " + xzero + " " + lineData;
}
function updateLineData() {
//resets and fills points
lineData = [];
for (i = (firstx - 1); i < (secondx + 2); i++) {
lineData.push({
x: i,
y: getY(i)
});
}
}
//makes dots for static points
function makeDots(xvalue, xvalue2) {
nodes = [{
x: xvalue,
y: getY(xvalue)
}, {
x: xvalue2,
y: getY(xvalue2)
}]
}
function makeLine() {}
$(document).ready(function() {
updateXs();
updateLineData();
displayVals();
var vis = d3.select('#visual'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y;
}), d3.max(lineData, function(d) {
return d.y;
})]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
})
.interpolate('basis');
vis.append("svg:path")
.attr("d", lineFunc(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none");
makeDots(firstx, secondx);
//puts in dots
vis.selectAll("circle.nodes")
.data(nodes)
.enter()
.append("circle")
.attr("cx", function(d) {
console.log(d.x)
return 200;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", "10px")
.attr("fill", "black")
//updates when slider changes
$("#myRange").change(function() {
slider = $("#myRange").val();
updateXs();
updateLineData();
displayVals();
});
});
</script>
Please help and thanks in advance. Also, I was wondering if I could get some tips on how to make the line move using the .change function
You haven't applied your scale function to your dots:
vis.selectAll(".nodes")
.data(nodes)
.enter().append("circle")
.attr("class", "nodes")
.attr("cx", function (d) {
return xRange(d.x); //<-- convert from user space to pixel space
})
.attr("cy", function (d) {
return yRange(d.y); //<-- convert from user space to pixel space
});
To make your line update, you need to select it and change the d attribute:
d3.select(".myLine") //<-- select it by some unique class
.attr("d", lineFunc(lineData)); //<-- update the d attribute
To get a smooth curve without interpolation, just supply more points. See udpated fiddle.
Fiddle here.