Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 filling an area with a gradient

I'm wanting to fill the area of this line chart with a gradient, so that the bottom of the gradient is transparent, and the top of the area fill is black. Is this possible?

All my google searches are bring up charts like: http://bl.ocks.org/d3noob/4433087 - I don't want the gradient to be based on the values, in this example I'd want red across the top of the area, not just when a value reaches that %.

var entries = [{"date":"2016-01-06","value":15},{"date":"2015-11-17","value":15.4},{"date":"2015-11-11","value":16.5},{"date":"2015-09-24","value":15.1},{"date":"2015-08-22","value":15},{"date":"2015-08-12","value":15},{"date":"2015-07-30","value":14.6},{"date":"2015-07-19","value":14.8},{"date":"2015-07-18","value":14.9},{"date":"2015-07-12","value":14.9},{"date":"2015-07-08","value":14.9},{"date":"2015-06-29","value":14.3},{"date":"2015-06-21","value":14.5},{"date":"2015-06-18","value":14.7},{"date":"2015-06-09","value":15},{"date":"2015-06-08","value":14.1},{"date":"2014-12-06","value":13.4},{"date":"2014-09-10","value":13.1},{"date":"2014-08-01","value":14.2},{"date":"2014-07-07","value":15},{"date":"2014-05-31","value":14},{"date":"2014-05-24","value":15},{"date":"2014-05-14","value":15},{"date":"2014-05-13","value":14},{"date":"2014-05-08","value":14.5},{"date":"2014-05-02","value":15}];

var margin = {top: 30, right: 20, bottom: 30, left: 50},
	overlayW = $('.chart').innerWidth(),
	overlayH = $('.chart').innerHeight(),
	width = overlayW,
	height = 250 - margin.top - margin.bottom,

	parseDate = d3.time.format("%Y-%m-%d").parse,
	bisectDate = d3.bisector(function(d) { return d.date; }).left,
	formatValue = d3.format(",.2f");

var x = d3.time.scale()
	.range([0, width]);

var y = d3.scale.linear()
	.range([height, 0]);

var xAxis = d3.svg.axis()
	.scale(x)
	.tickSize(0)
	.tickValues(x.domain())

	.orient("bottom")
	.tickFormat(d3.time.format("%b"));

var yAxis = d3.svg.axis()
	.scale(y)
	.tickSize(0)
	.ticks(5)
	.orient("left");

var area = d3.svg.area()
	.x(function(d) { return x(d.date); })
	.y0(height)
	.y1(function(d) { return y(d.value); });

var svg = d3.select(".drawn").append("svg")
		.attr("width", width)
		.attr("height", height + margin.top + margin.bottom)
	.append("g")
		.attr("transform", "translate(-15,30)");

enter(entries);






function enter(data) {

	data.forEach(function(d) {
		d.date = parseDate(d.date);
		d.value = +d.value;
	});

	data.sort(function(a, b) {
		return a.date - b.date;
	});

  x.domain([data[0].date, data[data.length - 1].date]);
  y.domain(d3.extent(data, function(d) { return d.value; }));
  //y.domain(d3.extent(data, function(d) { return d.value; }));
  var e = d3.extent(data, function(d) { return d.value; });
  



  svg.append("path")
	  .datum(data)
	  .attr("class", "area")
	  .attr("d", area);





  svg.append("g")
	  .attr("class", "x axis")
	  .attr("transform", "translate(0," + height + ")")
	  .call(xAxis);

  svg.append("g")
	  .attr("class", "y axis")
		.attr("transform", "translate(" + width + ",0)")
	  .call(yAxis);



}
.chart {display:block;background:#4BAC4E;height:250px;width:600px;}

.axis path,
.axis line {
  fill: none;
  stroke: rgba(0, 0, 0, .3);
  shape-rendering: crispEdges;
}

text {
  font: 400 11px mono;
  letter-spacing: .3px;
  text-transform: uppercase;
  fill: rgba(0, 0, 0, .3);
}

.domain {
  display: none;
}

.area {
  fill: black;
  stroke: none;
  stroke-width: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="chart">
  <div class="drawn"></div>
</div>

https://jsfiddle.net/5kesyqu0/3/

like image 540
ditto Avatar asked Oct 18 '25 10:10

ditto


1 Answers

You can achieve this making a linear gradient like this:

//make defs and add the linear gradient
var lg = svgmain.append("defs").append("linearGradient")
.attr("id", "mygrad")//id of the gradient
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "0%")
.attr("y2", "100%")//since its a vertical linear gradient 
;
lg.append("stop")
.attr("offset", "0%")
.style("stop-color", "red")//end in red
.style("stop-opacity", 1)

lg.append("stop")
.attr("offset", "100%")
.style("stop-color", "blue")//start in blue
.style("stop-opacity", 1)

Then add this gradient to the fill of your path.

  svg.append("path")
      .datum(data)
      .attr("class", "area")
      .attr("d", area)
        .style("fill", "url(#mygrad)");//id of the gradient for fill

Working code here.

Another example as per your requirement (So that the bottom of the gradient is transparent, and the top of the area fill is red).

like image 146
Cyril Cherian Avatar answered Oct 20 '25 00:10

Cyril Cherian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!