问题描述
我有一个项目需要重新创建渐变图表。我在网上找到了一些关于如何重新创建渐变面积图的文档:Documentation。
主要问题是我无法让这段代码工作。我已将其更改为使用我的数据,但图表不会显示。轴被正确渲染。但是图表本身没有显示出来。
我已将 var x = d3.scaleTime().range([0,width]);
替换为 var x = d3.scaleBand().range([0,width]);
,因为在文档中他们使用的是 x 轴上的 Date 对象。
没有控制台错误,但图表不会简单地显示出来。代码看起来很简单,但我似乎无法理解它有什么问题。我对 D3.js 非常陌生,并且仍在学习很多关于该库的知识。
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://unpkg.com/vue"></script>
<script src="https://d3js.org/d3.v6.js"></script>
</head>
<body>
<div class="p-3 flex flex-col" id="one">
<div class="w-full flex-1">
<div id="chart"></div>
</div>
</div>
<script>
new Vue({
el: '#one',data: {
type: Array,required: true,},mounted() {
// set the dimensions and margins of the graph
var margin = { top: 20,right: 20,bottom: 30,left: 50 },width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3
.select("#chart")
.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 + ")");
var data = [
{
date: "Jan",value: 1507
},{
date: "Feb",value: 1600
},{
date: "Mar",value: 1281
},{
date: "Apr",value: 1898
},{
date: "May",value: 1749
},{
date: "June",value: 1270
},{
date: "July",value: 1712
},{
date: "Aug",{
date: "Sept",value: 1257
},{
date: "Oct",{
date: "Nov",{
date: "Dec",value: 1257
}
];
// set the ranges
var x = d3.scaleBand().range([0,width]);
var y = d3.scaleLinear().rangeRound([height,0]);
// define the area
var area = d3
.area()
.x(function(d) {
console.log(d.date);
console.log(x.domain());
return x(d.date);
})
.y(function(d) {
console.log(d.value);
console.log(y.domain());
return y(d.value);
});
x.domain(
data.map(function(d) {
return d.date;
})
);
y.domain([
0,d3.max(data,function(d) {
return d.value;
})
]);
// set the gradient
svg
.append("linearGradient")
.attr("id","area-gradient")
.attr("gradientUnits","userSpaceOnUse")
.attr("x1",0)
.attr("y1",y(0))
.attr("x2",0)
.attr("y2",y(1000))
.selectAll("stop")
.data([
{ offset: "0%",color: "red" },{ offset: "30%",{ offset: "45%",color: "black" },{ offset: "55%",{ offset: "60%",color: "lawngreen" },{ offset: "100%",color: "lawngreen" }
])
.enter()
.append("stop")
.attr("offset",function(d) {
return d.offset;
})
.attr("stop-color",function(d) {
return d.color;
});
// Add the area.
svg
.append("path")
.datum(data)
.attr("class","area")
.attr("d",area);
// Add the X Axis
svg
.append("g")
.attr("transform","translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g").call(d3.axisLeft(y));
}
});
</script>
</body>
</html>
解决方法
两件事。
首先,您错过了设置 css
以填充渐变的 path
:
.area {
fill: url(#area-gradient);
stroke-width: 0px;
}
其次,为了绘制“区域”,d3.area
生成器需要 .y0
和 .y1
accessors。这就是从这里到那里填充的意思。
var area = d3
.area()
.x(function (d) {
return x(d.date);
})
.y1(function (d) {
return y(d.value);
})
.y0(height);
运行片段:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://unpkg.com/vue"></script>
<script src="https://d3js.org/d3.v6.js"></script>
<style>
.area {
fill: url(#area-gradient);
stroke-width: 0px;
}
</style>
</head>
<body>
<div class="p-3 flex flex-col" id="one">
<div class="w-full flex-1">
<div id="chart"></div>
</div>
</div>
<script>
new Vue({
el: '#one',data: {
type: Array,required: true,},mounted() {
// set the dimensions and margins of the graph
var margin = { top: 20,right: 20,bottom: 30,left: 50 },width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3
.select('#chart')
.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 + ')'
);
var data = [
{
date: 'Jan',value: 1507,{
date: 'Feb',value: 1600,{
date: 'Mar',value: 1281,{
date: 'Apr',value: 1898,{
date: 'May',value: 1749,{
date: 'June',value: 1270,{
date: 'July',value: 1712,{
date: 'Aug',{
date: 'Sept',value: 1257,{
date: 'Oct',{
date: 'Nov',{
date: 'Dec',];
// set the ranges
var x = d3.scaleBand().range([0,width]);
var y = d3.scaleLinear().rangeRound([height,0]);
// define the area
var area = d3
.area()
.x(function (d) {
return x(d.date);
})
.y1(function (d) {
return y(d.value);
})
.y0(height);
x.domain(
data.map(function (d) {
return d.date;
})
);
y.domain([
0,d3.max(data,function (d) {
return d.value;
}),]);
// set the gradient
svg
.append('linearGradient')
.attr('id','area-gradient')
.attr('gradientUnits','userSpaceOnUse')
.attr('x1',0)
.attr('y1',y(0))
.attr('x2',0)
.attr('y2',y(1000))
.selectAll('stop')
.data([
{ offset: '0%',color: 'red' },{ offset: '30%',{ offset: '45%',color: 'black' },{ offset: '55%',{ offset: '60%',color: 'lawngreen' },{ offset: '100%',])
.enter()
.append('stop')
.attr('offset',function (d) {
return d.offset;
})
.attr('stop-color',function (d) {
return d.color;
});
// Add the area.
svg.append('path').datum(data).attr('class','area').attr('d',area);
// Add the X Axis
svg
.append('g')
.attr('transform','translate(0,' + height + ')')
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append('g').call(d3.axisLeft(y));
},});
</script>
</body>
</html>