进度圈更新百分比
Updating percentage in progress circle
我正在使用此处给出的备选方案之一 (CSS Progress Circle) 构建一个带有进度圈的待办事项列表。在我的 script.js 中,我定义了函数 drawRingProgress()
,当我在脚本末尾执行它时,它会呈现 canvas。
当我的脚本的其他功能被执行以添加任务、编辑、删除或将它们标记为完成时,参数 pendingTasks
和 completedTasks
得到更新。但是,如果我在其他提到的函数中调用函数 drawRingProgress()
,为了更新进度,canvas 会在其他地方多次错误绘制(取决于这些函数的 HTML 元素作用于)。呈现更新进度百分比的正确方法是什么?
Link 到工作示例:https://jsfiddle.net/tailslider13/f4qtmhzj/7/
let pendingTasks = 31;
let completedTasks = 69;
function drawRingProgress(pendingTasks, completedTasks) {
var el = document.getElementById('graph'); // get canvas
let progress_percentage = Math.floor((completedTasks / (completedTasks + pendingTasks)) * 100) || 0;
var options = {
// percent: el.getAttribute('data-percent') || 25,
percent: progress_percentage,
// size: 110,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof (G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 3.2;
var drawCircle = function (color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#046582', options.lineWidth, options.percent / 100)
}
drawRingProgress(pendingTasks, completedTasks);
下面是我绘制图表的方式。我已经从中删除了所有其他函数,因此它仅根据您设置的变量显示图形进度。弄清楚其他功能后,您可以通过该方法更新它们。
首先我会在脚本的开头获取 canvas 并将变量指定为全局变量。
其次,我会把白色甜甜圈画平。除非您打算以某种方式更改它,否则函数 drawGraph()
将被调用一次,仅此而已。
第三个函数 drawRingProgress()
会在您添加、删除或完成任务时从其他函数调用。确保这些函数在调用 drawRingProgress()
.
之前也会更新 pendingTasks
和 completedTasks
在 drawRingProgress()
中,我添加了文本,因为 canvas 具有内置方法,因此您不需要使用 <span>
。至于你所有的选项,我为此删除了它们,但你可以将它们添加回你认为合适的地方。
const inputField = document.getElementById("addTask");
const taskList = document.getElementById("taskList");
var canvas = document.getElementById('graph');
var ctx = canvas.getContext('2d');
canvas.width = 200;
canvas.height = 200;
let pendingTasks = 20;
let completedTasks = 5;
//Progress ring
function drawGraph() {
ctx.beginPath();
ctx.strokeStyle = "white";
ctx.arc(canvas.width/2, canvas.height/2, 50, 0, Math.PI*2, false);
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = 15;
ctx.stroke();
ctx.closePath();
}
drawGraph();
function drawRingProgress(pendingTasks, completedTasks) {
let progress_percentage = (completedTasks / pendingTasks) * 100;
ctx.font = "30px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "#046582";
ctx.fillText(progress_percentage+'%', canvas.width/2,canvas.height/2);
percent = Math.min(Math.max(0, (progress_percentage/100) || 1), 1);
ctx.beginPath();
ctx.save();
ctx.translate(0, canvas.height); // change center
ctx.rotate((-1 / 2 + 0 / 180) * Math.PI); // rotate -90 deg
ctx.arc(canvas.width/2, canvas.height/2, 50, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = "#046582";
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = 15;
ctx.stroke();
ctx.restore();
ctx.closePath();
}
drawRingProgress(pendingTasks, completedTasks);
#body {
background-color: #046582;
}
header {
background-color: #f39189;
padding: 50px;
margin: 50px;
position: sticky;
top: 0px;
}
h1 {
text-align: center;
}
.listItem {
margin: 20px 0px;
background-color: white;
}
.container {
background-color: #c4c4c4;
}
.taskList {
list-style-type: none;
background-color: transparent;
overflow: hidden;
margin-top: 150px;
}
.inputContainer {
margin: 50px;
padding: 20px;
max-width: 50%;
width: 100%;
background-color: #f39189;
}
#footer {
text-align: center;
position: sticky;
bottom: 0px;
background-color: #f39189;
padding: 20px;
}
.deleteButton {
background-image: url("/content/delete.png");
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
width: 30px;
height: 30px;
margin: 15px;
}
#addTask {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 1.3rem;
}
.taskName {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 1.2rem;
}
.listContainer {
height: 1080px;
}
.inputContainer {
position: fixed;
}
.checkedbox {
text-decoration: line-through;
color: #f39189;
}
/* START Styling Progress ring */
.chart {
position: relative;
/* margin:0px; */
width: 220px;
height: 220px;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
span {
color: #046582;
display: block;
line-height: 220px;
text-align: center;
width: 220px;
font-family: sans-serif;
font-size: 30px;
font-weight: 100;
margin-left: 5px;
}
/* Links progress ring */
/*
http://jsfiddle.net/Aapn8/3410/ */
/* END Styling Progress ring */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
</head>
<div class="container">
<body id="body">
<header class="row justify-content-end">
<h1 class="col-4">Take note</h1>
<!-- Progress ring -->
<div class="col-4">
<canvas class="chart" id="graph"></canvas>
</div>
</header>
<!-- Input field and button -->
<div class="row inputContainer rounded">
<input class="col-auto" type="newTask" placeholder="Enter new Task" id="addTask" />
<button class="col-auto" id="btnAdd">Add</button>
</div>
<!-- List of tasks created -->
<div class="listContainer">
<ul class="taskList rounded" id="taskList"></ul>
</div>
<footer class="row" id="footer">
<h6 class="col w-100">2021</h6>
</footer>
<!-- BOOTSTRAP -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.min.js" integrity="sha384-lpyLfhYuitXl2zRZ5Bn2fqnhNAKOAaM/0Kr9laMspuaMiZfGmfwRNFh8HlMy49eQ" crossorigin="anonymous">
</script>
</body>
</div>
</html>
我也不确定您使用 bootstraps 图表的目的是什么。我以前没有使用过它,但是从检查文档来看,您似乎并没有真正为它进行适当的编码。另外你有一个 <div>
和 class 的图表而不是 <canvas>
这对我来说似乎是错误的(但就像我说的我以前没有使用过它)。在此处的示例中,我将其更改为 <canvas>
并且还删除了您与跨度一起创建的 canvas。
希望这就是您想要的,如果不是,也许您仍然可以将我这里的内容与您真正想要的拼凑起来。
嘿 Carlos 和所有对解决方案感兴趣的人。
在研究代码后,我注意到问题在于每次调用函数但从未删除时创建元素 span
和 canvas
。
解决方案是让这些元素开始,即在 html 代码中 ||或者在调用函数之前创建一次。
至于变量pendingTasks
和completedTasks
,我建议将它们更改为pendingTasks
和totalAmountOfTasks
。 (除非他们可以处于第三种状态。)
那么你要喂入圆圈的比例是pendingTasks/totalAmountOfTasks
.
记得在没有任务时检查是否被零除!
干杯,
托马斯
我正在使用此处给出的备选方案之一 (CSS Progress Circle) 构建一个带有进度圈的待办事项列表。在我的 script.js 中,我定义了函数 drawRingProgress()
,当我在脚本末尾执行它时,它会呈现 canvas。
当我的脚本的其他功能被执行以添加任务、编辑、删除或将它们标记为完成时,参数 pendingTasks
和 completedTasks
得到更新。但是,如果我在其他提到的函数中调用函数 drawRingProgress()
,为了更新进度,canvas 会在其他地方多次错误绘制(取决于这些函数的 HTML 元素作用于)。呈现更新进度百分比的正确方法是什么?
Link 到工作示例:https://jsfiddle.net/tailslider13/f4qtmhzj/7/
let pendingTasks = 31;
let completedTasks = 69;
function drawRingProgress(pendingTasks, completedTasks) {
var el = document.getElementById('graph'); // get canvas
let progress_percentage = Math.floor((completedTasks / (completedTasks + pendingTasks)) * 100) || 0;
var options = {
// percent: el.getAttribute('data-percent') || 25,
percent: progress_percentage,
// size: 110,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof (G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 3.2;
var drawCircle = function (color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#046582', options.lineWidth, options.percent / 100)
}
drawRingProgress(pendingTasks, completedTasks);
下面是我绘制图表的方式。我已经从中删除了所有其他函数,因此它仅根据您设置的变量显示图形进度。弄清楚其他功能后,您可以通过该方法更新它们。
首先我会在脚本的开头获取 canvas 并将变量指定为全局变量。
其次,我会把白色甜甜圈画平。除非您打算以某种方式更改它,否则函数 drawGraph()
将被调用一次,仅此而已。
第三个函数 drawRingProgress()
会在您添加、删除或完成任务时从其他函数调用。确保这些函数在调用 drawRingProgress()
.
pendingTasks
和 completedTasks
在 drawRingProgress()
中,我添加了文本,因为 canvas 具有内置方法,因此您不需要使用 <span>
。至于你所有的选项,我为此删除了它们,但你可以将它们添加回你认为合适的地方。
const inputField = document.getElementById("addTask");
const taskList = document.getElementById("taskList");
var canvas = document.getElementById('graph');
var ctx = canvas.getContext('2d');
canvas.width = 200;
canvas.height = 200;
let pendingTasks = 20;
let completedTasks = 5;
//Progress ring
function drawGraph() {
ctx.beginPath();
ctx.strokeStyle = "white";
ctx.arc(canvas.width/2, canvas.height/2, 50, 0, Math.PI*2, false);
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = 15;
ctx.stroke();
ctx.closePath();
}
drawGraph();
function drawRingProgress(pendingTasks, completedTasks) {
let progress_percentage = (completedTasks / pendingTasks) * 100;
ctx.font = "30px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "#046582";
ctx.fillText(progress_percentage+'%', canvas.width/2,canvas.height/2);
percent = Math.min(Math.max(0, (progress_percentage/100) || 1), 1);
ctx.beginPath();
ctx.save();
ctx.translate(0, canvas.height); // change center
ctx.rotate((-1 / 2 + 0 / 180) * Math.PI); // rotate -90 deg
ctx.arc(canvas.width/2, canvas.height/2, 50, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = "#046582";
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = 15;
ctx.stroke();
ctx.restore();
ctx.closePath();
}
drawRingProgress(pendingTasks, completedTasks);
#body {
background-color: #046582;
}
header {
background-color: #f39189;
padding: 50px;
margin: 50px;
position: sticky;
top: 0px;
}
h1 {
text-align: center;
}
.listItem {
margin: 20px 0px;
background-color: white;
}
.container {
background-color: #c4c4c4;
}
.taskList {
list-style-type: none;
background-color: transparent;
overflow: hidden;
margin-top: 150px;
}
.inputContainer {
margin: 50px;
padding: 20px;
max-width: 50%;
width: 100%;
background-color: #f39189;
}
#footer {
text-align: center;
position: sticky;
bottom: 0px;
background-color: #f39189;
padding: 20px;
}
.deleteButton {
background-image: url("/content/delete.png");
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
width: 30px;
height: 30px;
margin: 15px;
}
#addTask {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 1.3rem;
}
.taskName {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 1.2rem;
}
.listContainer {
height: 1080px;
}
.inputContainer {
position: fixed;
}
.checkedbox {
text-decoration: line-through;
color: #f39189;
}
/* START Styling Progress ring */
.chart {
position: relative;
/* margin:0px; */
width: 220px;
height: 220px;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
span {
color: #046582;
display: block;
line-height: 220px;
text-align: center;
width: 220px;
font-family: sans-serif;
font-size: 30px;
font-weight: 100;
margin-left: 5px;
}
/* Links progress ring */
/*
http://jsfiddle.net/Aapn8/3410/ */
/* END Styling Progress ring */
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
</head>
<div class="container">
<body id="body">
<header class="row justify-content-end">
<h1 class="col-4">Take note</h1>
<!-- Progress ring -->
<div class="col-4">
<canvas class="chart" id="graph"></canvas>
</div>
</header>
<!-- Input field and button -->
<div class="row inputContainer rounded">
<input class="col-auto" type="newTask" placeholder="Enter new Task" id="addTask" />
<button class="col-auto" id="btnAdd">Add</button>
</div>
<!-- List of tasks created -->
<div class="listContainer">
<ul class="taskList rounded" id="taskList"></ul>
</div>
<footer class="row" id="footer">
<h6 class="col w-100">2021</h6>
</footer>
<!-- BOOTSTRAP -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.min.js" integrity="sha384-lpyLfhYuitXl2zRZ5Bn2fqnhNAKOAaM/0Kr9laMspuaMiZfGmfwRNFh8HlMy49eQ" crossorigin="anonymous">
</script>
</body>
</div>
</html>
我也不确定您使用 bootstraps 图表的目的是什么。我以前没有使用过它,但是从检查文档来看,您似乎并没有真正为它进行适当的编码。另外你有一个 <div>
和 class 的图表而不是 <canvas>
这对我来说似乎是错误的(但就像我说的我以前没有使用过它)。在此处的示例中,我将其更改为 <canvas>
并且还删除了您与跨度一起创建的 canvas。
希望这就是您想要的,如果不是,也许您仍然可以将我这里的内容与您真正想要的拼凑起来。
嘿 Carlos 和所有对解决方案感兴趣的人。
在研究代码后,我注意到问题在于每次调用函数但从未删除时创建元素 span
和 canvas
。
解决方案是让这些元素开始,即在 html 代码中 ||或者在调用函数之前创建一次。
至于变量pendingTasks
和completedTasks
,我建议将它们更改为pendingTasks
和totalAmountOfTasks
。 (除非他们可以处于第三种状态。)
那么你要喂入圆圈的比例是pendingTasks/totalAmountOfTasks
.
记得在没有任务时检查是否被零除!
干杯,
托马斯