我试着用d3.js做一个组合图,但我的图形宽度有问题,我遵循这个例子
https://www.d3-graph-gallery.com/graph/barplot_grouped_basicWide.html
使列将条形图分组到我的图表中,但是当我通过控制台显示值x.bandwidth (x.bandwidth =0)时,我的图表就消失了。
这是我的代码图,它的工作是由API调用的,谢谢你的帮助。
const $panel = $(`#${panelUniqueId}`).find('.panel');
$panel.empty();
var data = [
{ name: "01:00", sales: 3500, forecast: 7000 },
{ name: "02:00", sales: 3500, forecast: 7000 },
{ name: "03:00", sales: 3500, forecast: 7000 },
{ name: "04:00", sales: 3500, forecast: 7000 },
{ name: "05:00", sales: 3500, forecast: 7000 },
{ name: "06:00", sales: 3500, forecast: 7000 },
{ name: "07:00", sales: 3500, forecast: 7000 },
{ name: "08:00", sales: 3500, forecast: 7000 },
{ name: "09:00", sales: 3500, forecast: 7000 },
{ name: "10:00", sales: 2800, forecast: 4500 },
{ name: "11:00", sales: 3600, forecast: 3300 },
{ name: "12:00", sales: 1700, forecast: 4700 },
{ name: "13:00", sales: 2200, forecast: 5500 },
{ name: "14:00", sales: 2500, forecast: 6500 },
{ name: "15:00", sales: 1500, forecast: 7500 },
{ name: "16:00", sales: 2000, forecast: 4100 },
{ name: "17:00", sales: 2500, forecast: 8000 },
{ name: "18:00", sales: 3500, forecast: 7000 },
{ name: "19:00", sales: 3500, forecast: 7000 },
{ name: "20:00", sales: 3500, forecast: 7000 },
{ name: "21:00", sales: 3500, forecast: 7000 },
{ name: "22:00", sales: 3500, forecast: 7000 },
{ name: "23:00", sales: 3500, forecast: 7000 },
{ name: "24:00", sales: 3500, forecast: 9000 },
];
if (response.panelTitle === null || response.panelTitle === '') {
$panel = '<div class="main-image" style=" width: 100%; height: 100%;pos"> <div class="row">';
} else {
$panel.append(`<h1 id="POG-LBL-001" style="padding: 1rem; margin-bottom: 0; width: 100%; height: 4.0rem; font-size: 1.5rem;"><p><strong>${response.panelTitle}</strong></p></h1>`);
$panel.append('<div class="main-image" style="margin: 0 1rem 1rem 1rem; width: calc(100% - 2rem); height: calc(100% - 6rem); position:relative; pos"></div>')
}
if (response.url != null || response.url != "") {
$(`#${panelUniqueId}`).find('#POG-LBL-001').on('click', function() {
window.open(response.url);
});
}
var getDatasetFordisplayGraph = response.dataSetForDisplayGraph;
var getDisplaycolors = response.displayColors;
var getComboGraphType = response.comboGraphType;
var getYaxisScalemax = response.yaxisScaleMax;
var getYaxisScalemin = response.yaxisScaleMin;
var getYaxisScalesplit = response.yaxisScaleSplit;
var getGuidedisplayFlag = response.guideDisplayFlg;
var dataLegend;
var dataForGraph = [];
//Custom data to draw map
for (i = 0; i < getDatasetFordisplayGraph.length; i++) {
var map = {};
for (j = 0; j < getDatasetFordisplayGraph[i].length; j++) {
for (const [key, value] of Object.entries(getDatasetFordisplayGraph[i][j])) {
map[`${key}`] = `${value}`;
}
}
dataForGraph.push(map);
}
// var arrayGroupBar = dataForGraph.map(ele => {
// var tempItem = Object.assign({}, ele);
// if (tempItem.time != undefined) {
// delete tempItem.time;
// return tempItem;
// } else if (tempItem.area != undefined) {
// delete tempItem.area;
// return tempItem;
// } else if (tempItem.factory != undefined) {
// delete tempItem.factory;
// return tempItem;
// } else if (tempItem.machine != undefined) {
// delete tempItem.machine;
// return tempItem;
// }
// });
//
// console.log(arrayGroupBar);
dataLegend = getDatasetFordisplayGraph[0].filter(ele => {
if (!ele.time != undefined) {
return !ele.time;
} else if (!ele.area != undefined) {
return !ele.area;
} else if (!ele.factory != undefined) {
return !ele.factory;
} else if (!ele.machine != undefined) {
return !ele.machine;
}
}).map(ele => Object.keys(ele)[0]);
var dataOx = [];
dataOx.push(getYaxisScalemax, getYaxisScalemin, getYaxisScalesplit, getDisplaycolors, getComboGraphType, dataLegend);
//transform column to row
const transpose = a => a[0].map((_, c) => a.map(r => r[c]));
const rows = transpose(dataOx);
var columns = ["max", "min", "split", "color", "type", "legend"];
const assemblyData = (columns, rows) => {
return rows.map((row) => {
return row.reduce((res, field, index) => {
res[columns[index]] = field;
return res
}, {});
});
}
var customedObject = assemblyData(columns, rows);
//console.log(customedObject);
var data = dataForGraph;
d3.select('.main-image').append('div').classed('row', true).style("height", "100%").style("width", "100%").style("margin", "unset")
.append('div').attr('id', 'POG-GRP-002').classed('w-80', true).style("height", "100%");
var margin = { top: 50, right: 100, bottom: 40, left: 140 },
width = $('#POG-GRP-002').width() - margin.left - margin.right,
height = $('#POG-GRP-002').height() - margin.top - margin.bottom,
svg = d3.select('.w-80')
.style('max-width', 'max-content')
.style('height', 'max-content')
.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 dataOx = data.map(function(d) {
// if (d.time != undefined) {
// return d.time;
// } else if (d.area != undefined) {
// return d.area;
// } else if (d.factory != undefined) {
// return d.factory;
// } else if (d.machine != undefined) {
// return d.machine;
// }
// });
var dataOx = d3.map(data, function(d) {
if (d.time != undefined) {
return d.time;
} else if (d.area != undefined) {
return d.area;
} else if (d.factory != undefined) {
return d.factory;
} else if (d.machine != undefined) {
return d.machine;
}
});
console.log(dataOx);
var x = d3.scaleBand()
.domain(dataOx)
.rangeRound([0, width])
.paddingInner(0.05);
var x1 = d3.scaleBand()
.domain(dataLegend)
.rangeRound([0, x.bandwidth()])
.padding([0.05]);
var xAxis = d3.axisBottom(x);
console.log("default domain-range: ", x.domain());
console.log("custom range-range: ", x.range());
console.log("custom innerPadding: ", x.paddingInner());
console.log("custom outerPadding: ", x.paddingOuter());
console.log("Check step = bandwidth+paddingInner: ", xScale.step());
console.log("Check bandWidth: ", x.bandwidth());
svg.append('g')
.attr('id', 'POG-GRP-002-001')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + (height - margin.bottom) + ')')
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-0.8em")
.attr("dy", "-0.6em")
.attr("transform", "rotate(-90)");
var moveOyLeft = 0;
var moveOfRight = 0;
let legend = d3.select('.main-image .row').append("div").attr('id', 'POG-LBL-003').classed("w-20", true).style("padding-top", "4rem");
var arrayLeft = [];
var arrayRight = [];
customedObject.forEach((element) => {
if (element["type"] == 0) {
arrayLeft.push(element);
} else if (element["type"] == 1) {
arrayRight.push(element);
}
});
//console.log(arrayLeft);
//console.log(arrayRight);
var yindex;
var yAxisindex;
// lọc lấy max min và split
const uniques = [...new Set(
arrayLeft.map(x => JSON.stringify((({ max, min, split }) => ({ max, min, split }))(x))))
].map(JSON.parse);
if (uniques.length == 1) {
var maxOne = parseFloat(uniques[0].max);
var minOne = parseFloat(uniques[0].min);
var splitOne = parseFloat(uniques[0].split);
var tickOne = [];
for (var i = minOne; i <= maxOne; i += splitOne) {
tickOne.push(i);
}
d3.max(tickOne) == maxOne ? tickOne.push() : tickOne.push(maxOne);
yindex = d3.scaleLinear().nice().domain([uniques[0].min, uniques[0].max])
.range([height - margin.bottom, 0]);
yAxisindex = d3.axisLeft(yindex).tickValues(tickOne);
svg.append('g')
.attr('id', 'POG-GRP-002-002')
.attr('transform', 'translate(' + moveOyLeft + ',0)')
.attr('class', 'y3-axis'.concat('-dn'))
.attr('stroke', "#FFFF")
.call(yAxisindex)
.selectAll('.tick').attr('stroke', "#FFFF");
}
var itemLengend = [];
arrayLeft.forEach((element, index) => {
var legendUser = element["legend"];
itemLengend.push(legendUser);
if (uniques.length > 1) {
var maxOy = parseFloat(element["max"]);
var minOy = parseFloat(element["min"]);
var splitOy = parseFloat(element["split"]);
var tickCount = [];
for (var i = minOy; i <= maxOy; i += splitOy) {
tickCount.push(i);
}
d3.max(tickCount) == maxOy ? tickCount.push() : tickCount.push(maxOy);
yindex = d3.scaleLinear().nice().domain([element["min"], element["max"]])
.range([height - margin.bottom, 0]);
yAxisindex = d3.axisLeft(yindex).tickValues(tickCount);
svg.append('g')
.attr('id', 'POG-GRP-002-002')
.attr('transform', 'translate(' + moveOyLeft + ',0)')
.attr('class', 'y3-axis'.concat('_' + index))
.attr('stroke', element["color"])
.call(yAxisindex)
.selectAll('.tick text').attr('stroke', element["color"]).attr('fill', element["color"]);
moveOyLeft -= 50;
d3.select("#POG-GRP-002 svg").attr("width", (width + -(moveOyLeft) + 100));
d3.select("#POG-GRP-002 svg g").attr('transform', 'translate(' + (margin.left + +"50") + ',' + margin.top + ')');
}
// ve hanrei
if (getGuidedisplayFlag == 1) {
let keys = legend.selectAll('.key')
.data(itemLengend)
.enter()
.append('g')
.attr('class', 'key')
.style('display', 'flex')
.style('align-items', 'center')
.style('margin-right', '20px');
keys.append('rect')
.attr('class', 'symbol')
.attr('id', 'POG-LBL-003-001')
.style('height', '20px')
.style('width', '20px')
.style('margin', '5px 5px')
.style('background-color', element["color"]);
keys.append('text')
.attr('class', 'name')
.attr('id', 'POG-LBL-003-002')
.text(function(d) { return d });
keys.exit().remove();
}
});
var color = d3.scaleOrdinal()
.domain(dataLegend)
.range(getDisplaycolors);
var bar = svg.append('g')
.attr('class', 'group-bar')
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('class', 'bar')
.attr('transform', function(d) {
if (d.time != undefined) {
return 'translate(' + x(d.time) + ',0)';
} else if (d.area != undefined) {
return 'translate(' + x(d.area) + ',0)';
} else if (d.factory != undefined) {
return 'translate(' + x(d.factory) + ',0)';
} else if (d.machine != undefined) {
return 'translate(' + x(d.machine) + ',0)';
}
});
// バーチャート.
bar.selectAll("rect")
.data(function(d) {
return dataLegend.map(function(key) {
var a = { key: key, value: d[key] };
//console.log(a);
return a;
});
})
.enter()
.append('rect')
.attr('class', 'sales')
.attr('fill', function(d) { return color(d.key); })
.attr('x', function(d) {
return x1(d.key);
})
.attr('y', function(d) {
return yindex(d.value);
})
.attr('height', function(d) {
//console.log((d[item]));
return height - yindex(d.value) - margin.bottom;
})
.attr('width', x1.bandwidth());
// vẽ đường line cho biểu đồ
//lọc lấy lấy max min split
const uniquesRight = [...new Set(
arrayRight.map(x => JSON.stringify((({ max, min, split }) => ({ max, min, split }))(x))))
].map(JSON.parse);
var y2;
var yAxis2
if (uniquesRight.length == 1) {
var maxOne = parseFloat(uniquesRight[0].max);
var minOne = parseFloat(uniquesRight[0].min);
var splitOne = parseFloat(uniquesRight[0].split);
var tickOne = [];
for (var i = minOne; i <= maxOne; i += splitOne) {
tickOne.push(i);
}
d3.max(tickOne) == maxOne ? tickOne.push() : tickOne.push(maxOne);
y2 = d3.scaleLinear().nice()
.domain([minOne, maxOne])
.range([height - margin.bottom, 0]);
yAxis2 = d3.axisRight(y2).tickValues(tickOne);
svg.append('g')
.attr('id', 'POG-GRP-002-004')
.attr('transform', 'translate(' + Math.ceil(width + moveOfRight) + ',0)')
.attr('class', 'y2-axis'.concat('-0'))
.attr('stroke', "#FFFF")
.call(yAxis2)
.selectAll('.tick').attr('stroke', "#FFFF");
}
//var arrItem = [];
//var reveredArr = arrItem.reverse();
var itemLengend2 = [];
arrayRight.forEach((element, index) => {
var legendUser = element["legend"];
itemLengend2.push(legendUser);
if (uniquesRight.length > 1) {
var maxOy = parseFloat(element["max"]);
var minOy = parseFloat(element["min"]);
var splitOy = parseFloat(element["split"]);
var tickCount = [];
for (var i = minOy; i <= maxOy; i += splitOy) {
tickCount.push(i);
}
d3.max(tickCount) == maxOy ? tickCount.push() : tickCount.push(maxOy);
y2 = d3.scaleLinear().nice()
.domain([element["min"], element["max"]])
.range([height - margin.bottom, 0]);
yAxis2 = d3.axisRight(y2).tickValues(tickCount);
svg.append('g')
.attr('id', 'POG-GRP-002-004')
.attr('transform', 'translate(' + Math.ceil(width + moveOfRight) + ',0)')
.attr('class', 'y2-axis'.concat('-' + index))
.style('stroke', element["color"])
.call(yAxis2);
moveOfRight += 55;
}
//bắt đầu vẽ biểu đồ line ở đây
var linePlaceHolder = svg.append('g').attr("class", "line-percent");
var percentLine = d3.line()
.x(function(d) {
if (d.time != undefined) {
return x(d.time);
} else if (d.area != undefined) {
return x(d.area);
} else if (d.factory != undefined) {
return x(d.factory);
} else if (d.machine != undefined) {
return x(d.machine);
}
})
//.x(function(d){return x(d.time)})
.y(function(d) {
//console.log(d);
return y2(d[legendUser]);
});
linePlaceHolder.append("path")
.datum(data)
.attr('fill', 'none')
.classed('line', true)
.attr('stroke-width', '3px')
.attr('stroke', element["color"])
.attr("d", percentLine);
// ve hanrei cho line
if (getGuidedisplayFlag == 1) {
let keysLegend = legend.selectAll('.key-strain')
.data(itemLengend2)
.enter().append('g')
.attr('class', 'key-strain')
.style('display', 'flex')
.style('align-items', 'center')
.style('margin-right', '20px');
keysLegend.append('line')
.attr('class', 'symbol')
.attr('id', 'POG-LBL-003-001')
.style('height', '5px')
.style('width', '30px')
.style('margin', '5px 5px')
.style('background-color', element["color"]);
keysLegend.append('text')
.attr('class', 'name')
.attr('id', 'POG-LBL-003-002')
.text(function(d) { return d });
keysLegend.exit().remove();
}
});
// 横線を描画する
d3.select('y2-axis-0').selectAll('g').filter(function(d) { return d; })
.append('line')
.attr('x2', -width)
.attr('x1', 0)
.attr('stroke', '#777')
.attr('stroke-dasharray', 4)
.attr('opacity', 0.5)
//Select Date button
var form = d3.select("[id='" + panelUniqueId + "']")
.select('[class="main-image"]')
.append('div')
.attr('class', 'datePick')
.style('width', '100%')
.style('height', '20px')
.style('background-color', '#262626')
.append("form")
.style("float", "left")
.style("position", "absolute")
.style("bottom", "-1rem")
// 前日ボタン
form.append("button")
.style("background-color", "#262626")
.style("width", "20px")
.style("height", "20px")
.attr("id", "POG-TXT-006")
.attr("type", "button")
.attr("onclick", "POGpreviousButton(event,\'" + panelUniqueId + "\')")
.append("i")
.attr("class", "fas fa-caret-left")
.style("font-size", "20px")
.style("color", "white")
// 対象日 日付ボックス
form.append("input")
.attr("type", "text")
.attr("id", "POG-TXT-005")
.attr("autocomplete", "off")
.attr("onSelect", "hasdataPickerValue(event,\'" + panelUniqueId + "\')")
.style("width", "140px")
.style("height", "20px")
.style("padding-top", "6px")
.style("background-color", "#262626")
.style("color", "white")
.style("border-style", "solid")
.style("border-width", "1px")
// 本日ボタン
form.append("input")
.attr("id", "POG-TXT-007")
.attr("type", "button")
.attr("value", " ")
.attr("onclick", "POGnowFunction(event,\'" + panelUniqueId + "\')")
.style('height', '20px')
.style('width', '20px')
.style("border-radius", "50%")
.style("background-color", "white")
// 翌日ボタン
form.append("button")
.style("background-color", "#262626")
.style('height', '20px')
.style('width', '20px')
.attr("id", "POG-TXT-008")
.attr("type", "button")
.attr("onclick", "POGnextButton(event,\'" + panelUniqueId + "\')")
.append("i")
.attr("class", "fas fa-caret-right")
.style("font-size", "20px")
.style("color", "white")
$('#POG-TXT-005').val(formatDatePCG(date))
$('#POG-TXT-005').datepicker(
{
dateFormat: "yy/mm/dd",
onSelect: function(dateText) {
date = new Date(dateText)
reGrapDraw(panelUniqueId, formatDatePCG(date))
}
});
}
//call api if click button
function POGpreviousButton(e, panelUniqueId) {
e.preventDefault();
date.setDate(date.getDate() - 1);
$('#POG-TXT-005').val(formatDatePCG(date))
reGrapDraw(panelUniqueId, formatDatePCG(date))
}
function POGnextButton(e, panelUniqueId) {
e.preventDefault();
date.setDate(date.getDate() + 1);
$('#POG-TXT-005').val(formatDatePCG(date))
reGrapDraw(panelUniqueId, formatDatePCG(date))
}
function POGnowFunction(e, panelUniqueId) {
e.preventDefault();
date = new Date()
$('#POG-TXT-005').val(formatDatePOG(date))
reGrapDraw(panelUniqueId, formatDatePCG(date))
}
function formatDatePOG(d) {
var month = '' + (d.getMonth() + 1);
var day = '' + d.getDate();
var year = d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return [year, month, day].join('/');
}
function reGrapDraw(panelUniqueId, dateSelected) {
console.log("getAPI")
$.ajax({
url: '/api/panel/POG',
type: 'GET',
data: { 'panelUniqueId': panelUniqueId, 'date': dateSelected },
success: function(response) {
genPanelPOG(panelUniqueId, response);
}
});
}```发布于 2021-02-27 10:23:32
我解决了我的问题
在var x = d3.scaleBand() .domain(dataOx) .rangeRound([0, width]) .padding(1);中必须改变填充(0.05),使其与x1的填充相同。
https://stackoverflow.com/questions/66394896
复制相似问题