根据百度中的各位大佬的总结作出下方图,做个记录:
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas">您的浏览器不支持Canvas标签,请升级或更换浏览器</canvas>
</body>
</html>
<!-- <script src="canvas.js"></script> -->
<script>
let json = [
{"name": "前期准备前期", "time": "2019-03-15", "style": "green", "actualTime": "2019-03-18"},
{"name": "技术评估", "time": "2019-03-18", "style": "red", "actualTime": "2019-03-25"},
{"name": "开发阶段", "time": "2019-03-20", "style": "red", "actualTime": "2019-03-30"},
{"name": "提测", "time": "2019-03-22", "style": "red", "actualTime": "2019-04-05"},
{"name": "新版本验证", "time": "2019-03-25", "style": "red", "actualTime": "2019-04-15"},
{"name": "仿真验证", "time": "2019-03-26", "style": "red", "actualTime": "2019-04-25"},
{"name": "预发布", "time": "2019-03-30", "style": "red", "actualTime": "2019-05-15"},
{"name": "待上线", "time": "2019-04-03", "style": "red", "actualTime": "2019-05-25"},
{"name": "已上线", "time": "2019-04-08", "style": "red", "actualTime": "2019-06-15"},
]
let canvasTop = 100
let everyRecBtw = 50
let everyRecHeight = 40
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width = window.screen.width;
canvas.height = 600;
var context = canvas.getContext("2d");
json.map((item, index) => {
item.width = item.name.length * 25
item.startY = canvasTop
json.reduce((prev, next, currentIndex, arr) => {
arr[currentIndex].startX = (~~prev.startX + ~~prev.width) + 50
return next
}, [])
item.baseLine = item.startX + item.width / 2
})
json.forEach((obj, index) => {
let fromX = obj.startX + obj.width
let fromY = canvasTop + everyRecHeight / 2
let toX = fromX + everyRecBtw
let toY = fromY
drawRoundRect(context, obj.startX, obj.startY, obj.width, everyRecHeight, 5, obj)
if (index+1 < json.length) {
drawArrow(context, fromX, fromY, toX, toY, 30, 10, 2, 'black')
}
})
}
// 画圆角矩形和文字
function drawRoundRect(ctx, startX, startY, width, height, radius, obj){
// 画圆角矩形
ctx.beginPath();
ctx.arc(startX + radius, startY + radius, radius, Math.PI, Math.PI * 3 / 2);
ctx.lineTo(width - radius + startX, startY);
ctx.arc(width - radius + startX, radius + startY, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(width + startX, height + startY - radius);
ctx.arc(width - radius + startX, height - radius + startY, radius, 0, Math.PI * 1 / 2);
ctx.lineTo(radius + startX, height + startY);
ctx.arc(radius + startX, height - radius + startY, radius, Math.PI * 1 / 2, Math.PI);
ctx.closePath();
// 画文字基线使文字对齐
ctx.moveTo(obj.baseLine, canvasTop);
ctx.lineTo(obj.baseLine, canvasTop + everyRecHeight);
ctx.stroke();
// 给矩形填充颜色
ctx.fillStyle = obj.style;
ctx.strokeStyle = "#000"
ctx.stroke();
ctx.fill();
// 写文字
ctx.textAlign = "center";
ctx.font = 'bold 16px Arial';
ctx.fillStyle = "#000";
ctx.fillText(obj.name, obj.baseLine, canvasTop + (everyRecHeight + 16) / 2); // 渲染图中文字
ctx.fillText(obj.time, obj.baseLine, canvasTop - 20); // 顶部时间
ctx.fillText(obj.actualTime, obj.baseLine, canvasTop + everyRecHeight + 20 + 16); // 底部时间
}
// 画箭头
function drawArrow(ctx, fromX, fromY, toX, toY, theta, headlen, width, color) {
var theta = theta || 30,
headlen = headlen || 10,
width = width || 1,
color = color || '#000',
angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
angle1 = (angle + theta) * Math.PI / 180,
angle2 = (angle - theta) * Math.PI / 180,
topX = headlen * Math.cos(angle1),
topY = headlen * Math.sin(angle1),
botX = headlen * Math.cos(angle2),
botY = headlen * Math.sin(angle2);
ctx.save();
ctx.beginPath();
var arrowX, arrowY;
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
arrowX = toX + topX;
arrowY = toY + topY;
ctx.moveTo(arrowX, arrowY);
ctx.lineTo(toX, toY);
arrowX = toX + botX;
arrowY = toY + botY;
ctx.lineTo(arrowX, arrowY);
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.stroke();
ctx.restore();
}
</script>