Changing line color?

4,950 views
Skip to first unread message

Jessica Polito

unread,
Nov 6, 2011, 9:55:08 AM11/6/11
to d3-js
Hi everyone,
I'm making a line chart, but I would like the color of the line to
vary based on a separate set of data --
ideally, one set of data would be used to determine the position, and
a second would determine the color of the line segment
connecting that datapoint to the next one. The x value is given by
the index.

For example, this data should give the y value corresponding to x = i:
var posdata = [3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 7]

but this data should be passed to a color interpolating scale to
determine the color of the segment from x = i to x = i+1:
var coldata = [1, 2, 3, 4, 7, 6, 8, 9, 8, 7, 6, 5, 3]

I think I can do this by creating a separate d3.svg.line(), and
corresponding path, for each segment of my chart;
is there any easier way?
Thank you,
--Jessica

Lars Kotthoff

unread,
Nov 6, 2011, 10:04:18 AM11/6/11
to d3...@googlegroups.com, jpo...@gmail.com
Hi Jessica,

> For example, this data should give the y value corresponding to x = i:
> var posdata = [3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 7]
>
> but this data should be passed to a color interpolating scale to
> determine the color of the segment from x = i to x = i+1:
> var coldata = [1, 2, 3, 4, 7, 6, 8, 9, 8, 7, 6, 5, 3]
>
> I think I can do this by creating a separate d3.svg.line(), and
> corresponding path, for each segment of my chart;
> is there any easier way?

You should just need one d3.svg.line(), used like this:

var colorscale = d3.scale.category20c();
d3.svg.line().y(function(d, i) { return posdata[i]; })
.attr("stroke", function(d, i) { return colorscale(coldata[i]); });

Lars

Jessica Polito

unread,
Nov 6, 2011, 10:20:02 AM11/6/11
to d3-js
I actually tried that already, but when i try to set the stroke attr
of a line in that way, I get an error:

Uncaught TypeError: Object function line(d) {
return d.length < 1 ? null : "M" +
interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension);
} has no method 'attr'

I'm new to d3, so I may be missing something here?
--Jessica

Lars Kotthoff

unread,
Nov 6, 2011, 10:34:23 AM11/6/11
to d3...@googlegroups.com, jpo...@gmail.com
Oh sorry, my mistake :)

You can't set .attr() on d3.svg.line(), set it on the element you're
drawing instead:

var line = d3.svg.line()
.x(function(d, i) { return i; })
.y(function(d, i) { return d; }),
colorscale = d3.scale.category20c();
svg.selectAll("path")
.data(posdata).enter()
.append("svg:path")


    .attr("stroke", function(d, i) { return colorscale(coldata[i]); })

.attr("d", line);

You could also use svg:line elements instead of svg:path but this is probably
easier.

Lars

wimdows

unread,
Nov 6, 2011, 5:49:52 PM11/6/11
to d3-js
Heya Lars,

Are you sure about this?

I was curious how the line would look, so I turned your code into a
working file like this:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>colored bits of line</title>
<script type="text/javascript" src="../../D3/d3.js"></script>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript">

var w = 300,
h = 200;

var posdata = [3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 7];
var coldata = [1, 2, 3, 4, 7, 6, 8, 9, 8, 7, 6, 5, 3];

var line = d3.svg.line()
.x(function(d, i) { return i*10; })
.y(function(d) { return d*10; });

var colorscale = d3.scale.category20c();


var vis = d3.select("#chart")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(20,20)");


vis.selectAll("path")
.data([posdata])
.enter().append("svg:path")
.attr("d", line)
.style("stroke", function(d, i) { return
colorscale(coldata[i]); })
.style("fill", "none");

</script>
</body>
</html>

And it does give a line, but not one with different colors. And
somehow this figures: why would coloring the indexes also color the
subsequent bits of line?

But, I am probably making some mistake or leaving something out. So
please correct me if/where I am wrong.

Regards,

wim

Lars Kotthoff

unread,
Nov 6, 2011, 6:38:28 PM11/6/11
to d3...@googlegroups.com, googlea...@wimdows.nl
> And it does give a line, but not one with different colors.

Yes, if you use svg:path, the colour will be the same -- to get a different
colour for each segment you would have to use different svg:paths or svg:lines.

Sorry, I shouldn't post examples without actually trying them -- you're right,
this one doesn't work as intended. Something like this gives you line segments
with different colours:

vis.selectAll("line")
.data(posdata)
.enter().append("svg:line")
.attr("x1", function(d, i) { return i; })
.attr("x2", function(d, i) { return i+1; })
.attr("y1", function(d, i) { return posdata[i]; })
.attr("y2", function(d, i) { return posdata[i+1]; })
.attr("fill", "none")
.attr("stroke", function(d, i) { return colorscale(coldata[i]); });

I'm setting the coordinates explicitly here, but you can also use the previous
approach with d3.svg.line() and svg:path. The only difference is that then you
would need to transform the data into a matrix with two columns in each row for
the coordinates to connect.

Lars

wimdows

unread,
Nov 6, 2011, 7:01:43 PM11/6/11
to d3-js
This version works like a charm!

I didn't post the intial question, but I'll save that last bit of code
anyway. Could come in handy one day! :)

Regards,

wim

wimdows

unread,
Nov 6, 2011, 7:17:04 PM11/6/11
to d3-js
(Except for the last value for y2, but that's a minor detail. ;) )
Reply all
Reply to author
Forward
0 new messages