I can't quite get this. Trying to modify:
https://bl.ocks.org/duspviz-mit/9b6dce37101c30ab80d0bf378fe5e583
to be able add low value to the left of the bar and high value to right. If anyone could point in the right direction, or show another example, would be much appreciated.
Just copy the ticks of the axis for the boundary of the domain.
Made the svg a bit bigger to fit the texts
<html>
<head>
<script src="https://d3js.org/d3.v4.js"></script>
<style type="text/css">
.axis text {
font: 10px sans-serif;
}
.axis line, .axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
svg{
padding-left: 50px;
}
</style>
</head>
<body>
<div id="legend1"></div>
<script type="text/javascript">
var w = 300, h = 50;
var key = d3.select("#legend1")
.append("svg")
.attr("width", w+100)
.attr("height", h+50);
var legend = key.append("defs")
.append("svg:linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "100%")
.attr("x2", "100%")
.attr("y2", "100%")
.attr("spreadMethod", "pad");
legend.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#f7fcf0")
.attr("stop-opacity", 1);
legend.append("stop")
.attr("offset", "33%")
.attr("stop-color", "#bae4bc")
.attr("stop-opacity", 1);
legend.append("stop")
.attr("offset", "66%")
.attr("stop-color", "#7bccc4")
.attr("stop-opacity", 1);
legend.append("stop")
.attr("offset", "100%")
.attr("stop-color", "#084081")
.attr("stop-opacity", 1);
key.append("rect")
.attr("width", w)
.attr("height", h - 30)
.style("fill", "url(#gradient)")
.attr("transform", "translate(50,10)");
var y = d3.scaleLinear()
.range([300, 0])
.domain([68, 12]);
var yAxis = d3.axisBottom()
.scale(y)
.ticks(5);
key.append("g")
.attr("class", "y axis")
.attr("transform", "translate(50,30)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -30)
.attr("dy", "0")
.attr("dx", "0")
.attr("fill", "#000")
.style("text-anchor", "end")
.text("axis title");
var extras = key.select(".y.axis").selectAll(".dummy")
.data(y.domain())
.enter()
.append("g")
.attr("class", "tick")
.attr("transform", d => `translate(${y(d)},0)` );
extras.each( function (d) {
d3.select(this).append("line").attr("stroke", "#000").attr("y2", 6);
d3.select(this).append("text").attr("fill", "#000").attr("y", 9).attr("dy", "0.71em").text(d);
});
</script>
</body>
</html>
Related
I'm using this tutorial, Making a cool Bitcoin price chart using D3.js and the CryptoCompare API and I am having trouble styling the lines that are drawn.
For example, I would like to be able to select and style the lines x and y to change their color to white. See this snippet from the tutorial:
var x = d3.scaleTime()
.range([0, width])
I've tried adding .attr("fill", "#fff"), but this only breaks it. How do I change the colors of d3.scaleTime() and d3.scaleLinear()?
I have also tried the following as described in the d3-scale documentation:
var x = d3.scaleTime()
.range([0, width])
x(20); // "#9a3439"
Here's the entire script:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="500"></svg>
</head>
<style>
body {
text-align: center;
margin-top: 5em;
background-color: #74b9ff;
}
h1 {
color: snow;
}
</style>
<body>
<h1>Bitcoin Prices in U.S. Dollars</h1>
<script>
var url = "https://min-api.cryptocompare.com/data/histoday?fsym=BTC&tsym=USD&limit=200&aggregate=3&e=CCCAGG";
d3.json(url).get(function(error, d) {
var data = d.Data;
data.forEach(function(d){ d.time = new Date(d.time * 1000) });
if (error) throw error;
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleTime()
.range([0, width])
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.x(function(d) { return x(d.time); })
.y(function(d) { return y(d.close); });
x.domain(d3.extent(data, function(d) { return d.time; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.attr("stroke-width", 2)
.attr("fill", "none")
.style("font-size",".8em");
g.append("g")
.call(d3.axisLeft(y))
.attr("stroke-width", 2)
.style("font-size",".8em")
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 20)
.attr("text-anchor", "end")
.attr("font-size", "1.2em")
.text("Price ($)")
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ffeaa7")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 2)
.attr("d", line);
});
</script>
</body>
</html>
You can style the axes as shown below.
var xAxis = g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
xAxis.select("path") //Axis
.style("stroke","white");
xAxis.selectAll("line") //ticks
.style("stroke","white");
var yAxis = g.append("g")
.call(d3.axisLeft(y));
yAxis.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 20)
.attr("text-anchor", "end")
.attr("font-size", "1.2em")
.text("Price ($)");
yAxis.select("path") //Axis
.style("stroke","white");
yAxis.selectAll("line") //ticks
.style("stroke","white");
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="500"></svg>
</head>
<style>
body {
text-align: center;
margin-top: 5em;
background-color: #74b9ff;
}
h1 {
color: snow;
}
</style>
<body>
<h1>Bitcoin Prices in U.S. Dollars</h1>
<script>
var url = "https://min-api.cryptocompare.com/data/histoday?fsym=BTC&tsym=USD&limit=200&aggregate=3&e=CCCAGG";
d3.json(url).get(function(error, d) {
var data = d.Data;
data.forEach(function(d) {
d.time = new Date(d.time * 1000)
});
if (error) throw error;
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleTime()
.range([0, width])
var y = d3.scaleLinear()
.range([height, 0]);
var line = d3.line()
.x(function(d) {
return x(d.time);
})
.y(function(d) {
return y(d.close);
});
x.domain(d3.extent(data, function(d) {
return d.time;
}));
y.domain(d3.extent(data, function(d) {
return d.close;
}));
var xAxis = g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.attr("stroke-width", 2)
.attr("fill", "none")
.style("font-size", ".8em")
xAxis.select("path") //Axis
.style("stroke", "white");
xAxis.selectAll("line") //ticks
.style("stroke", "white");
var yAxis = g.append("g")
.call(d3.axisLeft(y))
.attr("stroke-width", 2)
.style("font-size", ".8em");
yAxis.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 20)
.attr("text-anchor", "end")
.attr("font-size", "1.2em")
.text("Price ($)");
yAxis.select("path") //Axis
.style("stroke", "white");
yAxis.selectAll("line") //ticks
.style("stroke", "white");
g.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ffeaa7")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 2)
.attr("d", line);
});
</script>
</body>
</html>
While Gilsha's answer seems like best practice and allows for more direct control over styling, the answer got from that was to use selectAll() to select and style each "path" (axes), "line" (ticks), and "text" (display of price and date).
Including the following in the end of the function d3.json(url).get(function(error, d) styles everything as white:
g.selectAll("path") //Axes
.style("stroke","white");
g.selectAll("line") //Ticks
.style("stroke","white");
g.selectAll("text") //Text displaying date and price
.attr("fill", "white");
Note that this broad-stroke approach includes the path for the plotted data line as well. If you need to distinguish between them, you can define a variable for that and style it independently as Gilsha did for the axes.
I'm creating a legend for some data.
This is my code: Plunker.
The problem is that the labels are uniformly distributed along the x axis while they should follow the color scale scheme:
var colorScale = d3.scaleLinear()
.domain([0, 10, 15, 20, 25, 100])
.range(['#E28672', '#EC93AB', '#CEB1DE', '#95D3F0', '#77EDD9', '#A9FCAA']);
Here is what I have:
And this is what I would like:
Thanks!
You need to set the tick values that you want to show, this can be done with:
axis.tickValues([value,value,...])
In your case you want the labeled values to be equal to the color breaks in your scale. Luckily you have an array containing those values already, the scale's domain:
axis.tickValues(colorScale.domain());
With an adjustment to legend width (the labels are rather close together otherwise), and applying that change, we get:
var colorScale = d3.scaleLinear()
.domain([0, 10, 15, 20, 25, 100])
.range(['#E28672', '#EC93AB', '#CEB1DE', '#95D3F0', '#77EDD9', '#A9FCAA']);
// append a defs (for definition) element to your SVG
var svgLegend = d3.select('body').append('svg')
.attr("width",600);
var defs = svgLegend.append('defs');
// append a linearGradient element to the defs and give it a unique id
var linearGradient = defs.append('linearGradient')
.attr('id', 'linear-gradient');
// horizontal gradient
linearGradient
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%");
// append multiple color stops by using D3's data/enter step
linearGradient.selectAll("stop")
.data([
{offset: "0%", color: "#E28672"},
{offset: "10%", color: "#EC93AB"},
{offset: "15%", color: "#CEB1DE"},
{offset: "20%", color: "#95D3F0"},
{offset: "25%", color: "#77EDD9"},
{offset: "100%", color: "#A9FCAA"}
])
.enter().append("stop")
.attr("offset", function(d) {
return d.offset;
})
.attr("stop-color", function(d) {
return d.color;
});
// append title
svgLegend.append("text")
.attr("class", "legendTitle")
.attr("x", 0)
.attr("y", 20)
.style("text-anchor", "left")
.text("Legend title");
// draw the rectangle and fill with gradient
svgLegend.append("rect")
.attr("x", 10)
.attr("y", 30)
.attr("width", 400)
.attr("height", 15)
.style("fill", "url(#linear-gradient)");
//create tick marks
var xLeg = d3.scaleLinear()
.domain([0, 100])
.range([10, 400]);
var axisLeg = d3.axisBottom(xLeg)
.tickValues(colorScale.domain())
svgLegend
.attr("class", "axis")
.append("g")
.attr("transform", "translate(0, 40)")
.call(axisLeg);
.legendTitle {
font-size: 15px;
fill: #4F4F4F;
font-weight: 12;
}
.axis path, .axis line {
fill: none;
stroke: none; /*black;*/
shape-rendering: crispEdges;
}
.axis text {
font-family: Consolas, courier;
fill: #000;
font-size: 9pt;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
I'd also point out that we can go one step further, and append the stops for the gradient using the scale's domain as well:
var colorScale = d3.scaleLinear()
.domain([0, 10, 15, 20, 25, 100])
.range(['#E28672', '#EC93AB', '#CEB1DE', '#95D3F0', '#77EDD9', '#A9FCAA']);
// append a defs (for definition) element to your SVG
var svgLegend = d3.select('body').append('svg')
.attr("width",600);
var defs = svgLegend.append('defs');
// append a linearGradient element to the defs and give it a unique id
var linearGradient = defs.append('linearGradient')
.attr('id', 'linear-gradient');
// horizontal gradient
linearGradient
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%");
// append multiple color stops by using D3's data/enter step
linearGradient.selectAll("stop")
.data(colorScale.domain())
.enter().append("stop")
.attr("offset", function(d) {
return d+"%";
})
.attr("stop-color", function(d) {
return colorScale(d);
});
// append title
svgLegend.append("text")
.attr("class", "legendTitle")
.attr("x", 0)
.attr("y", 20)
.style("text-anchor", "left")
.text("Legend title");
// draw the rectangle and fill with gradient
svgLegend.append("rect")
.attr("x", 10)
.attr("y", 30)
.attr("width", 400)
.attr("height", 15)
.style("fill", "url(#linear-gradient)");
//create tick marks
var xLeg = d3.scaleLinear()
.domain([0, 100])
.range([10, 400]);
var axisLeg = d3.axisBottom(xLeg)
.tickValues(colorScale.domain())
svgLegend
.attr("class", "axis")
.append("g")
.attr("transform", "translate(0, 40)")
.call(axisLeg);
.legendTitle {
font-size: 15px;
fill: #4F4F4F;
font-weight: 12;
}
.axis path, .axis line {
fill: none;
stroke: none; /*black;*/
shape-rendering: crispEdges;
}
.axis text {
font-family: Consolas, courier;
fill: #000;
font-size: 9pt;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
In D3JS V4: Suppose that you have six rectangles. How would you create a gradient that flows through from the first to the last?
I tried creating a group for the rectangles and then add the color-gradient-id to the group, but it still causes for the gradient to happen within each rectangle individually.
You have to set gradientUnits to userSpaceOnUse. According to the docs, userSpaceOnUse:
...represent values in the coordinate system that results from taking the current user coordinate system in place at the time when the gradient element is referenced
Here is a demo without userSpaceOnUse, which result is not what you want:
var svg = d3.select("svg");
var gradient = svg.append("defs")
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "50%")
.attr("x2", "100%")
.attr("y2", "50%");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "Black")
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "white")
.attr("stop-opacity", 1);
var g = svg.append("g")
.style("fill", "url(#gradient)");
var rects = g.selectAll("foo")
.data(d3.range(7))
.enter()
.append("rect")
.attr("y", 20)
.attr("x", (d, i) => 20 + 50 * i)
.attr("width", 40)
.attr("height", 40);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="400"></svg>
Now a demo with userSpaceOnUse:
var svg = d3.select("svg");
var gradient = svg.append("defs")
.append("linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "50%")
.attr("x2", "100%")
.attr("y2", "50%")
.attr("gradientUnits","userSpaceOnUse");
gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", "Black")
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", "white")
.attr("stop-opacity", 1);
var g = svg.append("g")
.style("fill", "url(#gradient)");
var rects = g.selectAll("foo")
.data(d3.range(7))
.enter()
.append("rect")
.attr("y", 20)
.attr("x", (d, i) => 20 + 50 * i)
.attr("width", 40)
.attr("height", 40);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="400"></svg>
I am making a scatterplot, and pulling in an image fill for each circle on the plot. The problem is that the images are PNG's with transparent backgrounds. This means my overlapping circles show through each other:
Seen here - http://i.stack.imgur.com/bphon.png
I have tried setting a background colour with the CSS, but it seems to be completely overwritten by the .style("fill") in the JS. And I am looking to pull in 30ish images, so I don't want to have to save them all to be able to load the images with my CSS.
So, my question is, is there a way to put a white background behind my PNGs, while pulling those PNGs from URL's contained in my dataset?
Thanks for the help
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis-text {
font-family: sans-serif;
font-size: 11px;
background-color: white;
font-weight: bold;
}
.teamcircle {
background-color: white;
}
</style>
</head>
<body>
<div>
<input type="button" id="playerbtn" value="See Player View">
<input type="button" id="teambtn" value="See Team View">
</div>
<div id="data">
<div id="player-circles">
</div>
</div>
<script type="text/javascript">
//Width and height
var margin = {top: 50, right: 20, bottom: 30, left: 40};
var w = 960 - margin.left - margin.right;
var h = 500 - margin.top - margin.bottom;
//Create scale functions
var xScale = d3.scale.linear()
.range([0, w]);
var yScale = d3.scale.linear()
.range([h, 0]);
// var color = d3.scale.color();
// Define the Axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Load the TEAM data set
var teamdata = d3.tsv("team.tsv", function(error, teamdata) {
if (error) throw error;
teamdata.forEach(function(d) {
d.entriesper60 = +d.entriesper60;
d.carryinpercent = +d.carryinpercent;
});
xScale.domain(d3.extent(teamdata, function(d) { return d.carryinpercent; })).nice();
yScale.domain(d3.extent(teamdata, function(d) { return d.entriesper60; })).nice();
//Create X axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.append("text")
.attr("class", "axis-text")
.attr("x", w)
.attr("y", -6)
.style("text-anchor", "end")
.text("Carry-in %");
//Create Y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "axis-text")
.attr("y", -20)
.attr("z", 0)
.style("text-anchor", "middle")
.text("Entries/60")
// DEFS & Pattern for images
svg.append("defs")
.selectAll("pattern")
.data(teamdata)
.enter()
.append("pattern")
.attr('id', function(d, i) {
return d.name;
})
// .attr('patternUnits', 'userSpaceOnUse')
.attr('width', 20)
.attr('height', 20)
.append("image")
.attr("xlink:href", function(d) {
return d.image + d.name;
})
.attr('width', 20)
.attr('height', 20)
.attr("transform", "translate(2, 2)");
// Create TEAM Circles
svg.selectAll("circle")
.data(teamdata)
.enter()
.append("circle")
.attr("class", "teamcircle")
.style("stroke", function(d) { return d.hex; })
.style("stroke-width", 2)
.style("stroke-opacity", .8)
.attr("r", 12)
.attr("cx", function(d) { return xScale(d.carryinpercent); })
.attr("cy", function(d) { return yScale(d.entriesper60); })
.attr("fill", function(d) { return "url(#" + d.name + ")";
});
});
</script>
</body>
</html>
The best way I can think of is to create a group for every circle, and create a circle with a white background first. Something like this:
var teamCircle = svg.selectAll("g.teamcircle")
.data(teamdata)
.enter()
.append("g")
.attr("class", "teamcircle")
.transform(function(d){return "translate(" + xScale(d.carryinpercent) + "," + yScale(d.entriesper60) + ")"});
teamCircle.append("circle")
.attr("fill", "white")
.attr("r", 12)
teamCircle.append("circle")
.style("stroke", function(d) { return d.hex; })
.style("stroke-width", 2)
.style("stroke-opacity", .8)
.attr("r", 12)
.attr("fill", function(d) { return "url(#" + d.name + ")";
I made a two-line chart with a legend. I want to highlight the stroke-width of each of the lines to 4px based on the color of the legend circle when the user hovers over it. So, user hovers over the blue legend circle, the blue line stroke-width changes to 4px. Same for the red one if he hovers over the red circle on the legend. Is this possible to do based on my code? Here is the whole code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="../d3/d3.js"></script>
<script type="text/javascript" src="../d3/d3-tip.js"></script>
<style type="text/css">
body{
font: 16px Calibri;
}
.line1{
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
.line1:hover{
stroke-width: 3.5px;
}
.line2{
fill: none;
stroke: red;
stroke-width: 2px;
}
.line2:hover{
stroke-width: 3.5px;
}
.axis path,
.axis line{
fill:none;
stroke: black;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.axis text{
font-family: sans-serif;
font-size: 14px;
stroke: black;
stroke-width: 0.5px;
}
.legend .series {
cursor: pointer;
}
.legend circle {
stroke-width: 2px;
}
.legend .disabled circle {
fill-opacity: 0;
}
</style>
<!--...this code will be used on an external html file and instered-->
<html>
<body>
<div id="dropdown">
<select id = "opts">
<option value = "ds1">Atlas</option>
<option value = "ds2">BioSQL</option>
<option value = "ds3">Coppermine</option>
<option value = "ds4">Ensembl</option>
<option value = "ds5">Mediawiki</option>
<option value = "ds6">Opencart</option>
<option value = "ds7">PhpBB</option>
<option value = "ds8">Typo3</option>
</select>
</div>
<script type="text/javascript">
console.log("worked");
var ds1="../CSV/atlas/results/metrics.csv";
var ds2="../CSV/biosql/results/metrics.csv";
var ds3="../CSV/coppermine/results/metrics.csv";
var ds4="../CSV/ensembl/results/metrics.csv";
var ds5="../CSV/mediawiki/results/metrics.csv";
var ds6="../CSV/opencart/results/metrics.csv";
var ds7="../CSV/phpbb/results/metrics.csv";
var ds8="../CSV/typo3/results/metrics.csv";
</script>
</body>
</html> <!--...............................................................-->
<div id="area1"></div>
<div id="area2"></div>
</head>
<body>
<script type="text/javascript">
var margin = {top: 60, right: 20, bottom: 40, left: 40},
margin2 = {top: 430, right: 20, bottom: 0, left: 50},
width = 800 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
height2 = 870 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%Y").parse;
var color = d3.scale.category20()
.range(["#1f77b4", "#d62728", "#98df8a"]);
var x = d3.scale.linear()
.range([0, width]);
var x1 = d3.time.scale()
.nice(d3.time.year)
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
var x1Axis = d3.svg.axis()
.scale(x1)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg1 = d3.select("#area1").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height2 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var line1 = d3.svg.line()
.x(function(d) { return x(d.trID);})
.y(function (d) {return y(d.newT);})
.interpolate("basis");
var line2 = d3.svg.line()
.x(function(d) { return x1(d.time);})
.y(function (d) {return y(d.newT);})
.interpolate("basis");
var dsv = d3.dsv(";", "text/plain"); //setting the delimiter
var dataset = [] //defining the data array
var datapath="../CSV/atlas/results/metrics.csv";
dsv(datapath, function(data){ //------------select the file to load the csv------------
var label = document.getElementById('opts')[document.getElementById('opts').selectedIndex].innerHTML;//takes the name of the f
console.log(label);
dataset= data.map(function(d){ //parse
return { //insert parsed data in the array
trID: +d["trID"],
newT: +d["#newT"],
time: +d["time"]
};
});
dataset.forEach(function(d){
d.time = new Date(d.time*1000);
});
console.log(dataset);
x.domain(d3.extent(dataset, function(d) { return d.trID; }));
x1.domain(d3.extent(dataset, function(d) { return d.time; }));
// y.domain([0, d3.max(dataset.map( function(d) {return d.newT}))]);
y.domain(d3.extent(dataset, function(d) { return d.newT; }));
//------------------creating the lines---------------------
svg1.append("path")
.datum(dataset)
.attr("class", "line1")
.attr("d", line1);
svg1.append("path")
.datum(dataset)
.attr("class", "line2")
// .style("stroke-dasharray",("5,5"))
.attr("d", line2);
//----------------appending Legend--------------------------
var legend = svg1.selectAll(".legend")
.data((["Duration/Time","Duration/ID"]).slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("circle")
.attr("r", 7)
.attr("cx", 45)
.attr("cy", 10)
.style("fill", color);
legend.append("text")
.attr("x", 54)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "begin")
.style("font-family", "Calibri")
.text(function(d) { return d; });
//-----------------------------------------------------------
svg1.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("trID");
svg1.append("g")
.attr("class", "x1 axis")
.attr("transform", "translate(0," + height2 + ")")
.call(x1Axis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("time");
svg1.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("num of tables");
svg1.append("text")
.attr("class","simpletext")
.attr("x", (width/2))
.attr("y", 0 - (margin.top/2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("text-decoration", "underline")
.text(label);
});
d3.select('#opts')
.on('change', function(){
var dataset=[]
var datapath = eval(d3.select(this).property('value'));
label = document.getElementById('opts')[document.getElementById('opts').selectedIndex].innerHTML;
dsv(datapath, function(data){ //------------select the file to load the csv------------
dataset= data.map(function(d){ //parse
return { //insert parsed data in the array
trID: +d["trID"],
newT: +d["#newT"],
time: +d["time"]
};
});
dataset.forEach(function(d){
d.time = new Date(d.time*1000);
});
x.domain(d3.extent(dataset, function(d) { return d.trID; }));
x1.domain(d3.extent(dataset, function(d) { return d.time; }));
// y.domain([0, d3.max(dataset.map( function(d) {return d.newT}))]);
y.domain(d3.extent(dataset, function(d) { return d.newT; }));
d3.selectAll(".line1")
.transition()
.duration(1000)
.attr("d", line1(dataset));
d3.selectAll(".line2")
.transition()
.duration(1000)
.attr("d", line2(dataset));
//Update Axis
//Update X axis
svg1.select(".x.axis")
.transition()
.duration(1000)
.call(xAxis);
svg1.select(".x1.axis")
.transition()
.duration(1000)
.call(x1Axis);
//Update Y axis
svg1.select(".y.axis")
.transition()
.duration(1000)
.call(yAxis);
svg1.selectAll("path")
.data(dataset)
.exit()
.remove();
console.log(label);
svg1.selectAll(".simpletext")
.transition()
.text(label);
/* .attr("x", (width/2))
.attr("y", 0 - (margin.top/2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("text-decoration", "underline")
.text(label);*/
});
});
</script>
</body>
</html>
I define my color as this:
var color = d3.scale.category20()
.range(["#1f77b4", "#d62728", "#98df8a"]);
And each of my lines as this:
var line1 = d3.svg.line()
.x(function(d) { return x(d.trID);})
.y(function (d) {return y(d.newT);})
.interpolate("basis");
var line2 = d3.svg.line()
.x(function(d) { return x1(d.time);})
.y(function (d) {return y(d.newT);})
.interpolate("basis");
Of course it's possible.
So first it has nothing to do with line1 and line2 - they are about data of the line, not actual visual element. You need to change style of the path elements .line1 and .line2.
You can add event listeners when creating the legend.
//----------------appending Legend--------------------------
var legend = svg1.selectAll(".legend")
.data((["Duration/Time","Duration/ID"]).slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; })
.on("mouseover", function(d) {
if (d === "Duration/ID") {
// line1's legend is hovered
svg1.selectAll(".line1").style("stroke-width", "4px");
}
else if (d === "Duration/Time") {
// line2's legend is hovered
svg1.selectAll(".line2").style("stroke-width", "4px");
}
})
.on("mouseout", function() {
// revert the styles
svg1.selectAll(".line1").style("stroke-width", "2px");
svg1.selectAll(".line2").style("stroke-width", "2px");
});
This is just a demonstration. Of course it would be more consistent to define the styles in css and change class on events, and you may not want to hardcode legend names when you have more/dynamic series.