本文介绍了d3折线图的动画区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试转换d3区域.
I am trying a transition of a d3 area.
这是我尝试遵循的示例链接.它正在从数据线路径的外部进行区域转换.
Here's the example link which I tried to follow. It is doing the area transition from outside the data line path.
我需要这种过渡是从数据线区域内部进行的,并且随着数据线的进行,区域过渡也应该进行.
I need this transition to be from inside the data line area, and as the data line progresses the area transition should progress.
这是StackBlitz 链接.
Here's the StackBlitz link.
这是代码:
maxAllowed = 0;
graphData = [
{
hrCount: 4,
adjCount: 2
},
{
hrCount: 8,
adjCount: 5
},
{
hrCount: 12,
adjCount: 10
},
{
hrCount: 16,
adjCount: 13
},
{
hrCount: 20,
adjCount: 19
},
{
hrCount: 24,
adjCount: 25
},
{
hrCount: 28,
adjCount: 33
},
{
hrCount: 32,
adjCount: 37
},
{
hrCount: 36,
adjCount: 40
},
{
hrCount: 40,
adjCount: 42
},
{
hrCount: 44,
adjCount: 44
},
{
hrCount: 48,
adjCount: 47
},
{
hrCount: 52,
adjCount: 48
},
{
hrCount: 56,
adjCount: 50
},
{
hrCount: 60,
adjCount: 53
}
];
margin: {
top: number;
right: number;
bottom: number;
left: number;
};
width: number;
height: number;
g: any;
xScale: any;
yScale: any;
xAxis: any;
yAxis: any;
ngOnInit() {
this.maxAllowed = d3.max(this.graphData, (d: any) => d.hrCount) + 5;
this.drawLineGraph();
}
drawLineGraph() {
this.margin = {
top: 5,
right: 10,
bottom: 20,
left: 25
};
this.width =
document.getElementById("svgcontainer").parentElement.offsetWidth -
(this.margin.left + this.margin.right);
this.height =
document.getElementById("svgcontainer").parentElement.offsetHeight -
(this.margin.top + this.margin.bottom) +
80;
// Remove any existing SVG
d3.select("#svgcontainer")
.selectAll("svg > *")
.remove();
this.createGroup();
this.createScale();
this.createYAxisGridLine();
this.createShadowEffect();
this.createAxis();
this.createDataPathAndDots();
// Removing y-axis 0 tick-line
d3.selectAll(".y-axis-tick .tick line").each(function(d, i) {
if (i === 0) {
this.remove();
}
});
}
createGroup(): void {
this.g = d3
.select("#svgcontainer")
.append("svg")
.attr("width", this.width + this.margin.left + this.margin.right)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.style("background-color", "#0e1a30")
.append("g")
.attr(
"transform",
"translate(" + this.margin.left + ", " + this.margin.top + ")"
);
}
createScale(): void {
// x-scale
this.xScale = d3
.scaleBand()
.domain(this.graphData.map((d: any) => d.hrCount))
.range([0, this.width]);
// y-scale
this.yScale = d3
.scaleLinear()
.domain([0, this.maxAllowed])
.range([this.height, 0]);
}
createYAxisGridLine(): void {
this.g
.append("g")
.attr("class", "y-axis-grid")
.call(
d3
.axisLeft(this.yScale)
.tickSize(-this.width)
.tickFormat("")
.ticks(5)
);
}
createShadowEffect(): void {
const colorArray = [
["rgb(8, 141, 218)", "0.8"],
["rgb(8, 141, 218)", "0.5"],
["rgb(8, 141, 218)", "0"]
];
const defs = this.g.append("defs");
const grad = defs
.append("linearGradient")
.attr("id", "grad")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "0%")
.attr("y2", "100%")
.attr("gradientTransform", "rotate(-15)");
grad
.selectAll("stop")
.data(colorArray)
.enter()
.append("stop")
.style("stop-color", (d: any) => {
return d[0];
})
.style("stop-opacity", (d: any) => {
return d[1];
})
.attr("offset", (d: any, i: any) => {
return 100 * (i / 2) + "%";
});
const area = (datum, boolean) => {
return d3
.area()
.y0(this.height)
.y1((d: any) => this.yScale(d.adjCount))
.x((d: any) =>
boolean ? this.xScale(d.hrCount) + this.xScale.bandwidth() / 2 : 0
)(datum);
};
this.g
.append("path")
.attr("d", area(this.graphData, false))
.attr("fill", "url(#grad)")
.transition()
.duration(5000)
.attr("d", area(this.graphData, true));
}
createAxis(): void {
// x-axis
this.xAxis = d3.axisBottom(this.xScale).tickSizeOuter(0);
this.g
.append("g")
.attr("transform", "translate(0, " + this.height + ")")
.attr("class", "graph-axis")
.call(this.xAxis.scale(this.xScale))
.append("text")
.attr("x", this.width)
.attr("y", -6)
.attr("text-anchor", "end")
.attr("font", "10px sans-serif")
.attr("letter-spacing", "1px")
.attr("fill", "#8997b1")
.text("Hours");
// y-axis
this.yAxis = d3
.axisLeft(this.yScale)
.ticks(5)
.tickSizeOuter(0);
this.g
.append("g")
.attr("class", "graph-axis y-axis-tick")
.call(this.yAxis.scale(this.yScale))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.attr("font", "10px sans-serif")
.attr("letter-spacing", "1px")
.attr("fill", "#8997b1")
.text("Adjusters");
}
createDataPathAndDots(): void {
const line = d3
.line()
.x((d: any) => this.xScale(d.hrCount) + this.xScale.bandwidth() / 2)
.y((d: any) => this.yScale(d.adjCount));
const path = this.g
.append("path")
.attr("fill", "none")
.attr("stroke", "#088dda")
.attr("stroke-width", "2px")
.attr("d", line(this.graphData));
this.createPathTransition(path);
// Data dots
this.g
.selectAll("line-circle")
.data(this.graphData)
.enter()
.append("circle")
.attr("r", 4)
.attr("fill", (d: any) => {
if (d.hrCount === 0) {
return "none";
} else {
return "#088dda";
}
})
.attr(
"cx",
(d: any) => this.xScale(d.hrCount) + this.xScale.bandwidth() / 2
)
.attr("cy", (d: any) => this.yScale(d.adjCount));
}
createPathTransition(path: any): void {
const totLength = path.node().getTotalLength();
path
.attr("stroke-dasharray", totLength + " " + totLength)
.attr("stroke-dashoffset", totLength);
path
.transition()
.duration(5000)
.attr("stroke-dashoffset", 0);
}
推荐答案
这是一种潜在的解决方案.首先,我修改了您的区域生成器,如下所示:
Here's one potential solution. First, I modified your area generator like so:
const area = d3.area()
.y0(this.height)
.y1((d: any) => d.x)
.x((d: any) => d.y );
然后我将区域转换设置为:
Then I set up the area transition as:
this.g
.append("path")
.attr("fill", "url(#grad)")
.transition()
.duration(5000)
.attrTween("d", function(d){
var p = d3.select(".line").node(), // find the line graph
l = p.getTotalLength(), // get length
i = d3.interpolate(0,l), // interpolator over length
dAtT = []; // array to hold accumulated datapoints
return function(t) {
dAtT.push(p.getPointAtLength(i(t))) // on every iteration get a point on the line
return area(dAtT); // draw area
};
});
更新了 stackblitz .
这篇关于d3折线图的动画区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!