我正试图为我的学校项目制作一个成本图表,衡量项目的计划和实际成本。我得到了本地存储工作在一个正常的条形图感谢另一篇文章在这里,但不能让它工作在这个图表,因为它需要两个数据集。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>LS&INPUTS - Colum</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="card">
<p class="chart-heading">Job progress</p>
<div class="container">
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>
<div class="inputs-container">
<div class="input-title">
<p>Job</p>
<p>Job progress(%)</p>
</div>
<!-- Input 1 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input1text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput1" onchange ="updatePC()">
<input class="actualcost" type="number" id="actualinput1" onchange ="updateAC()">
</div>
<!-- Input 2 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input2text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput2" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput2" onchange ="updateAC()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input3text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput3" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput3" onchange ="updateAC()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input4text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput4" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput4" onchange ="updateAC()">
</div>
<!-- Input 5 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input5text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput5" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput5" onchange ="updateAC()">
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="script.js"></script>
</body>
</html>
let labelData = loadLabelFromLocalStorage();
let plannedCostData = loadPCFromLocalStorage();
let actualCostData = loadACFromLocalStorage();
setUILabel(labelData);
setUIPCData(plannedCostData);
setUIACData(actualCostData);
const ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labelData,
datasets: [{
data: actualCostData,
backgroundColor: "#2E9CCA",
},{
data: plannedCostData,
backgroundColor: "#AAABB8",
}]
},
options: {
plugins: {
legend: {
display: false,
}
},
scales: {
y: {
beginAtZero: true,
min: 0,
}
}
}
});
// add label
function addLabel(chart, data) {
chart.data.labels.forEach((dataset) => {
dataset.data = [...data]
});
chart.update();
}
function updateLabel(event) {
if (event) event.preventDefault();
labelData = getUILabel();
saveLabelToLocalStorage(labelData);
addLabel(myChart, labelData);
}
//Updating chart with values
function setUILabel(data) {
document.querySelectorAll('.labelinput').forEach((el, i) => el.value = data[i] || '');
}
function getUILabel() {
return Array.from(document.querySelectorAll('.labelinput'))
.map(el => String(el.value));
}
function saveLabelToLocalStorage(labelData) {
localStorage.setItem('Label', JSON.stringify(labelData));
}
function loadLabelFromLocalStorage() {
return JSON.parse(localStorage.getItem('Label') || '[]');
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//add "planned cost" data
function addPC(chart, data) {
chart.data.datasets.forEach((dataset) => {
dataset.data = [...data]
});
chart.update();
}
//Calling input values to update chart
function updatePC(event) {
if (event) event.preventDefault();
plannedCostData = getUIPCData();
savePCToLocalStorage(plannedCostData);
addPC(myChart, plannedCostData);
}
//Updating chart with values
function setUIPCData(data) {
document.querySelectorAll('.plannedcost').forEach((el, i) => el.value = data[i] || '');
}
function getUIPCData() {
return Array.from(document.querySelectorAll('.plannedcost'))
.map(el => Number(el.value));
}
function savePCToLocalStorage(plannedCostData) {
localStorage.setItem('number2', JSON.stringify(plannedCostData));
}
function loadPCFromLocalStorage() {
return JSON.parse(localStorage.getItem('number2') || '[]');
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//add actual cost
function addAC(chart, data) {
chart.data.datasets.forEach((dataset) => {
dataset.data = [...data]
});
chart.update();
}
//Calling input values to update chart
function updateAC(event) {
if (event) event.preventDefault();
actualCostData = getUIACData();
saveACToLocalStorage(actualCostData);
addAC(myChart, actualCostData);
}
//Updating chart with values
function setUIACData(data) {
document.querySelectorAll('.actualcost').forEach((el, i) => el.value = data[i] || '');
}
function getUIACData() {
return Array.from(document.querySelectorAll('.actualcost'))
.map(el => Number(el.value));
}
function saveACToLocalStorage(actualCostData) {
localStorage.setItem('number3', JSON.stringify(actualCostData));
}
function loadACFromLocalStorage() {
return JSON.parse(localStorage.getItem('number3') || '[]');
}
body {
background-color:#25274D;
}
.container {
flex: 0 0 auto;
width: 100%;
box-sizing: border-box;
display: block;
max-width: 100%;
}
.card {
width: 57.5rem;
height: 18rem;
background-color: white;
border-radius: 4px;
}
.container {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.inputfield {
display: flex;
grid-template-columns: 1fr 1fr;
gap: 0.65rem;
border-radius: 4px;
width: 0.5rem;
}
.inputs-container {
display: grid;
gap: 0.65rem;
}
.chart-heading {
text-align: left;
padding: 1.2rem 0 1.2rem 1rem;
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
width: 100%;
}
.input-title {
display: flex;
gap: 8rem;
}
.plannedcost {
width: 3.5rem;
}
.actualcost {
width: 3.5rem;
}
我尝试了上面的代码,但是当增加计划成本条的值时,相邻的实际成本条的值也会增加。
更改标签可以很好地工作,但是当增加值时,它就不能按预期工作了。我假设这是因为下面的代码用于计划和实际成本,但我不确定如何选择哪个数据集用于每个酒吧。
function addBarData(chart, data) {
chart.data.datasets.forEach((dataset) => {
dataset.data = [...data]
});
chart.update();
}
更新
现在所有的图表都是单独工作的,但当它们在同一页面上时,它们开始出现故障并共享数据。
let stackedLabelData = loadLabelFromLocalStorage();
let plannedData = loadPlanedFromLocalStorage();
let startedData = loadStartedFromLocalStorage();
let completedData = loadCompletedFromLocalStorage();
setUILabel(stackedLabelData);
setPlannedUIData(plannedData);
setStartedUIData(startedData);
setCompletedUIData(completedData);
let ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: stackedLabelData,
datasets: [{
data: plannedData,
backgroundColor: "#AAABB8",
},{
data: startedData,
backgroundColor: "#2E9CCA",
},{
data: completedData,
backgroundColor: "#296484",
}]
},
options: {
indexAxis: 'y',
plugins: {
legend: {
display: false,
}
},
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
},
}
});
////////////////////////////////////// update labels ///////////////////////////////////
function addBarLabel(chart, data) {
chart.data.labels = data;
chart.update();
}
//Calling input values to update chart
function updateLabel(event) {
if (event) event.preventDefault();
stackedLabelData = getUILabel();
saveLabelToLocalStorage(stackedLabelData);
addBarLabel(myChart, stackedLabelData);
}
//Updating chart with values
function setUILabel(data) {
document.querySelectorAll('.Labelinput').forEach((el, i) => el.value = data[i] || '');
}
function getUILabel() {
return Array.from(document.querySelectorAll('.Labelinput'))
.map(el => String(el.value));
}
function saveLabelToLocalStorage(stackedLabelData) {
localStorage.setItem('Label', JSON.stringify(stackedLabelData));
}
function loadLabelFromLocalStorage() {
return JSON.parse(localStorage.getItem('Label') || '[]');
}
////////////////////////////////////// update planned ///////////////////////////////////
function addBarData(chart, data, whichData) {
const idx = {"planned":0,"started":1, "completed":2 }[whichData]
chart.data.datasets[idx].data = data;
chart.update();
}
//Calling input values to update chart
function updatePlanned(event) {
if (event) event.preventDefault();
plannedData = getPlannedUIData();
savePlannedToLocalStorage(plannedData);
addBarData(myChart, plannedData, "planned");
}
//Updating chart with values
function setPlannedUIData(data) {
document.querySelectorAll('.planned').forEach((el, i) => el.value = data[i] || '');
}
function getPlannedUIData() {
return Array.from(document.querySelectorAll('.planned'))
.map(el => Number(el.value));
}
function savePlannedToLocalStorage(plannedData) {
localStorage.setItem('plannedjobs', JSON.stringify(plannedData));
}
function loadPlanedFromLocalStorage() {
return JSON.parse(localStorage.getItem('plannedjobs') || '[]');
}
////////////////////////////////////// update started ///////////////////////////////////
//Calling input values to update chart
function updateStarted(event) {
if (event) event.preventDefault();
startedData = getStartedUIData();
saveStartedToLocalStorage(startedData);
addBarData(myChart, startedData, "started");
}
//Updating chart with values
function setStartedUIData(data) {
document.querySelectorAll('.started').forEach((el, i) => el.value = data[i] || '');
}
function getStartedUIData() {
return Array.from(document.querySelectorAll('.started'))
.map(el => Number(el.value));
}
function saveStartedToLocalStorage(startedData) {
localStorage.setItem('startedjobs', JSON.stringify(startedData));
}
function loadStartedFromLocalStorage() {
return JSON.parse(localStorage.getItem('startedjobs') || '[]');
}
////////////////////////////////////// update completed //////////////////////////////////
//Calling input values to update chart
function updateCompleted(event) {
if (event) event.preventDefault();
completedData = getCompletedUIData();
saveCompletedFromLocalStorage(completedData);
addBarData(myChart, completedData, "completed");
}
//Updating chart with values
function setCompletedUIData(data) {
document.querySelectorAll('.completed').forEach((el, i) => el.value = data[i] || '');
}
function getCompletedUIData() {
return Array.from(document.querySelectorAll('.completed'))
.map(el => Number(el.value));
}
function saveCompletedFromLocalStorage(completedData) {
localStorage.setItem('completedjobs', JSON.stringify(completedData));
}
function loadCompletedFromLocalStorage() {
return JSON.parse(localStorage.getItem('completedjobs') || '[]');
}
///////////////////////////////////Second file////////////////////////////////////////
let labelData = loadLabelFromLocalStorage();
let plannedCostData = loadPCFromLocalStorage();
let actualCostData = loadACFromLocalStorage();
setUILabel(labelData);
setUIPCData(plannedCostData);
setUIACData(actualCostData);
ctx = document.getElementById('column');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labelData,
datasets: [{
data: actualCostData,
backgroundColor: "#2E9CCA",
},{
data: plannedCostData,
backgroundColor: "#AAABB8",
}]
},
options: {
plugins: {
legend: {
display: false,
}
},
scales: {
y: {
beginAtZero: true,
min: 0,
}
}
}
});
function addBarLabel(chart, data) {
chart.data.labels = data;
chart.update();
}
function updateLabel(event) {
if (event) event.preventDefault();
labelData = getUILabel();
saveLabelToLocalStorage(labelData);
addBarLabel(myChart, labelData);
}
//Updating chart with values
function setUILabel(data) {
document.querySelectorAll('.labelinput').forEach((el, i) => el.value = data[i] || '');
}
function getUILabel() {
return Array.from(document.querySelectorAll('.labelinput'))
.map(el => String(el.value));
}
function saveLabelToLocalStorage(labelData) {
localStorage.setItem('Label', JSON.stringify(labelData));
}
function loadLabelFromLocalStorage() {
return JSON.parse(localStorage.getItem('Label') || '[]');
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function addBarData(chart, data, whichData) {
const idx = whichData === "actual" ? 0:1;
chart.data.datasets[idx].data = data;
chart.update();
}
//Calling input values to update chart
function updatePC(event) {
if (event) event.preventDefault();
plannedCostData = getUIPCData();
savePCToLocalStorage(plannedCostData);
addBarData(myChart, plannedCostData, "planned");
}
//Updating chart with values
function setUIPCData(data) {
document.querySelectorAll('.plannedcost').forEach((el, i) => el.value = data[i] || '');
}
function getUIPCData() {
return Array.from(document.querySelectorAll('.plannedcost'))
.map(el => Number(el.value));
}
function savePCToLocalStorage(plannedCostData) {
localStorage.setItem('number2', JSON.stringify(plannedCostData));
}
function loadPCFromLocalStorage() {
return JSON.parse(localStorage.getItem('number2') || '[]');
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Calling input values to update chart
function updateAC(event) {
if (event) event.preventDefault();
actualCostData = getUIACData();
saveACToLocalStorage(actualCostData);
addBarData(myChart, actualCostData, "actual");
}
//Updating chart with values
function setUIACData(data) {
document.querySelectorAll('.actualcost').forEach((el, i) => el.value = data[i] || '');
}
function getUIACData() {
return Array.from(document.querySelectorAll('.actualcost'))
.map(el => Number(el.value));
}
function saveACToLocalStorage(actualCostData) {
localStorage.setItem('number3', JSON.stringify(actualCostData));
}
function loadACFromLocalStorage() {
return JSON.parse(localStorage.getItem('number3') || '[]');
}
body {
background-color:#25274D;
}
.container {
flex: 0 0 auto;
width: 100%;
box-sizing: border-box;
display: block;
max-width: 100%;
}
.card {
width: 57.5rem;
height: 18rem;
background-color: white;
border-radius: 4px;
}
.container {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.inputfield {
display: flex;
grid-template-columns: 1fr 1fr;
gap: 0.65rem;
border-radius: 4px;
width: 0.5rem;
}
.inputs-container {
display: grid;
gap: 0.65rem;
}
.chart-heading {
text-align: left;
padding: 1.2rem 0 1.2rem 1rem;
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
width: 100%;
}
.input-title {
display: flex;
gap: 8rem;
}
.planned {
width: 3.5rem;
}
.started {
width: 3.5rem;
}
.completed {
width: 3.5rem;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WORKING INPUTS - Stacked bar</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="card">
<p class="chart-heading">Job progress</p>
<div class="container">
<div class="chart-container">
<canvas id="myChart"></canvas>
</div>
<div class="inputs-container">
<div class="input-title">
<p>Job</p>
<p>Job progress(%)</p>
</div>
<!-- Input 1 -->
<div class="inputfield">
<input class="Labelinput" type="text" onkeyup="updateLabel()" value="Client 1" maxlength="10">
<input class="planned" type="number" onchange ="updatePlanned()">
<input class="started" type="number" onchange ="updateStarted()">
<input class="completed" type="number" onchange ="updateCompleted()">
</div>
<!-- Input 2 -->
<div class="inputfield">
<input class="Labelinput" type="text" id="input2text" onkeyup="updateLabel()" value="Client 2" maxlength="10">
<input class="planned" type="number" id="plannedinput2" onchange ="updatePlanned()">
<input class="started" type="number" id="startedinput2" onchange ="updateStarted()">
<input class="completed" type="number" id="completedinput2" onchange ="updateCompleted()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="Labelinput" type="text" id="input3text" onkeyup="updateLabel()" value="Client 3" maxlength="10">
<input class="planned" type="number" id="plannedinput3" onchange ="updatePlanned()">
<input class="started" type="number" id="startedinput3" onchange ="updateStarted()">
<input class="completed" type="number" id="completedinput3" onchange ="updateCompleted()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="Labelinput" type="text" id="input4text" onkeyup="updateLabel()" value="Client 4" maxlength="10">
<input class="planned" type="number" id="plannedinput4" onchange ="updatePlanned()">
<input class="started" type="number" id="startedinput4" onchange ="updateStarted()">
<input class="completed" type="number" id="completedinput4" onchange ="updateCompleted()">
</div>
<!-- Input 5 -->
<div class="inputfield">
<input class="Labelinput" type="text" id="input5text" onkeyup="updateLabel()" value="Client 5" maxlength="10">
<input class="planned" type="number" id="plannedinput5" onchange ="updatePlanned()">
<input class="started" type="number" id="startedinput5" onchange ="updateStarted()">
<input class="completed" type="number" id="completedinput5" onchange ="updateCompleted()">
</div>
</div>
</div>
</div>
<div class="card">
<p class="chart-heading">Job progress</p>
<div class="container">
<div class="chart-container">
<canvas id="column"></canvas>
</div>
<div class="inputs-container">
<div class="input-title">
<p>Job</p>
<p>Job progress(%)</p>
</div>
<!-- Input 1 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input1text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput1" oninput ="updatePC()">
<input class="actualcost" type="number" id="actualinput1" oninput ="updateAC()">
</div>
<!-- Input 2 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input2text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput2" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput2" onchange ="updateAC()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input3text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput3" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput3" onchange ="updateAC()">
</div>
<!-- Input 3 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input4text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput4" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput4" onchange ="updateAC()">
</div>
<!-- Input 5 -->
<div class="inputfield">
<input class="labelinput" type="text" id="input5text" onkeyup="updateLabel()" maxlength="10">
<input class="plannedcost" type="number" id="plannedinput5" onchange="updatePC()">
<input class="actualcost" type="number" id="actualinput5" onchange ="updateAC()">
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="stackedbar.js"></script>
<script src="column.js"></script>
</body>
</html>
2条答案
按热度按时间kxe2p93d1#
更新
请考虑更DRY(不要重复自己),例如像这个(不完整)的例子
rn0zuynd2#
我预计
更好地工作
如果你一定要试试这个