This is my current code
<!DOCTYPE html>
<meta charset="utf-8">
<title>Zoom by Rectangle</title>
<script src="http://d3js.org/d3.v2.min.js?2.10.1"></script>
<style>
body {
font-family: sans-serif;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
svg {
font: 10px sans-serif;
shape-rendering: crispEdges;
}
rect {
fill: #ddd;
}
rect.zoom {
stroke: steelblue;
fill-opacity: 0.5;
}
.axis path, .axis line {
fill: none;
stroke: #fff;
}
</style>
<p>
<script>
var margin = {
top : 20,
right : 20,
bottom : 30,
left : 40
}, width = 960 - margin.left - margin.right, height = 500 - margin.top
- margin.bottom;
var x = d3.scale.linear().range([ 0, width ]);
var y = d3.scale.linear().range([ height, 0 ]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
var zoom = d3.behavior.zoom().x(x).y(y).on("zoom", refresh);
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 + ")")
.call(zoom)
.append("g")
.on(
"mousedown",
function() {
console.log("Mouse down");
var e = this;
var origin = d3.mouse(e);
var rect = svg.append("rect").attr("class", "zoom");
d3.select("body").classed("noselect", true);
origin[0] = Math.max(0, Math.min(width, origin[0]));
origin[1] = Math
.max(0, Math.min(height, origin[1]));
d3.select(window).on(
"mousemove.zoomRect",
function() {
console.log("Mouse moving");
var m = d3.mouse(e);
m[0] = Math.max(0, Math
.min(width, m[0]));
m[1] = Math.max(0, Math.min(height,
m[1]));
console.log(m[0]);
console.log(m[1]);
rect.attr("x",
Math.min(origin[0], m[0]))
.attr(
"y",
Math.min(origin[1],
m[1])).attr(
"width",
Math.abs(m[0]
- origin[0]))
.attr(
"height",
Math.abs(m[1]
- origin[1]));
}).on(
"mouseup.zoomRect",
function() {
console.log("Mouse up");
d3.select(window).on(
"mousemove.zoomRect", null).on(
"mouseup.zoomRect", null);
d3.select("body").classed(
"noselect", false);
var m = d3.mouse(e);
m[0] = Math.max(0, Math
.min(width, m[0]));
m[1] = Math.max(0, Math.min(height,
m[1]));
if (m[0] !== origin[0]
&& m[1] !== origin[1]) {
zoom.x(
x
.domain([
origin[0],
m[0] ].map(
x.invert)
.sort()))
.y(
y.domain([
origin[1],
m[1] ].map(
y.invert)
.sort()));
}
rect.remove();
refresh();
}, true);
d3.event.stopPropagation();
});
var data = [ {
"x" : 30,
"y" : 30,
"r" : 20,
"c" : "green",
"s" : "s1"
}, {
"x" : 70,
"y" : 70,
"r" : 20,
"c" : "purple",
"s" : "s2"
}, {
"x" : 110,
"y" : 100,
"r" : 20,
"c" : "red",
"s" : "s3"
} ];
var data1 = [ {
"x" : 30,
"y" : 30
}, {
"x" : 70,
"y" : 70
}, {
"x" : 90,
"y" :90
} ];
x.domain(d3.extent(data, function(d) {
return d.x;
})).nice();
y.domain(d3.extent(data, function(d) {
return d.y;
})).nice();
svg.append("rect").attr("width", width).attr("height", height);
svg.append("g").attr("class", "x axis").attr("transform",
"translate(0," + height + ")").call(xAxis).append("text").attr(
"class", "label").attr("x", width).attr("y", -6).style(
"text-anchor", "end").text("Yield");
svg.append("g").attr("class", "y axis").call(yAxis).append("text")
.attr("class", "label").attr("transform", "rotate(-90)").attr(
"y", 6).attr("dy", ".71em").style("text-anchor", "end")
.text("Skew")
var line = d3.svg.line().x(function(d) {
return x(d.x);
}).y(function(d) {
return y(d.y);
});
svg.append("path").datum(data1).attr("class", "line").attr("stroke",
"steelblue").attr("stroke-width", 1.5).attr("d", line).attr(
"fill", "none");
svg.selectAll(".dot").data(data).enter().append("circle").attr("class",
"dot").attr("r", 3.5).attr("cx", function(d) {
return x(d.x);
}).attr("cy", function(d) {
return y(d.y);
}).style("fill", function(d) {
return color(d.c);
});
var legend = svg.selectAll(".legend").data(color.domain()).enter()
.append("g").attr("class", "legend").attr("transform",
function(d, i) {
return "translate(0," + i * 20 + ")";
});
legend.append("rect").attr("x", width - 18).attr("width", 18).attr(
"height", 18).style("fill", color);
legend.append("text").attr("x", width - 24).attr("y", 9).attr("dy",
".35em").style("text-anchor", "end").text(function(d) {
return d;
});
function refresh() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
}
</script>
The issue is when zoom in with the mouse, the x axis and y axis get updated with the zoomed in range but the actual data is not zooming, looks like i am missing something in the refresh method but i have no clue. ( still learning d3 )
I have done Zoom few days back, and also assumed I just needed to update the axis and the zoom will applied to the entire visualization. But, that wasn't the case. You have to explicitly call the rendering (where you draw the rectangles) again. Then, to prevent it adding duplicate rectangles, you have to handle update and exit sections correctly. I saw you are not using it. Please search for tutorials on enter, update, exit sections. Also, there are tutorials on D3 Wiki (about updating barchart etc). Good luck.
Related
I created a simple d3js vertical bar chart. I understand that typically, to create gridlines, I would use the "tickSize" call, and give them a height or width similar to that of the axis.
var yGridLine = d3.svg.axis()
.scale(yScale)
.tickSize(-width, 0 ,0)
.tickFormat("")
.orient("left");
The above code would create horizontal gridlines. So if I want to create vertical gridlines, then I would modify the orientation and reference axix (something similar to the following untested yet hypothetically correct code)
var xGridLine = d3.svg.axis()
.scale(xScale)
.tickSize(-height, 0 ,0)
.tickFormat("");
Now, the problem is, when using this approach, then the vertical gridlines are created in the middle of the vertical bars (or in the case of horizontal bar charts, then horizontal gridline are created in the middle of the horizontal bars), which is not visually pleasant and not according to requirements. What I want is to have the vertical gridlines appear between the vertical bars (i.e., at the centre points between the ticks). How do I do that?
Example
In this link, you will find a number of charts, where the vertical gridlines are between the ticks, not at the centre. This is what I like to achieve, and my question is how do I achieve that?
Thanks.
The whole code:
var data = [{
name: "Hemant",
age: 20
}, {
name: "Vinay",
age: 55
}, {
name: "Vikas",
age: 56
}, {
name: "Arun",
age: 88
}, {
name: "Varun",
age: 34
}, {
name: "Ajay",
age: 77
}],
w = 600,
h = 300,
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var mySvg = d3.select("body").append("svg").attr({
width: w,
height: h
}).append("g")
.attr("transform", 'translate(' + margin.left + ',' + margin.top + ')');
var xScale = d3.scale.ordinal()
.domain(data.map(function(d) {
return d.name;
}))
.rangeBands([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.age;
})])
.range([height, 0]);
var linearColorScale = d3.scale.linear()
.domain([0, data.length])
.range(["#e74c3c", "#8e44ad"]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var yGridLine = d3.svg.axis()
.scale(yScale)
.tickSize(-width, 0, 0)
.tickFormat("")
.orient("left");
var ordinalColorScale = d3.scale.category20();
mySvg.append("g")
.classed("gridLine", true)
.attr("transform", "translate(0,0)")
.call(yGridLine);
mySvg.selectAll("rect").data(data).enter()
.append("rect")
.attr("x", function(d) {
return xScale(d.name);
})
.attr("y", function(d, i) {
return yScale(d.age);
})
.attr("width", function(d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return height - yScale(d.age)
})
.style("fill", function(d, i) {
return ordinalColorScale(i);
})
mySvg.selectAll("text").data(data)
.enter()
.append("text")
.classed("bar", true)
.attr("x", function(d) {
return xScale(d.name) + xScale.rangeBand() / 2;
})
.attr("dx", 0)
.attr("y", function(d, i) {
return yScale(d.age);
})
.attr("dy", -6)
.text(function(d, i) {
return d.age;
});
mySvg.append("g")
.classed("axis", true)
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
mySvg.append("g")
.classed("axis", true)
.attr("transform", "translate(0,0)")
.call(yAxis);
svg {
border: 1px solid #ccc;
}
svg rect {
shape-rendering: crispedges;
}
.bar {
fill: #000;
text-anchor: middle;
font-size: 20px;
}
.axis path,
.axis line {
fill: none;
shape-rendering: crispedges;
stroke: #666;
}
.gridLine path,
.gridLine line {
fill: none;
shape-rendering: crispedges;
stroke: #e4e4e4;
}
<script src="http://d3js.org/d3.v3.min.js"></script>
You could achieve this by simply translating .gridLines by xScale.rangeBand() / 2 - i.e. half the width of a bar.
var data = [{
name: "Hemant",
age: 20
}, {
name: "Vinay",
age: 55
}, {
name: "Vikas",
age: 56
}, {
name: "Arun",
age: 88
}, {
name: "Varun",
age: 34
}, {
name: "Ajay",
age: 77
}],
w = 600,
h = 300,
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var mySvg = d3.select("body").append("svg").attr({
width: w,
height: h
}).append("g")
.attr("transform", 'translate(' + margin.left + ',' + margin.top + ')');
var xScale = d3.scale.ordinal()
.domain(data.map(function(d) {
return d.name;
}))
.rangeBands([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.age;
})])
.range([height, 0]);
var linearColorScale = d3.scale.linear()
.domain([0, data.length])
.range(["#e74c3c", "#8e44ad"]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var yGridLine = d3.svg.axis()
.scale(xScale)
.tickSize(-height, 0, 0)
.tickFormat("");
var ordinalColorScale = d3.scale.category20();
mySvg.append("g")
.classed("gridLine", true)
.attr("transform", "translate(" + [xScale.rangeBand() / 2, height] + ")")
.call(yGridLine);
mySvg.selectAll("rect").data(data).enter()
.append("rect")
.attr("x", function(d) {
return xScale(d.name);
})
.attr("y", function(d, i) {
return yScale(d.age);
})
.attr("width", function(d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return height - yScale(d.age)
})
.style("fill", function(d, i) {
return ordinalColorScale(i);
})
mySvg.selectAll("text").data(data)
.enter()
.append("text")
.classed("bar", true)
.attr("x", function(d) {
return xScale(d.name) + xScale.rangeBand() / 2;
})
.attr("dx", 0)
.attr("y", function(d, i) {
return yScale(d.age);
})
.attr("dy", -6)
.text(function(d, i) {
return d.age;
});
mySvg.append("g")
.classed("axis", true)
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
mySvg.append("g")
.classed("axis", true)
.attr("transform", "translate(0,0)")
.call(yAxis);
svg {
border: 1px solid #ccc;
}
svg rect {
shape-rendering: crispedges;
}
.bar {
fill: #000;
text-anchor: middle;
font-size: 20px;
}
.axis path,
.axis line {
fill: none;
shape-rendering: crispedges;
stroke: #666;
}
.gridLine path,
.gridLine line {
fill: none;
shape-rendering: crispedges;
stroke: #e4e4e4;
}
<script src="http://d3js.org/d3.v3.min.js"></script>
I want make a bar graph where i can show a particular time period represented by bars.
$(document).ready(function() {
render_chart();
});
function render_chart() {
var dataset = {
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
],
"gates": [
"Test-Gate"
],
"operators": [
"Operator1",
"Operator2",
"Operator3",
],
"layers": [
[{
"fromHours": "14:20:00",
"toHours": "23:00:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "08:30:00",
"toHours": "11:20:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "16:00:00",
"toHours": "18:00:00",
"gate": "Test-Gate"
}]
]
};
n = dataset["operators"].length;
var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
console.log("BEFORE", layersData[0][0]);
layersData.forEach(function(layer) {
layer.forEach(function(innerLayer) {
var fromHourParts = innerLayer.fromHours.split(/:/);
var toHourParts = innerLayer.toHours.split(/:/);
innerLayer.fromHours = new Date();
innerLayer.fromHours.setTime(todayMillis + getTimePeriodMillis(fromHourParts));
innerLayer.toHours = new Date();
innerLayer.toHours.setTime(todayMillis + getTimePeriodMillis(toHourParts));
})
});
console.log("AFTER", dataset["layers"][0][0]);
function getTimePeriodMillis(parts) {
return (parseInt(parts[0], 10) * 60 * 60 * 1000) +
(parseInt(parts[1], 10) * 60 * 1000) +
(parseInt(parts[2], 10) * 1000);
}
function appendExtraZeroToSingleValues(inputValue) {
if (inputValue === 0) {
return inputValue + "0";
}
return inputValue;
}
var parseTime = d3.timeParse("%H:%M");
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var svg = d3.select("#groupchart").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 tomorrow = new Date();
tomorrow.setHours(0, 0, 0, 0);
tomorrow.setDate(today.getDate());
var xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);
var yScale = d3.scaleBand()
.domain(dataset["gates"])
.rangeRound([0, height])
.padding(.08);
var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));
console.log("X-DOMAIN", xScale.domain());
console.log("X-RANGE", xScale.range());
var yAxis = d3.axisLeft(yScale)
.tickSize(-(width - margin.left))
.tickPadding(5);
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("y", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return yScale(d.gate) + yScale.bandwidth() / n * k;
})
.attr("height", yScale.bandwidth() / n)
.transition()
.attr("x", function(d) {
console.log(xScale(d.fromHours));
return xScale(d.fromHours);
})
.attr("width", function(d) {
console.log(xScale(d.toHours - d.fromHours));
return xScale(Math.abs(d.toHours - d.fromHours / 36e5));
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis);
var legend = svg.append("g")
.attr("class", "legend");
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", width / 2.8)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d, i) {
return dataset["colors"][i];
})
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", (width / 2.8) + 10)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'gate');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.gate) return null;
tooltip.select('.gate').html("<b>" + dataset["operators"][i] + "</b>");
tooltip.select('.tempRange').html(appendExtraZeroToSingleValues(d.fromHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.fromHours.getMinutes()) + " Hours to " +
appendExtraZeroToSingleValues(d.toHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.toHours.getMinutes()) + " Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.gate) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
}
.axis .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
Tried like above, but cannot figure out how to do it properly. I messed up and bars does not end inside the graph somehow. The x axis domain is all messed up and also the width of the rects. It works fine if i take another scale. But in time-scale i cannot make it to work.
What i am doing wrong?
Instead of passing the difference of the values to the scale...
scale(a - b)
...pass each value to the scale and subtract them:
scale(a) - scale(b).
In your case:
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
Here is the code with that change:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var dataset = {
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
],
"gates": [
"Test-Gate"
],
"operators": [
"Operator1",
"Operator2",
"Operator3",
],
"layers": [
[{
"fromHours": "14:20:00",
"toHours": "23:00:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "08:30:00",
"toHours": "11:20:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "16:00:00",
"toHours": "18:00:00",
"gate": "Test-Gate"
}]
]
};
n = dataset["operators"].length;
var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
console.log("BEFORE", layersData[0][0]);
layersData.forEach(function(layer) {
layer.forEach(function(innerLayer) {
var fromHourParts = innerLayer.fromHours.split(/:/);
var toHourParts = innerLayer.toHours.split(/:/);
innerLayer.fromHours = new Date();
innerLayer.fromHours.setTime(todayMillis + getTimePeriodMillis(fromHourParts));
innerLayer.toHours = new Date();
innerLayer.toHours.setTime(todayMillis + getTimePeriodMillis(toHourParts));
})
});
console.log("AFTER", dataset["layers"][0][0]);
function getTimePeriodMillis(parts) {
return (parseInt(parts[0], 10) * 60 * 60 * 1000) +
(parseInt(parts[1], 10) * 60 * 1000) +
(parseInt(parts[2], 10) * 1000);
}
function appendExtraZeroToSingleValues(inputValue) {
if (inputValue === 0) {
return inputValue + "0";
}
return inputValue;
}
var parseTime = d3.timeParse("%H:%M");
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var svg = d3.select("#groupchart").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 tomorrow = new Date();
tomorrow.setHours(0, 0, 0, 0);
tomorrow.setDate(today.getDate());
var xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);
var yScale = d3.scaleBand()
.domain(dataset["gates"])
.rangeRound([0, height])
.padding(.08);
var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));
console.log("X-DOMAIN", xScale.domain());
console.log("X-RANGE", xScale.range());
var yAxis = d3.axisLeft(yScale)
.tickSize(-(width - margin.left))
.tickPadding(5);
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("y", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return yScale(d.gate) + yScale.bandwidth() / n * k;
})
.attr("height", yScale.bandwidth() / n)
.transition()
.attr("x", function(d) {
console.log(xScale(d.fromHours));
return xScale(d.fromHours);
})
.attr("width", function(d) {
console.log(xScale(d.toHours - d.fromHours));
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis);
var legend = svg.append("g")
.attr("class", "legend");
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", width / 2.8)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d, i) {
return dataset["colors"][i];
})
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", (width / 2.8) + 10)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'gate');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.gate) return null;
tooltip.select('.gate').html("<b>" + dataset["operators"][i] + "</b>");
tooltip.select('.tempRange').html(appendExtraZeroToSingleValues(d.fromHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.fromHours.getMinutes()) + " Hours to " +
appendExtraZeroToSingleValues(d.toHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.toHours.getMinutes()) + " Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.gate) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
}
.axis .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
I have a parallel coordinates visualization and I've added a table below that represents all the data in the visualization.
I want to filter the table based on the selection of the parallel coordinates visualization. So, just showing the data highlighted in the parallel coordinates visualization.
Any ideas on how to do that?
I've tried in the brush section to highlight the cells in the table in red adding a style in for the tags, but it doesn't seem to work. See code below:
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
d3.selectAll("td").style('bgcolor', 'red');
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
I've tried to add the highlight of the cells in the brush function. Here I achieve for all the cells to turn red, but I don't know how to highlight only the ones selected in the selection.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
d3.selectAll("td").style('background-color', 'red');
}
See code below, which you can find also in the following link GitHub:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.background path {
fill: none;
stroke: #ddd;
shape-rendering: crispEdges;
}
.foreground path {
fill: none;
stroke: steelblue;
stroke-width: 2;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
cursor: move;
}
.tooltip {
background-color: rgba(220,220,220,0.5);
color: #333;
margin: 10px;
height: 25px;
padding-right: 10px;
padding-left: 10px;
padding-top: 10px;
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
td, th {
padding: 1px 4px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Fuente original: https://bl.ocks.org/jasondavies/1341281
var margin = {
top: 30,
right: 10,
bottom: 10,
left: 10
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangePoints([0, width], 1),
y = {},
dragging = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
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 notas = [
{
"Nombre": "Emily",
"Matematicas": "10",
"Ciencias": "10",
"Historia": "8",
"Geografia": "8",
"Lengua": "10"
},
{
"Nombre": "Cooper",
"Matematicas": "10",
"Ciencias": "7",
"Historia": "2",
"Geografia": "8",
"Lengua": "10"
}];
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip")
.attr("class","tooltip");
// Extract the list of dimensions and create a scale for each.
x.domain(dimensions = d3.keys(notas[0]).filter(function(d) {
return d != "Nombre" && (y[d] = d3.scale.linear()
.domain(d3.extent(notas, function(p) {
return +p[d];
}))
.range([height, 0]));
}));
// Add grey background lines for context.
background = svg.append("g")
.attr("class", "background")
.selectAll("path")
.data(notas)
.enter().append("path")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("g")
.attr("class", "foreground")
.selectAll("path")
.data(notas)
.enter().append("path")
.attr("d", path)
.on("mouseover", function(n){
d3.select(this)
.transition().duration(100)
.style({'stroke' : '#F00'});
tooltip.text(n.Nombre);
return tooltip.style("visibility", "visible");
})
.on("mousemove", function(){
return tooltip
.style("top", (event.pageY-10)+"px")
.style("left",(event.pageX+10)+"px");
})
.on("mouseout", function(d){
d3.select(this)
.transition().duration(100)
.style({'stroke': 'steelblue' })
.style({'stroke-width' : '2'});
return tooltip.style("visibility", "hidden");
});
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("g")
.attr("class", "dimension")
.attr("transform", function(d) {
return "translate(" + x(d) + ")";
})
.call(d3.behavior.drag()
.origin(function(d) {
return {
x: x(d)
};
})
.on("dragstart", function(d) {
dragging[d] = x(d);
background.attr("visibility", "hidden");
})
.on("drag", function(d) {
dragging[d] = Math.min(width, Math.max(0, d3.event.x));
foreground.attr("d", path);
dimensions.sort(function(a, b) {
return position(a) - position(b);
});
x.domain(dimensions);
g.attr("transform", function(d) {
return "translate(" + position(d) + ")";
})
})
.on("dragend", function(d) {
delete dragging[d];
transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
transition(foreground).attr("d", path);
background
.attr("d", path)
.transition()
.delay(500)
.duration(0)
.attr("visibility", null);
}));
// Add an axis and title.
g.append("g")
.attr("class", "axis")
.each(function(d) {
d3.select(this).call(axis.scale(y[d]));
})
.append("text")
.style("text-anchor", "middle")
.attr("y", -9)
.text(function(d) {
return d;
});
// Add and store a brush for each axis.
g.append("g")
.attr("class", "brush")
.each(function(d) {
d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brushstart", brushstart).on("brush", brush));
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
function position(d) {
var v = dragging[d];
return v == null ? x(d) : v;
}
function transition(g) {
return g.transition().duration(500);
}
// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function(p) {
return [position(p), y[p](d[p])];
}));
}
function brushstart() {
d3.event.sourceEvent.stopPropagation();
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
// The table generation function
function tabulate(data, columns) {
var table = d3.select("body").append("table")
.attr("style", "margin-left: 250px"),
thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(notas)
.enter()
.append("tr");
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
.attr("style", "font-family: Courier") // sets the font style
.html(function(d) { return d.value; });
return table;
}
// render the table
var peopleTable = tabulate(notas, ["Nombre", "Matematicas","Ciencias", "Historia","Geografia", "Lengua"]);
</script>
</body>
</html>
I've added also the code in JSFiddle but it doesn't display anything. I'm not sure what I'm doing wrong. I'm not familiar with JSFiddle, so I might be doing something wrong.
I've tried also to use divgrid (DivGrid) and with the following code I can see how when I attempt to brush the table gets updated. The problem is that it doesn't get updated with the data I need. I just have it to show 5 records.
<script src="divgrid.js"></script>
...
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) {
return !y[p].brush.empty();
}),
extents = actives.map(function(p) {
return y[p].brush.extent();
});
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
//d3.selectAll("td").style('background-color', 'red');
var grid = d3.divgrid();
d3.select('body')
.datum(notas.slice(0,5))
.call(grid);
}
The problems I have (I think) is that (1) the update of the table is not really in the right place as it is only updating when starting to brush, not when brushing over the lines and (2) I need to find a way to pickup the data from the lines that are selected. I've added to code in github as a reference (GitHub)
Any ideas?
Thanks
I would like to get the tooltip moved along with cursor when cursor is on bars('rect') of d3js barcharts. Iam placing tooltip on top of corresponding bars in barchart with correct data loaded from .json objects given in code.I tried, but i didn't get proper solution for how to get cursor coordinates and passing cursor coordinates to d3 tooltip offset().
Can any one generate proper code in javascript that works with my application.
Thanks in advance.
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script type="text/javascript">
var XPos=0;
var YPos=0;
var inputData = [ {
x : "i20",
y : 1
}, {
x : "Tucson",
y : 37
}, {
x : "iLoad",
y : 16
}, {
x : "iMax",
y : 18
}, {
x : "Elantra",
y : 8
}, {
x : "Veloster",
y : 1
}, {
x : "i30",
y : 86
}, {
x : "iX35",
y : 7
}, {
x : "Accent",
y : 27
} ];
var svgHeight = 400;
var svgWidth = 400;
var maxY = 100; // You can also compute this from the data (y axis)
var barSpacing = 10; // The amount of space you want to keep between the bars
var padding = {
left : 50,
right : 0,
top : 20,
bottom : 20
};
function render(inputData)
{
var svgHeight = 250;
var svgWidth = 700;
var maxY = 100; // You can also compute this from the data (y axis)
var barSpacing = 10; // The amount of space you want to keep between the bars
var padding = {
left: 50,
right: 0,
top: 20,
bottom: 20
};
var maxWidth = svgWidth - padding.left - padding.right;
var maxHeight = svgHeight - padding.top - padding.bottom;
//var x = d3.scale.ordinal().domain(inputData.map(function (d) {
// return d.x;
//})).rangeRoundBands([0, maxWidth]);
var x = d3.scale.ordinal().domain(inputData.map(function (d) {
return d.x;
})).rangeRoundBands([0, maxWidth], .3);
var y = d3.scale.linear().domain([0,
d3.max(inputData, function (d) {
return d.y;
})
]).range([maxHeight, 0]);
var xAxis = d3.svg.axis().scale(x).orient('bottom');
var yAxis = d3.svg.axis().scale(y).orient('left');
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([YPos, XPos])
.html(function(d)
{
return "<strong>total:</strong> <span style='color:orange'>" +
d.y + "</span>";
})
var svg = d3.select('.chart').attr({
width: svgWidth,
height: svgHeight
});
var chart = svg.append('g').attr(
{
transform: function (d, i) {
return 'translate(' + padding.left + ','
+ padding.top + ')';
}
});
chart.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + maxHeight + ')')
.call(xAxis)
.append("text")
.attr("x", maxWidth)
//.attr("y", 20)
.attr("dy", ".81em")
.style("text-anchor", "end")
.text("Model");
chart.append('g')
.attr('class', 'y axis')
.attr('height', maxHeight)
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Total");
var bars = chart.selectAll('g.bar-group')
.data(inputData)
.enter()
.append('g') // Container for the each bar
.attr({
transform: function (d, i) {
return 'translate(' + x(d.x) + ', 0)';
},
class: 'bar-group'
})
;
bars.call(tip);
bars.append('rect')
.attr('y', maxHeight)
.attr('height', 0)
.attr('width', function (d) { return x.rangeBand(d) - 1; })
.attr('class', 'bar')
.transition().duration(1500)
.attr('y', function (d, i) { return y(d.y); })
.attr('height', function (d, i) { return maxHeight - y(d.y); });
bars.select('rect')
.on('mouseover', tip.show)
.on('mousemove', function(event)
{
XPos = event.clientX;
YPos = event.clientY;tip.show;
})
.on('mouseout', tip.hide);
}
render(inputData);
</script>
<style type="text/css">
.chart rect {
fill: steelblue;
}
.chart rect:hover {
fill: blue;
opacity: 0.1;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font-size: 12px;
}
.chart .current {
fill: green;
cursor: pointer;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
<body>
<div class="chart-container">
<svg class="chart">
</svg>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script type="text/javascript">
var XPos=0;
var YPos=0;
var inputData = [ {
x : "i20",
y : 1
}, {
x : "Tucson",
y : 37
}, {
x : "iLoad",
y : 16
}, {
x : "iMax",
y : 18
}, {
x : "Elantra",
y : 8
}, {
x : "Veloster",
y : 1
}, {
x : "i30",
y : 86
}, {
x : "iX35",
y : 7
}, {
x : "Accent",
y : 27
} ];
var svgHeight = 400;
var svgWidth = 400;
var maxY = 100; // You can also compute this from the data (y axis)
var barSpacing = 10; // The amount of space you want to keep between the bars
var padding = {
left : 50,
right : 0,
top : 20,
bottom : 20
};
function render(inputData)
{
var svgHeight = 250;
var svgWidth = 700;
var maxY = 100; // You can also compute this from the data (y axis)
var barSpacing = 10; // The amount of space you want to keep between the bars
var padding = {
left: 50,
right: 0,
top: 20,
bottom: 20
};
var maxWidth = svgWidth - padding.left - padding.right;
var maxHeight = svgHeight - padding.top - padding.bottom;
//var x = d3.scale.ordinal().domain(inputData.map(function (d) {
// return d.x;
//})).rangeRoundBands([0, maxWidth]);
var x = d3.scale.ordinal().domain(inputData.map(function (d) {
return d.x;
})).rangeRoundBands([0, maxWidth], .3);
var y = d3.scale.linear().domain([0,
d3.max(inputData, function (d) {
return d.y;
})
]).range([maxHeight, 0]);
var xAxis = d3.svg.axis().scale(x).orient('bottom');
var yAxis = d3.svg.axis().scale(y).orient('left');
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([YPos, XPos])
.html(function(d)
{
return "<strong>total:</strong> <span style='color:orange'>" +
d.y + "</span>";
})
var svg = d3.select('.chart').attr({
width: svgWidth,
height: svgHeight
});
var chart = svg.append('g').attr(
{
transform: function (d, i) {
return 'translate(' + padding.left + ','
+ padding.top + ')';
}
});
chart.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + maxHeight + ')')
.call(xAxis)
.append("text")
.attr("x", maxWidth)
//.attr("y", 20)
.attr("dy", ".81em")
.style("text-anchor", "end")
.text("Model");
chart.append('g')
.attr('class', 'y axis')
.attr('height', maxHeight)
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Total");
var bars = chart.selectAll('g.bar-group')
.data(inputData)
.enter()
.append('g') // Container for the each bar
.attr({
transform: function (d, i) {
return 'translate(' + x(d.x) + ', 0)';
},
class: 'bar-group'
})
;
bars.call(tip);
bars.append('rect')
.attr('y', maxHeight)
.attr('height', 0)
.attr('width', function (d) { return x.rangeBand(d) - 1; })
.at`enter code here`tr('class', 'bar')
.transition().duration(1500)
.attr('y', function (d, i) { return y(d.y); })
.attr('height', function (d, i) { return maxHeight - y(d.y); });
//****************ANSWER IS HERE***********************`enter code here`
bars.select('rect')
.on('mousemove', function(event)
{
tip.style("top", (d3.event.pageY - 51) + "px")
.style("left", (d3.event.pageX - 51) + "px")
}
)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
//*******************UP TO Here********************
}
render(inputData);
</script>
<style type="text/css">
.chart rect {
fill: steelblue;
}
.chart rect:hover {
fill: blue;
opacity: 0.1;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font-size: 12px;
}
.chart .current {
fill: green;
cursor: pointer;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
<body>
<div class="chart-container">
<svg class="chart">
</svg>
</div>
I have started working with d3 recently, and I seem to have come across an error. When I run my code, I get these results:
Error: Invalid value for <path> attribute d="MNaN,NaNLNaN,NaNCNaN,NaN,NaN,NaN,NaN,NaNCNaN,NaN,NaN,NaN,NaN,NaNCNaN,NaN,NaN,NaN,NaN,NaNCNaN,NaN,NaN,NaN,NaN,NaNCNaN,NaN,NaN,NaN,NaN,NaNLNaN,NaN"
Here's my code:
<head>
<title>Compression</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.1/d3.min.js"></script>
<style>
.axis path,
.axis line {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: 'Arial';
font-size: 13px;
}
.tick {
stroke-dasharray: 1, 2;
}
.bar {
fill: FireBrick;
}
</style>
</head>
<body>
<input type="range" id="myRange" value="50" step="2.5">
<p id="demo"></p>
<br>
<br>
<svg id="visual" width="1000" height="500"></svg>
<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 = [];
//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)"
});
}
}
$(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");
//updates when slider changes
$("#myRange").change(function() {
slider = $("#myRange").val();
updateXs();
updateLineData();
displayVals();
});
});
</script>
</body>
</html>
The idea is that it should be a graph that changes with the slider. The slider is supposed to alter the quadratic equation, while making sure it goes through two specific points. I can't see any ticks or any lines in the graph though.
Actually, it turns out that it was because of the quotes in:
for (i = (firstx - 1); i < (secondx + 2); i++) {
lineData.push({
x: "i",
y: "getY(i)"
});
}