I have been working on an interactive line chart built using D3.js. One hover I would like a tool tip to be displayed with a vertical line. The vertical line comes out fine, however, I have problems related to the tool tip. The tool tip position is not on the graph and I am only getting the first data element.
Here is my code:
margin = {
top: 20,
right: 20,
bottom: 20,
left: 50
};
var width = Math.max(250, Math.min(700, d3.select("#content").width- margin.left - margin.right)),
height = 500;
var vis = d3.select("#line_chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
max_x = 0, max_y = 0, min = 100;
d3.csv("line.csv", function(error, data) {
for(i=0; i < data.length; i++){
max_y = Math.max(max_y, data[i].number);
max_x = Math.max(max_x, data[i].class);
min = Math.min(min, data[i].class);
}
xScale = d3.scale.linear().range([margin.left, width - margin.right]).domain([min, max_x]),
yScale = d3.scale.linear().range([height - margin.top, margin.bottom]).domain([0, max_y]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (margin.left) + ",0)")
.call(yAxis);
var lineGen = d3.svg.line()
.x(function(d) {
return xScale(d.class);
})
.y(function(d) {
return yScale(d.number);
})
.interpolate("basis");
var pth = vis.append('svg:path')
.attr('d', lineGen(data))
.attr('stroke', '#000')
.attr('stroke-width', 3.5)
.attr('fill', 'none');
var totalLength = pth.node().getTotalLength();
pth
.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2400)
.ease("linear")
.attr("stroke-dashoffset", 0);
//Line chart mouse over
var hoverLineGroup = vis.append("g")
.attr("class", "hover-line");
var hoverLine = hoverLineGroup
.append("line")
.attr("stroke", "#000")
.attr("x1", 10).attr("x2", 10)
.attr("y1", 0).attr("y2", height);
var hoverTT = hoverLineGroup.append('text')
.attr("class", "hover-tex capo")
.attr('dy', "0.35em");
var cle = hoverLineGroup.append("circle")
.attr("r", 4.5);
var hoverTT2 = hoverLineGroup.append('text')
.attr("class", "hover-text capo")
.attr('dy', "0.35em");
hoverLineGroup.style("opacity", 1e-6);
var rectHover = vis.append("rect")
.data(data)
.attr("class", "overlay")
.attr("width", width)
.attr("height", height);
rectHover
.on("mouseout", hoverMouseOff)
.on("mousemove", hoverMouseOn);
function hoverMouseOn(d) {
var mouse_x = d3.mouse(this)[0];
var mouse_y = d3.mouse(this)[1];
var graph_y = yScale.invert(mouse_y);
var graph_x = xScale.invert(mouse_x);
hoverTT.text("Marks: " + Math.round(graph_x * 100)/100);
hoverTT.attr('x', mouse_x + 10);
hoverTT.attr('y', yScale(d.class));
hoverTT2.text("Frequency: " + Math.round(d.number * 100)/100)
.attr('x', mouse_x + 10)
.attr('y', yScale(d.class) +15);
cle
.attr('x', mouse_x)
.attr('y', mouse_y);
hoverLine.attr("x1", mouse_x).attr("x2", mouse_x)
hoverLineGroup.style("opacity", 1);
}
function hoverMouseOff() {
hoverLineGroup.style("opacity", 1e-6);
};
});
}
The data:
class,number
25,1
30,7
35,11
45,13
50,21
55,23
60,30
65,41
75,39
80,24
85,14
90,4
95,8
100,2
I am not able to figure out what the issue is.
How can I solve this?
Thanks in advance.
EDIT: Here is the working code: https://jsfiddle.net/kan83q0m/1/
In your hoverMouseOn method, the variable d is undefined. You'll need to use d3.bisector to find the closest data point, like this:
var bisectDate = d3.bisector(function(d) { return d.class; }).left;
var mouseDate = xScale.invert(mouse_x);
var i = bisectDate(data, mouseDate);
var d0 = data[i - 1]
var d1 = data[i];
var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;
Also, I put the mousemove listener on 'vis' instead of 'rectHover':
vis
.on("mouseout", hoverMouseOff)
.on("mousemove", hoverMouseOn);
and used d.number instead of d.class for the y values. If you want the tooltip to always be on the line it gets a bit more complicated. Here's a working fiddle.
Might be easier to just put the tooltip at your mouse coordinates like in this fiddle.
Related
I am trying to get Zoom to work, I am new to D3 and I find it very abstract and not intuitive. I recently finished a beginners course in JavaScript but D3 feels like a completely new language.
I found this topic which might help a bit.
D3 Zooming in graph
I also found the following code that created the graph on the web, the simplest I could find and I don't understand all of it. Now I wanna zoom in and used code that I also found on the web but which has to be adapted. I understood that much that the zoom variable at the top is calling a function called NeuerChart which has the actual zooming behaviour in it. It needs to zoom the graph and the axes when I spin the mousewheel.
In the end I need to implement this into a real problem, thanks. Using D3.v5.
<script>
let zoom = d3.zoom()
.scaleExtent([0.5, 10])
.extent([[0, 0], [width, height]])
.on('zoom', NeuerChart);
// Step 1
let min = 0;
let max = 100;
let x_arr = [];
let y_arr = [];
let s_arr = [];
let z_arr = [];
for (let i = 0; i < 360; i++) {
var r = Math.round(Math.random() * (max - min)) + min;
x_arr[i]= i;
y_arr[i]= r;
z_arr.push([x_arr[i],y_arr[i]]);
}
s_arr = y_arr.sort(function(a, b){return a - b});
let neu_arr = [];
let zz_arr = [];
for (let i = 0; i < 360; i++) {
neu_arr[i]= i;
zz_arr.push([neu_arr[i], s_arr[i]]);
}
console.log(z_arr);
console.log(zz_arr);
var dataset1 = zz_arr;
// Step 3
var svg = d3.select("svg"),
margin = 200,
width = svg.attr("width") - margin, //1700
height = svg.attr("height") - margin //700
// Step 4
var xScale = d3.scaleLinear().domain([0 , 365]).range([0, width]),
yScale = d3.scaleLinear().domain([0, 105]).range([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + 100 + "," + 100 + ")");
// Step 5
// Title
svg.append('text')
.attr('x', width/2 + 100)
.attr('y', 100)
.attr('text-anchor', 'middle')
.style('font-family', 'Helvetica')
.style('font-size', 20)
.text('Line Chart');
// X label
svg.append('text')
.attr('x', width/2 + 100)
.attr('y', height - 15 + 150)
.attr('text-anchor', 'middle')
.style('font-family', 'Helvetica')
.style('font-size', 12)
.text('Zeitachse');
// Y label
svg.append('text')
.attr('text-anchor', 'middle')
.attr('transform', 'translate(60,' + 500 + ')rotate(-90)')
.style('font-family', 'Helvetica')
.style('font-size', 12)
.text('Wert');
// Step 6
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale).ticks(7).tickValues([0, 60, 120, 180, 240, 300, 360]));
g.append("g")
.call(d3.axisLeft(yScale));
// Step 7
svg.append('g')
.selectAll("dot")
.data(dataset1)
.enter()
.append("circle")
.attr("cx", function (d) { return xScale(d[0]); } )
.attr("cy", function (d) { return yScale(d[1]); } )
.attr("r", 3)
.attr("transform", "translate(" + 100 + "," + 100 + ")")
.style("fill", "#CC0000");
// Step 8
var line = d3.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); })
.curve(d3.curveMonotoneX)
svg.append("path")
.datum(dataset1)
.attr("class", "line")
.attr("transform", "translate(" + 100 + "," + 100 + ")")
.attr("d", line)
.style("fill", "none")
.style("stroke", "#CC0000")
.style("stroke-width", "2")
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.attr("transform", "translate(" + 100 + "," + 100 + ")")
.call(zoom);
function NeuerChart () {
// recover the new scale
var newX = d3.event.transform.rescaleX(xScale);
var newY = d3.event.transform.rescaleY(yScale);
// update axes with these new boundaries
xAxis.call(d3.axisBottom(newX))
yAxis.call(d3.axisLeft(newY))
}
</script>
I added the code here in Codepen:
https://codepen.io/Dvdscot/pen/zYjpzVP
This is how it should work:
https://codepen.io/Dvdscot/pen/BaxJdKN
Problem is solved, see the code at Codepen:
`
Reset zoom
`https://codepen.io/Dvdscot/pen/zYjpzVP
edited to include code where cell is defined
I am attempting to create a chart that pulls data from an XHR request, but d is undefined in certain functions in my script:
var svg = d3.select("svg"),
margin = {top: 30, right: 40, bottom: 60, left: 40},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
var formatValue = d3.format(",d");
var x = d3.scaleTime()
//var x = d3.scaleLinear()
.domain([new Date(2017, 0, 1), new Date(2020, 11, 31)])
//.rangeRound([0, width]);
.range([0, width-300]);
/*var xScale = d3.scaleTime()
.domain([new Date(2018, 0, 1), new Date(2020, 11, 31)])
.range([50, 1150]);*/
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//variables for legends
var legendRectSize = 18;
var legendSpacing = 4;
d3.request("https://api.parliament.uk/sparql?query=PREFIX%20rdfs%3A%20%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0APREFIX%20%3A%20%3Chttps%3A%2F%2Fid.parliament.uk%2Fschema%2F%3E%0APREFIX%20id%3A%20%3Chttps%3A%2F%2Fid.parliament.uk%2F%3E%0Aselect%20%3FTreaty%20%3FTreatyname%20%3FLeadOrg%20%3FSeries%20%3FLink%20%3FworkPackage%20%3FprocStepName%20%3Fdate%20where%20%7B%0A%20%3FTreaty%20a%20%3ATreaty%20.%20%20%0A%20%20%20%20%20%3FTreaty%20rdfs%3Alabel%20%3FTreatyname%20.%0A%20%20OPTIONAL%7B%20%3FTreaty%20%3AtreatyHasLeadGovernmentOrganisation%2F%20rdfs%3Alabel%20%3FLeadOrg%20.%7D%20%0A%20%20OPTIONAL%20%7B%3FTreaty%20%3AtreatyHasSeriesMembership%2F%20%3AseriesItemCitation%20%3FSeries.%7D%0A%20%20OPTIONAL%20%7B%3FTreaty%20%3AworkPackagedThingHasWorkPackagedThingWebLink%20%3FLink.%7D%0A%09%3FTreaty%20%3AworkPackagedThingHasWorkPackage%20%3FworkPackage%20.%0A%20%20%09%3FworkPackage%20%3AworkPackageHasProcedure%2Frdfs%3Alabel%20%3Fproc%0A%20%20FILTER(%3Fproc%20IN%20(%22Treaties%20subject%20to%20the%20Constitutional%20Reform%20and%20Governance%20Act%202010%22))%0A%20%20%20%3FworkPackage%20%3AworkPackageHasBusinessItem%20%3FprocStep%20.%0A%20%20%20%20%20%3FprocStep%20%3AbusinessItemDate%20%3Fdate%20.%0A%20%20%3FprocStep%20%3AbusinessItemHasProcedureStep%20id%3Acspzmb6w%20.%0A%20%20%3FprocStep%20%3AbusinessItemHasProcedureStep%2Frdfs%3Alabel%20%3FprocStepName.%20%0A%20%20%20%20%0A%20%20%20%7D%0A")
.mimeType('application/sparql-results+json')
.response(function(xhr) { return JSON.parse(xhr.responseText); })
.get(function(data) {
console.log(data);
var data1 = data.results.bindings;
//if (error) alert(error);
data1.forEach(function(d){
d.datetrimmed = d.date.value.split('+')[0];
console.log(d.datetrimmed)
d.Date1 = Date.parse(d.datetrimmed)
console.log(d.Date1)
d.Date2 = d3.timeMonth(d.Date1)
console.log(d.Date2)
console.log(d.LeadOrg.value)
})
x.domain(d3.extent(data.results.bindings, function(d) { return d.Date2; }));
var myColor = d3.scaleOrdinal()
.range(['#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231', '#911eb4', '#46f0f0', '#f032e6', '#bcf60c', '#fabebe', 'red', '#e6beff', '#9a6324', '#fffac8', '#800000']);
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(function(d) { return x(d.Date2); }).strength(1))
.force("y", d3.forceY(height / 2))
.force("collide", d3.forceCollide(14))
.stop();
for (var i = 0; i < 120; ++i) simulation.tick();
g.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 5))
.attr("text-anchor", "middle")
.style("font-size", "24px")
.style("font-family", "Tahoma")
.style("text-decoration", "underline")
.style("fill", "#f2f0f7")
.text("All Treaties Subject to CRAG 2010 by Lead Organisation");
g.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top - 45))
.attr("text-anchor", "middle")
.style("font-size", "12px")
.style("font-family", "Tahoma")
.style("fill", "#f2f0f7")
.text("Click a point on the chart or hover over a square on the legend to highlight all treaties from a given department");
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(20));
g.append("text")
.attr("transform",
"translate(" + (width/2-100) + " ," +
(height + margin.top + 10) + ")")
.style("text-anchor", "middle")
.style("font-size", "14px")
.style("font-family", "Tahoma")
.style("fill", "#f2f0f7")
.text("Date the treaty was laid before the House of Commons");
var cell = g.append("g")
.attr("class", "cells")
.selectAll("g").data(d3.voronoi()
.extent([[-margin.left, -margin.top], [width + margin.right, height + margin.top]])
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.polygons(data1)).enter().append("g");
The error occurs at this point further in, where it says that it cannot read property data of undefined:
cell.append("circle")
.attr("class", function(d){
console.log(d)
org = d.data.results.bindings.LeadOrg.value;
return org.replace(/[\s,]/g,'') })
Is there a way I should be defining d further in to the code?
This part of the code is still within the get request from the d3.request function. Is this going to cause problems?
Any help would be appreciated.
You never pass the data from cell to "circle". To do that, consider the following:
cell.append("circle")
.datum(function(d) { return d; })
.attr("class", function(d){
console.log(d)
org = d.data.results.bindings.LeadOrg.value;
return org.replace(/[\s,]/g,'') })
This takes the object d you assigned to cell, and returns it as the data object to assign to the circle as well.
Note that .datum is very related to .data, except that it expects one singular value, not an array of values.
i have plotted dynamic waves based on randomly generated data in d3.js. I am using "dot" (svg.selectAll("dot")) element to represent the data point(x and y axis) on the waves. Based on setinterval method my data is getting updated every 200ms and i am transforming the data from right to left. But the data points(dots) that i added to the waves are not moving along with the waves, they are fixed(not moving) and only waves are moving.
here's the code:
https://jsfiddle.net/rajatmehta/tm5166e1/4/
function updateData() {
var newData = GenData(N,lastUpdateTime);
lastUpdateTime = newData[newData.length-1].timestamp;
var newData2 = GenData2(N,lastUpdateTimeNew);
lastUpdateTimeNew = newData2[newData2.length-1].timestamp;
for (var i=0; i<newData.length; i++){
console.log(globalData.length);
if(globalData.length>99){
globalData.shift();
}
globalData.push(newData[i]);
}
for (var i=0; i<newData2.length; i++){
console.log(globalDataNew.length);
if(globalDataNew.length>99){
globalDataNew.shift();
}
globalDataNew.push(newData2[i]);
}
//code for transition start
x1 = newData[0].timestamp;
x2 = newData[newData.length - 1].timestamp;
dx = dx + (x(x1) - x(x2)); // dx needs to be cummulative
x1New = newData2[0].timestamp;
x2New = newData2[newData2.length - 1].timestamp;
dxNew = dxNew + (x(x1New) - x(x2New)); // dx needs to be cummulative
d3.select("path#path1")
.datum(globalData)
.attr("class", "line")
.attr("d", valueline(globalData))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.select("path#path2")
.datum(globalDataNew)
.attr("class", "line")
.attr("d", valueline2(globalDataNew))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dxNew) + ")");
svg.select(".x.axis").call(xAxis);
}
I am new to d3.js, so dont have much idea about this.
Two problems:
You are not appending the circles correctly: you cannot append a <circle> element to a <path>element. You have to use an "enter" selection, appending them to the SVG (or a group element):
chartBody.selectAll(null)
.data(globalData)
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
console.log(d)
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
In the update function, select those circles by class:
d3.selectAll(".dot1")
.data(globalData)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
Here is your code with those changes:
var lastUpdateTime = +new Date();
var lastUpdateTimeNew = +new Date();
var GenData = function(N, lastTime) {
var output = [];
for (var i = 0; i < N; i++) {
output.push({
value: Math.random() * 10,
timestamp: lastTime
});
lastTime = lastTime + 1000;
}
return output;
}
var GenData2 = function(N, lastTime) {
var output = [];
for (var i = 0; i < N; i++) {
output.push({
value: Math.random() * 20,
timestamp: lastTime
});
lastTime = lastTime + 1000;
}
return output;
}
var globalData;
var globalDataNew;
// plot the original data by retrieving everything from time 0
data = GenData(50, lastUpdateTime);
dataNew = GenData2(50, lastUpdateTimeNew);
lastUpdateTime = data[data.length - 1].timestamp;
lastUpdateTimeNew = dataNew[dataNew.length - 1].timestamp;
globalData = data;
globalDataNew = dataNew;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var margin = {
top: 30,
right: 20,
bottom: 30,
left: 50
},
width = 800 - margin.left - margin.right,
height = 350 - margin.top - margin.bottom;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
x.domain(d3.extent(globalDataNew, function(d) {
return d.timestamp;
}));
y.domain(d3.extent(globalDataNew, function(d) {
return d.value;
}));
var xAxis = d3.svg.axis().scale(x)
.orient("bottom")
.ticks(d3.time.seconds, 20)
.tickFormat(d3.time.format('%X'))
.tickSize(5)
.tickPadding(8);
var xAxisTop = d3.svg.axis().scale(x)
.orient("bottom").tickFormat("").tickSize(0);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var yAxisRight = d3.svg.axis().scale(y)
.orient("right").tickFormat("").tickSize(0);
var valueline = d3.svg.line()
.x(function(d) {
return x(d.timestamp);
})
.y(function(d) {
return y(d.value);
});
var valueline2 = d3.svg.line()
.x(function(d) {
return x(d.timestamp);
})
.y(function(d) {
return y(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 + ")");
svg.append("rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var clip = svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
/* .on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(formatTime(d.timestamp) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
})*/
chartBody.append("path") // Add the valueline path
.datum(globalData)
.attr("id", "path1")
.attr("class", "line")
.attr("d", valueline);
chartBody.selectAll(null)
.data(globalData)
.enter()
.append("circle")
.attr("class", "dot1")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.selectAll(null)
.data(globalDataNew)
.enter()
.append("circle")
.attr("class", "dot2")
.attr("r", 3)
.attr("cx", function(d) {
return x(d.timestamp);
})
.attr("cy", function(d) {
return y(d.value);
});
chartBody.append("path") // Add the valueline path
.datum(globalDataNew)
.attr("id", "path2")
.attr("class", "line")
.attr("d", valueline2);
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)")
.call(yAxisRight);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + String(0) + ")")
.call(xAxisTop);
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", (0 - (height / 2)))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("font-weight", "bold")
.text("Return (%)");
var inter = setInterval(function() {
updateData();
}, 1000);
//////////////////////////////////////////////////////////////
var N = 3;
var dx = 0;
var dxNew = 0;
function updateData() {
var newData = GenData(N, lastUpdateTime);
lastUpdateTime = newData[newData.length - 1].timestamp;
var newData2 = GenData2(N, lastUpdateTimeNew);
lastUpdateTimeNew = newData2[newData2.length - 1].timestamp;
for (var i = 0; i < newData.length; i++) {
if (globalData.length > 99) {
globalData.shift();
}
globalData.push(newData[i]);
}
for (var i = 0; i < newData2.length; i++) {
if (globalDataNew.length > 99) {
globalDataNew.shift();
}
globalDataNew.push(newData2[i]);
}
//code for transition start
x1 = newData[0].timestamp;
x2 = newData[newData.length - 1].timestamp;
dx = dx + (x(x1) - x(x2)); // dx needs to be cummulative
x1New = newData2[0].timestamp;
x2New = newData2[newData2.length - 1].timestamp;
dxNew = dxNew + (x(x1New) - x(x2New)); // dx needs to be cummulative
d3.select("path#path1")
.datum(globalData)
.attr("class", "line")
.attr("d", valueline(globalData))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.select("path#path2")
.datum(globalDataNew)
.attr("class", "line")
.attr("d", valueline2(globalDataNew))
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dxNew) + ")");
d3.selectAll(".dot1")
.data(globalData)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
d3.selectAll(".dot2")
.data(globalDataNew)
.transition()
.ease("linear")
.attr("transform", "translate(" + String(dx) + ")");
svg.select(".x.axis").call(xAxis);
}
body {
font: 12px Arial;
}
path {
stroke: black;
stroke-width: 1;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: black;
stroke-width: 2;
shape-rendering: crispEdges;
}
text {
fill: black;
}
rect {
fill: #add8e6;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
PS: You have to append new circles as the lines move to the left. However, this is another issue.
I ma shifting the X-Axis to bottom, it is not visible and only coming when its on the bar chart. There is some svg area problem which I ma not able to find out. how to shift the barchart a bit upwards so that X=Axis labeling could be accommodated.
Here is the fiddle link Working but X-Axis Label is on the Top
a = 100;
b = 150;
c = 103;
dataset= [a,b,c];
var w = 500;
var h = 250;
var barPadding = 1;
var marginleft = 1;
var margintop =1;
var marginbottom =15;
margin = {top:1, right:10, bottom:1, left:1};
colors = ["#e41a1c", "#377eb8", "#4daf4a"];
h = h ;
var category= ['A', 'B', 'C'];
var x = d3.scale.ordinal()
.domain(category)
.rangeRoundBands([0, w]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(0);;
//Create SVG element
var svg = d3.select("#hello")
.append("svg")
.attr("width", w )
.attr("height", h )
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
// GENERATING RECTANGLES AND MAKING BAR CHART
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return i * (w / dataset.length);
})
.attr("y", function(d) {
return h - (d*1.5) ;
})
.attr("width", w / dataset.length - barPadding)
.attr("height", function(d) {
return (d*2 );
})
.attr("fill", function(d,i) {
return colors[i];
// .attr("fill", function(d) {
// return "rgb(0, 0, " + (d * 10) + ")";
});
var x_Axis = svg.append('g')
.attr('class','xnewaxis')
.attr("transform", "translate(0," + (20) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "start")
.attr("dx", "-2.5em")
.attr("dy", ".5em")
.attr("transform", "rotate(-15)" );
Your code has several problems:
two different datasets for the bars;
lacks an ordinal scale for positioning the bars (actually, there is one, which you don't use);
lacks a linear scale for the bars values;
calls xAxis twice, with different translations;
But, for solving the axis problem, you just need to translate it correctly:
var x_Axis = svg.append('g')
.attr('class','xnewaxis')
.attr("transform", "translate(0," + (h- 30) + ")")
//30 here is the padding from the bottom of the SVG
Here is your fiddle: https://jsfiddle.net/gfwo0br9/
The bars are still showing up behind the axis (actually, the bars are going way below the end of the SVG itself). To fix that, you'll have to draw the bars properly (with a scale setting the range and the domains).
I have some pretty simple code to plot a time series line graph. The x-scale is rendered correctly, however the line is not being rendered.
I am pretty sure that the issue we are facing here is with my function for calculating the x axis value, but I can't see what I might be doing wrong
My code for the graph is similar to this:
var data = getData();
var graph;
var line;
function getData() {
var theDate = new Date(2012, 01, 01, 0, 0, 0, 0);
var arr = [];
for (var x = 0; x < 30; x++) {
arr.push([theDate.getTime(), rand(100)]);
theDate.setDate(theDate.getDate() + 1);
}
return arr;
}
function rand(max) {
return Math.floor(Math.random() * (max + 1))
}
var m = [80, 80, 80, 80]; // margins
var w = 1000 - m[1] - m[3]; // width
var h = 400 - m[0] - m[2]; // height
// pretty sure the issue is which this line
var x = d3.time.scale().domain([new Date(data[0][0]), new Date(data[data.length - 1][0])]).range([0, w]);
var y = d3.scale.linear().domain([0, 100]).range([h, 0]);
line = d3.svg.line()
.x(function (d, i) { return x(new Date(d[0])); })
.y(function (d) { return y(d[1]); })
.interpolate("linear")
graph = d3.select("#graph").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
var xAxis = d3.svg.axis().scale(x).ticks(d3.time.days, 1).tickFormat(d3.time.format("%d"));
graph.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
var yAxisLeft = d3.svg.axis().scale(y).ticks(10).orient("left");
graph.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(0,0)") //positon of the y axis
.call(yAxisLeft);
graph.append("svg:path")
.data([data])
.attr("class", "line")
.attr("transform", "translate(" + x(1) + ")")
.attr("d", line)
.transition()
.duration(1500)
.ease("linear")
.attr("transform", "translate(" + x(0) + ")");
I figured it out, changing
graph.append("svg:path")
.data([data])
.attr("class", "line")
.attr("transform", "translate(" + x(1) + ")")
.attr("d", line)
.transition()
.duration(1500)
.ease("linear")
.attr("transform", "translate(" + x(0) + ")");
to
graph.append("svg:path")
.data([data])
.attr("class", "line")
worked.
Obviously my transition for the x axis is incorrect