最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - d3 filling an area with a gradient - Stack Overflow

programmeradmin3浏览0评论

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: - 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=".4.11/d3.min.js"></script>
<script src=".1.1/jquery.min.js"></script>
<div class="chart">
  <div class="drawn"></div>
</div>

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/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./ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="chart">
  <div class="drawn"></div>
</div>

https://jsfiddle/5kesyqu0/3/

Share Improve this question edited Mar 7, 2016 at 6:02 Tim Penner 3,54122 silver badges36 bronze badges asked Mar 6, 2016 at 23:10 dittoditto 6,28710 gold badges58 silver badges91 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 12

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).

I might be late to this party, but exactly the same result I wanted to acplish recently. While browsing internet I found this SO question and decided to post my own answer. Looks like no one else ever posted this solution yet. So, here goes:

let svgDefs = svg.append('defs');    

let filterBlur = svgDefs
    .append("filter")
    .attr('id', 'blur')
    .attr("x", "0")
    .attr("y", "0")
    .append("feGaussianBlur")
    .attr("in", "SourceGraphic")
    .attr("stdDeviation", 20);
    
let mask = svgDefs
    .append("mask")
    .attr('id', 'mask')
    .datum(data)
    .append("path")
    .attr("fill", "#fff")
    .attr("d", d3.svg.area()
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.value); }));

svg.append("path")
    .datum(data)
    .attr("stroke", "#274EF6")
    .attr("stroke-width", 15)
    .attr("fill", "none")
    .attr("filter", "url(#blur)")
    .attr("mask", "url(#mask)")
    .attr("class", "line-blur")
    .attr("d", d3.svg.line()
        .x(function (d) {
            return x(d.date);
        })
        .y(function (d) {
            return y(d.value);
        }));

Basic idea is not to use area chart, instead use line chart with pretty wide line-width. Then, apply blur effect to it and then mask property, where path of the mask will be created by that area, which we discarded at first step. Hope it is helpful

https://jsfiddle/RomanTourdyiev/dzcfsh1x/5/

发布评论

评论列表(0)

  1. 暂无评论