我无法创建并排的条形图。
我将在这里放置我的代码和一张图像,这些图像以不同的颜色并排放置。我是D3.js的新手,不知道为什么会这样。
现在的图表:
在我的jsonFile中,我有两个推销员,其中显示了每个推销员的销售历史。例如,我需要在一月份显示卖方A和卖方B的上一年的销售历史记录,但是正如您在上图中所看到的,这不是正在发生的情况。酒吧在错误的地方。
我的HTML代码:
.
var sales = [
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jan",
"Vendas_Ano": 21611.950000000004,
"Vendas_Ant": 16033.31
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Fev",
"Vendas_Ano": 48108.08,
"Vendas_Ant": 51142.299999999996
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Mar",
"Vendas_Ano": 13427.280000000004,
"Vendas_Ant": 21274.129999999997
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Apr",
"Vendas_Ano": 28553.83,
"Vendas_Ant": 15228.569999999998
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Mai",
"Vendas_Ano": 19639.59,
"Vendas_Ant": 10291.359999999999
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jun",
"Vendas_Ano": 22530.840000000007,
"Vendas_Ant": 21905.29
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jul",
"Vendas_Ano": 20216.759999999995,
"Vendas_Ant": 8276
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Ago",
"Vendas_Ano": 39832.04,
"Vendas_Ant": 49810.810000000005
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Set",
"Vendas_Ano": 12861.52,
"Vendas_Ant": 24425.32
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Out",
"Vendas_Ano": 9227.34,
"Vendas_Ant": 17804.65
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Nov",
"Vendas_Ano": 0,
"Vendas_Ant": 9993.34
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Dez",
"Vendas_Ano": 0,
"Vendas_Ant": 36568.7
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jan",
"Vendas_Ano": 22681.14,
"Vendas_Ant": 28587.71
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Fev",
"Vendas_Ano": 31382.11,
"Vendas_Ant": 37637.420000000006
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Mar",
"Vendas_Ano": 32453.779999999995,
"Vendas_Ant": 32993.12
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Apr",
"Vendas_Ano": 23445.4,
"Vendas_Ant": 30835.75
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Mai",
"Vendas_Ano": 16471.71,
"Vendas_Ant": 18028.07
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jun",
"Vendas_Ano": 11617.470000000001,
"Vendas_Ant": 22651.53
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jul",
"Vendas_Ano": 24699.44,
"Vendas_Ant": 34152.28999999999
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Ago",
"Vendas_Ano": 35476.94000000001,
"Vendas_Ant": 22069.699999999997
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Set",
"Vendas_Ano": 37462.92,
"Vendas_Ant": 23120.08
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Out",
"Vendas_Ano": 22042.140000000003,
"Vendas_Ant": 28449.95
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Nov",
"Vendas_Ano": 0,
"Vendas_Ant": 30755.050000000003
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Dez",
"Vendas_Ano": 0,
"Vendas_Ant": 22838.64
}
]
var charnecaData = [];
var joaoData = [];
for (var i = 0; i < sales.length; i++) {
if (sales[i]["vendnm"] === "CHARNECA") {
charnecaData.push(sales[i]);
} else {
joaoData.push(sales[i]);
}
}
//functions for toggling between data
function change(value) {
if (value === 'lastYear') {
update(charnecaData);
} else if (value === 'currentYear') {
update(joaoData);
} else {
update(sales);
}
}
function update(data) {
xChart.domain(data.map(function (d) { return d.MonthAbrev; }));
yChart.domain([0, d3.max(data, function (d) { return +d.Vendas_Ant; })]);
var barWidth = width / data.length;
var bars = chart.selectAll(".bar")
.remove()
.exit()
.data(data)
bars.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function (d, i) { return i * barWidth + 1 })
.attr("y", function (d) { return yChart(d.Vendas_Ant); })
.attr("height", function (d) { return height - yChart(d.Vendas_Ant); })
.attr("width", barWidth - 5)
.attr("fill", function (d) {
if (d.vendnm === 'CHARNECA') {
return "rgb(251,180,174)";
} else {
return "rgb(179,205,227)";
}
})
.on("mouseover", function (a) {
chart.append("text")
.attr("class", "title-text")
.style("fill", "rgb(44, 160, 44)")
.text(a.vendnm + ' - ' +
a.MonthAbrev + ' - ' +
Number(Math.round(a.Vendas_Ant * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 }) + '€'
)
.attr("text-anchor", "middle")
.attr("x", 400)
.attr("y", 50);
})
.on("mouseout", function (a) {
chart.select(".title-text").remove();
})
//left axis
chart.select('.y')
.call(yAxis)
//bottom axis
chart.select('.xAxis')
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)";
});
}//end update
var margin = { top: 20, right: 20, bottom: 30, left: 50 };
var width = 600;
var height = 300;
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xChart = d3.scaleBand()
.range([0, width]);
var yChart = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(xChart);
var yAxis = d3.axisLeft(yChart);
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
chart.append("g")
.attr("class", "xAxis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)";
});
update(sales);
正如我所说的,我是D3.js的新手,我正在根据以下代码进行此测试:https://bl.ocks.org/syncopika/f1c9036b0deb058454f825238a95b6be
我已经对其进行了多次比较,以了解自己在做什么错,但我无法解决问题。
预先感谢您的帮助。
答案 0 :(得分:0)
首先scaleBand()
具有为每个点提供宽度的功能:
var barWidth = xChart.bandwidth()/2;
然后,您需要使用xChart()
函数来获取每个数据点的x
坐标,而不是根据特定数据点的索引进行计算。
稍加调整坐标,最终结果将归结为以下代码行:
.attr("x", function (d, i) { return xChart(d.MonthAbrev) + barWidth*((d.vendnm == 'CHARNECA')?0.2:1) })
我希望这会有所帮助,如果不是您要的内容,请告诉我。
var sales = [
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jan",
"Vendas_Ano": 21611.950000000004,
"Vendas_Ant": 16033.31
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Fev",
"Vendas_Ano": 48108.08,
"Vendas_Ant": 51142.299999999996
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Mar",
"Vendas_Ano": 13427.280000000004,
"Vendas_Ant": 21274.129999999997
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Apr",
"Vendas_Ano": 28553.83,
"Vendas_Ant": 15228.569999999998
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Mai",
"Vendas_Ano": 19639.59,
"Vendas_Ant": 10291.359999999999
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jun",
"Vendas_Ano": 22530.840000000007,
"Vendas_Ant": 21905.29
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Jul",
"Vendas_Ano": 20216.759999999995,
"Vendas_Ant": 8276
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Ago",
"Vendas_Ano": 39832.04,
"Vendas_Ant": 49810.810000000005
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Set",
"Vendas_Ano": 12861.52,
"Vendas_Ant": 24425.32
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Out",
"Vendas_Ano": 9227.34,
"Vendas_Ant": 17804.65
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Nov",
"Vendas_Ano": 0,
"Vendas_Ant": 9993.34
},
{
"vendnm": "CHARNECA",
"MonthAbrev": "Dez",
"Vendas_Ano": 0,
"Vendas_Ant": 36568.7
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jan",
"Vendas_Ano": 22681.14,
"Vendas_Ant": 28587.71
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Fev",
"Vendas_Ano": 31382.11,
"Vendas_Ant": 37637.420000000006
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Mar",
"Vendas_Ano": 32453.779999999995,
"Vendas_Ant": 32993.12
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Apr",
"Vendas_Ano": 23445.4,
"Vendas_Ant": 30835.75
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Mai",
"Vendas_Ano": 16471.71,
"Vendas_Ant": 18028.07
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jun",
"Vendas_Ano": 11617.470000000001,
"Vendas_Ant": 22651.53
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Jul",
"Vendas_Ano": 24699.44,
"Vendas_Ant": 34152.28999999999
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Ago",
"Vendas_Ano": 35476.94000000001,
"Vendas_Ant": 22069.699999999997
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Set",
"Vendas_Ano": 37462.92,
"Vendas_Ant": 23120.08
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Out",
"Vendas_Ano": 22042.140000000003,
"Vendas_Ant": 28449.95
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Nov",
"Vendas_Ano": 0,
"Vendas_Ant": 30755.050000000003
},
{
"vendnm": "JOÃO LUIS",
"MonthAbrev": "Dez",
"Vendas_Ano": 0,
"Vendas_Ant": 22838.64
}
]
var charnecaData = [];
var joaoData = [];
for (var i = 0; i < sales.length; i++) {
if (sales[i]["vendnm"] === "CHARNECA") {
charnecaData.push(sales[i]);
} else {
joaoData.push(sales[i]);
}
}
//functions for toggling between data
function change(value) {
if (value === 'lastYear') {
update(charnecaData);
} else if (value === 'currentYear') {
update(joaoData);
} else {
update(sales);
}
}
function update(data) {
xChart.domain(data.map(function (d) { return d.MonthAbrev; }));
yChart.domain([0, d3.max(data, function (d) { return +d.Vendas_Ant; })]);
var barWidth = xChart.bandwidth()/2;
var bars = chart.selectAll(".bar")
.remove()
.exit()
.data(data)
bars.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function (d, i) { return xChart(d.MonthAbrev) + barWidth*((d.vendnm == 'CHARNECA')?0.2:1) })
.attr("y", function (d) { return yChart(d.Vendas_Ant); })
.attr("height", function (d) { return height - yChart(d.Vendas_Ant); })
.attr("width", barWidth - 5)
.attr("fill", function (d) {
if (d.vendnm === 'CHARNECA') {
return "rgb(251,180,174)";
} else {
return "rgb(179,205,227)";
}
})
.on("mouseover", function (a) {
//console.log(a)
chart.append("text")
.attr("class", "title-text")
.style("fill", "rgb(44, 160, 44)")
.text(a.vendnm + ' - ' +
a.MonthAbrev + ' - ' +
Number(Math.round(a.Vendas_Ant * 100) / 100).toLocaleString("es-ES", { minimumFractionDigits: 2 }) + '€'
)
.attr("text-anchor", "middle")
.attr("x", 400)
.attr("y", 50);
})
.on("mouseout", function (a) {
chart.select(".title-text").remove();
})
//left axis
chart.select('.y')
.call(yAxis)
//bottom axis
chart.select('.xAxis')
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)";
});
}//end update
var margin = { top: 20, right: 20, bottom: 30, left: 50 };
var width = 600;
var height = 300;
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xChart = d3.scaleBand()
.range([0, width]);
var yChart = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(xChart);
var yAxis = d3.axisLeft(yChart);
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
chart.append("g")
.attr("class", "xAxis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)";
});
update(sales);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>
<style>
.radio {
text-align: center;
}
.row {
text-align: center;
}
</style>
<body>
<div class='container'>
<div class='row'>
<div class='radio'>
<label class='radio-inline'>
<input type="radio" name="gender" value="lastYear" onclick='change(this.value)'> Last Year
</label>
<label class='radio-inline'>
<input type="radio" name="gender" value="currentYear" onclick='change(this.value)'> Current Year
</label>
<label class='radio-inline'>
<input type="radio" name="gender" value="both" onclick='change(this.value)' checked> Both
</label>
</div>
<svg class='chart'>
</svg>
</div>
</div>
</body>