如何解决在面积图d3中将一条线附加到路径的末端
我正在尝试在面积图路径的末尾添加一条线。我所在地区最困难的部分是动画。我有一个clipPath,其宽度从width: 0
转换为width: 960
,并且末尾的行也随之而行,因此应该保持同步。此外,该行顶部的文本也需要不断更新。
所需的输出:
我最初的想法是建立一个图表区域并添加一个clipPath,然后在该区域图内添加一个条形图,以便我可以根据附加的条形更新文本,但是条形图不在我的区域图内。将条形图放置在面积图内是我做错了什么,还是有更好的解决方案?
// Area chart width and height
const width1 = 1000,height1 = 100;
// Define x and y scale for area chart
const xScale1 = d3.scaleTime().range([0,width1]);
const yScale1 = d3.scaleLinear().range([height1,0]);
// Define x and y range for bar chart
let xScale2 = d3.scaleBand().range([0,width1]);
let yScale2 = d3.scaleLinear().range([height1,0]);
// Add SVG to #areachart
const svg1 = d3
.select('#areachart')
.append('svg')
.attr('viewBox',`0 0 ${width1} ${height1}`)
.attr('transform','translate(' + 0 + ',' + -50 + ')');
const g1 = svg1.append('g');
// Fetch data
d3.json(
'https://api.coronavirus.data.gov.uk/v1/data?filters=areaName=United%2520Kingdom;areaType=overview&structure=%7B%22areaType%22:%22areaType%22,%22areaName%22:%22areaName%22,%22areaCode%22:%22areaCode%22,%22date%22:%22date%22,%22newCasesByPublishDate%22:%22newCasesByPublishDate%22,%22cumCasesByPublishDate%22:%22cumCasesByPublishDate%22%7D&format=json'
)
.then(function(data) {
console.log('DATES SLICED ----->',data.data.slice(30,281));
//Define xScale1 & yScale1 domain after data loaded
yScale1.domain([
0,d3.max(data.data,function(d) {
return +d.cumCasesByPublishDate;
}),]);
xScale1.domain(
d3.extent(data.data,function(d) {
return new Date(d.date);
})
);
// Area generator
const area = d3
.area()
.curve(d3.curveStepAfter)
.x((d) => xScale1(new Date(d.date)))
.y1((d) => yScale1(+d.cumCasesByPublishDate))
.y0(yScale1(0));
g1.append('path')
.datum(data.data.slice(30,200))
.attr('d',area)
.classed('placeholder-layer',true)
.style('fill','#dadada')
.style('opacity','0.3');
// clipPath for areachart fill animation
const clip = g1.append('clipPath').attr('id','clip');
const clipRect = clip.append('rect').attr('width',0).attr('height',750);
g1.append('path')
.datum(data.data.slice(30,area)
.attr('clip-path','url(#clip)')
.classed('overlay-layer','yellow')
.style('opacity','0.3');
g1.append('line').attr('stroke-width',960).style('stroke','yellow');
clipRect
.transition()
.duration(10000)
.ease(d3.easeLinear)
.attr('width',960);
//x and y domain for bar chart
xScale2.domain(data.data.slice(30,200).map((d) => new Date(d.date)));
yScale2.domain([
0,]);
g1.selectAll('rect')
.data(data.data.slice(30,200))
.enter()
.append('rect')
.style('fill','red')
.attr('width',xScale2.bandwidth() * 10)
.attr('height',(d) => yScale2(+d.cumCasesByPublishDate))
.attr('x',0)
.attr('y',function(d) {
return yScale2(+d.cumCasesByPublishDate);
})
.transition()
.delay(function(d,i) {
return i * 30;
})
.attr('x',function(d) {
return xScale2(new Date(d.date));
})
.duration(100);
})
// if there's an error,log it
.catch((error) => console.log(error));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<section id="map">
<div id="visualisation-container">
<div id="visualisation"></div>
<div id="areachart"></div>
</div>
</section>
解决方法
我只用一条线,没有横杠,然后将transition.tween
与d3.interpolateDate
一起使用来进行文本更改。
// Area chart width and height
const width1 = 800,height1 = 250,marginBottom = 50
// Define x and y scale for area chart
const xScale1 = d3.scaleTime().range([0,width1]);
const yScale1 = d3.scaleLinear().range([height1,marginBottom]);
// Define x and y range for bar chart
let xScale2 = d3.scaleBand().range([0,width1]);
let yScale2 = d3.scaleLinear().range([height1,marginBottom]);
// Add SVG to #areachart
const svg1 = d3
.select('#areachart')
.append('svg')
.attr('width',width1)
.attr('height',height1);
const g1 = svg1.append('g');
// Fetch data
d3.json(
'https://api.coronavirus.data.gov.uk/v1/data?filters=areaName=United%2520Kingdom;areaType=overview&structure=%7B%22areaType%22:%22areaType%22,%22areaName%22:%22areaName%22,%22areaCode%22:%22areaCode%22,%22date%22:%22date%22,%22newCasesByPublishDate%22:%22newCasesByPublishDate%22,%22cumCasesByPublishDate%22:%22cumCasesByPublishDate%22%7D&format=json'
)
.then(data => {
data.data.forEach(d => {
d.cumCasesByPublishDate = +d.cumCasesByPublishDate;
d.date = new Date(d.date);
});
return data.data.slice(30,200);
})
.then(function(data) {
//Define xScale1 & yScale1 domain after data loaded
yScale1.domain([
0,d3.max(data,d => d.cumCasesByPublishDate),]);
xScale1.domain(
d3.extent(data,d => d.date)
);
// Area generator
const area = d3
.area()
.curve(d3.curveStepAfter)
.x((d) => xScale1(d.date))
.y1((d) => yScale1(d.cumCasesByPublishDate))
.y0(yScale1(0));
g1.append('path')
.datum(data)
.attr('d',area)
.classed('placeholder-layer',true)
.style('fill','#dadada')
.style('opacity','0.3');
// clipPath for areachart fill animation
const clip = g1.append('clipPath').attr('id','clip');
const clipRect = clip.append('rect').attr('width',0).attr('height',750);
g1.append('path')
.datum(data)
.attr('d',area)
.attr('clip-path','url(#clip)')
.classed('overlay-layer','yellow')
.style('opacity','0.3');
const format = d3.timeFormat("%B %d,%Y");
const duration = 10000;
g1.append('line')
.attr('stroke-width',5)
.style('stroke','black')
.attr('x1',xScale1.range()[0])
.attr('x2',xScale1.range()[0])
.attr('y1',yScale1.range()[0])
.attr('y2',yScale1.range()[1])
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr('x1',xScale1.range()[1])
.attr('x2',xScale1.range()[1])
g1.append('text')
.attr('x',xScale1.range()[0])
.attr('y',marginBottom / 2)
.attr('text-anchor','middle')
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attr('x',xScale1.range()[1])
.tween('text',function() {
const i = d3.interpolateDate(xScale1.domain()[0],xScale1.domain()[1]);
return (t) => d3.select(this).text(format(i(t)));
})
})
// if there's an error,log it
.catch((error) => console.log(error));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<section id="map">
<div id="visualisation-container">
<div id="visualisation"></div>
<div id="areachart"></div>
</div>
</section>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。