edit image 我正在使用d3 v4。我在其中创建了区域和折线图。数据形成是。 图表=> [1,4,5,2.4,6] line => [3,3,3,3,3]
现在我的要求是在折线图下面,区域图应该有不同的颜色。
如果还有其他库可以做到这一点,那么也建议。 这是我绘制线条和面积图的功能。 所以如果 dailyConsValue> targetConsValue?没有颜色' :'显示颜色' dailydate是年份[2017年1月 - 2017年12月] =>这是动态的。
以下是我的代码:
function drawGraph(drawData, highlightedData, first, last) {
let margin, width, height, parseDate, xScale, yScale, area,
dailyConsumption, targetConsumption, svg;
margin = {
top: 10,
right: 60,
bottom: 10,
left: 60
},
width = document.querySelector('#graph').clientWidth - margin.left - margin.right,
height = document.querySelector('#graph').clientHeight - margin.top - margin.bottom;
parseDate = d3.timeParse('%b %Y');
// x axis
xScale = d3.scaleTime().domain([parseDate(first), parseDate(last)]).range([0, width]);
// y axis
yScale = d3.scaleLinear().domain([-1, 2 + Math.max.apply(this, drawData.map(function(o){return o.dailyConsValue; }))])
.range([height, 0]);
area = d3.area()
.x(function(d) { return xScale(d['dailyDate']); })
.y0(function(d) { return yScale(d['targetConsValue']); })
.y1(function(d) { return yScale(d['dailyConsValue']); });
// define the line
dailyConsumption = d3.line().x(function(d) {return xScale(d['dailyDate']); })
.y(function(d) {return yScale(d['dailyConsValue']); });
targetConsumption = d3.line().x(function(d) {return xScale(d['dailyDate']); })
.y(function(d) {return yScale(d['targetConsValue']); });
svg = d3.select('#graph').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 + ')');
// add axis
svg.append('g')
.attr('transform', 'translate(0,0)').attr('class', 'Xaxis')
.call(d3.axisTop(xScale).ticks(drawData.length).tickSize(-innerHeight).tickFormat(d3.timeFormat('%b %Y')));
svg.append('g').attr('class', 'Yaxis')
.call(d3.axisLeft(yScale).tickSize(0));
// Prepare data
drawData.forEach(function( d ) {
d['dailyDate'] = parseDate( d['dailyDate'] );
d['targetConsValue'] = d['targetConsValue'];
d['dailyConsValue'] = d['dailyConsValue'];
} );
highlightedData.forEach(function( d ) {
d['dailyDate'] = parseDate( d['dailyDate'] );
d['dailyConsValue'] = d['dailyConsValue'];
d['active'] = d['active'];
} );
// add the area
svg.append('path').data([drawData]).attr('class', 'area')
.attr('d', area)
.transition().duration(2500).attrTween( 'd', this.tween( drawData, area ) );
// add data for first line
svg.append('path')
.data([drawData])
.attr('class', 'daily').attr('d', targetConsumption).transition()
.duration(2500).delay(1500 / 2).attrTween( 'd', this.tween( drawData, targetConsumption ) );
// add data for futureConsumption
svg.append('path')
.data([drawData])
.attr('class', 'target').attr('data-legend', 'CST')
.attr('d', dailyConsumption);
createLengends(drawData);
drawCircle(drawData, '10', '#037DA6');
drawCircle(drawData, '5', '#003A54');
/**
* legends start
* @param datalegendsData
*/
function createLengends(datalegendsData) {
let legend;
legend = svg.selectAll('.legend').data([datalegendsData])
.enter().append('g').attr('class', 'legend')
.attr('transform', function(d, i) { return 'translate(0,' + i * 20 + ')'; });
// making a line for legend
legend.append('line')
.attr('x1', width - 335).attr('x2', width - 305).attr('y1', height - 1)
.attr('y2', height - 1).style('stroke', '5,5').style('stroke', '#4682B4');
legend.append('text').attr('x', width - 300).attr('y', height - 1)
.attr('dy', '.35em').style('text-anchor', 'start').text('IST Verbrauch WOB')
.style('fill', '#666').style('font-weight', 'normal');
legend.append('line').attr('x1', width - 130).attr('x2', width - 100)
.attr('y1', height - 1).attr('y2', height - 1).style('stroke-dasharray', '5,5')
.style('stroke', '#003A54');
legend.append('text').attr('x', width - 96).attr('y', height - 1).attr('dy', '.35em')
.style('text-anchor', 'start').text('CST Sollwert').style('fill', '#666')
.style('font-weight', 'normal');
}
// legends end
/**
* highlighted data points start
* @param data
* @param r
* @param color
*/
function drawCircle(data, r, color) {
let tooltip;
tooltip = d3.select('#graph').append('div')
.attr('class', 'tooltip').style('display', 'none');
svg.selectAll('.dot').data(data).enter().append('circle') // Uses the enter().append() method
.attr('class', 'circle_' + r).attr('cx', function(d) { return xScale(d['dailyDate']); })
.attr('cy', function(d) {return yScale(d['dailyConsValue']); }).attr('r', r).attr('fill', color)
.on( 'mouseover', function( d) {
let arr, date;
d3.select( this ).classed('circle circle__highlighted', true);
d['active'] = true;
tooltip.transition().duration(200).style('display', 'block');
arr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
date = arr[d['dailyDate'].getMonth()] + ', ' + d['dailyDate'].getFullYear();
tooltip.html('Month ' + date + '<br/> Consumption- ' + d['dailyConsValue'] + ' unit')
.style('left', (parseInt(this.getAttribute('cx'), 10) + 70) + 'px').style('top', (this.getAttribute('cy')) + 'px');
/*tooltip.html('Month ' + date + '<br/> Consumption- ' + d['dailyConsValue'] + ' unit')
.style('left', (d3.event.offsetX + 20) + 'px').style('top', (d3.event.offsetY - 28) + 'px');*/
} ).on( 'mouseout', function( d ) {
d3.selectAll('.circle').classed('circle', true).classed('circle__highlighted', false);
d['active'] = false;
tooltip.transition().duration(500).style('display', 'none');
} );
}
// highlighted data points end
}
提前致谢。
答案 0 :(得分:0)
在你的style fill
中创建一个函数并比较这两个值并根据条件返回颜色,如下所示:
svg.append('path')
.data([drawData]).attr('class', 'area')
.attr('d', area)
.style('fill', function(d){
for (i in d) {
if (d[i]['dailyConsValue'] < d[i]['targetConsValue']) {
return "green"
} else {
return "blue"
}
}
})
.transition().duration(2500)
.attrTween( 'd', this.tween( drawData, area ) );
这将仅基于数据的最后一个值。如果您想根据条件在图表的每个位置使用不同的颜色,那么就我所知,您必须创建一个具有多个颜色停止的linearGradient
(动态)。
现在要创建一个linearGradient
,我使用d3创建了一个线性比例来计算颜色停止的偏移量并根据您的条件指定颜色。要动态创建linearGradient
,请参阅此fiddle