前言:
网站浏览页面:http://ntvu.love:88/chapter1/
最终效果浏览:
一、canvas 简介
<canvas> 是 HTML5 新增的,一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
它最初由苹果内部使用自己 MacOS X WebKit 推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。后来,有人通过 Gecko 内核的浏览器 (尤其是 Mozilla和Firefox),Opera 和 Chrome 和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。
Canvas 是由 HTML 代码配合高度和宽度属性而定义出的可绘制区域。JavaScript 代码可以访问该区域,类似于其他通用的二维 API,通过一套完整的绘图函数来动态生成图形。
Mozilla 程序从 Gecko 1.8 (Firefox 1.5) 开始支持 <canvas>, Internet Explorer 从 IE9 开始 <canvas> 。Chrome 和 Opera 9+ 也支持 <canvas>。
参考链接:https://www.runoob.com/w3cnote/html5-canvas-intro.html
二、如何使用canvas
引入canvas:这里创建了一个canvas,id为bar
[qzdypre]
<!--创建一个id为bar的画布-->
<canvas id="bar"></canvas>
[/qzdypre]
设置canvas的宽和高:如果不给 <canvas> 设置 widht、height 属性时,则默认 width为300、height 为 150,单位都是 px。也可以使用 css 属性来设置宽高,但是如宽高属性和初始比例不一致,他会出现扭曲。所以,建议永远不要使用 css 属性来设置 <canvas> 的宽高。
[qzdypre]
<!--以下为js代码-->
<script type="text/javascript">
let canvasWidth=900; //设置画布的宽度常量
let canvasHeight=600; //设置画布的高度常量
let canvas=document.querySelector('#bar') //选择id为bar的画布
canvas.width=canvasWidth;
canvas.height=canvasHeight;
[/qzdypre]
以上代码中使用了两个常量来设置了画布的宽和高,其中注意要选中画布必须执行line5,选中画布的ID才会生效。
详解:
如何让画布在页面中居中,使画面更美观?
首先答案是按照以往的经验使用margin-left:auto和margin-right:auto在这里是不管用的。
如果蓝色代表画布,绿色框内代表页面区域,那么要让他在页面水平方向居中,我们可以用
(W1(总宽度) - W2(画布宽度) )/2来设置为画布的左边距,即可让画布居中。
为了让画面看的清楚,我们设置画布的背景为灰色,然后用上面的思路看看能不能实现页面居中,代码如下:
[qzdypre]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#bar{
background: #EEE;
}
</style>
</head>
<body>
<canvas id="bar"></canvas>
<script type="text/javascript">
let canvasWidth=900;
let canvasHeight=600;
let canvas=document.querySelector("#bar");
canvas.width=canvasWidth;
canvas.height=canvasHeight;
canvas.style.marginLeft=(canvas.parentElement.clientWidth-canvas.width)/2+"px";
</script>
</body>
</html>
[/qzdypre]
效果如图:
为了制作一个柱形图,现在我们需要用getContext来获取一个2d的上下文。
这个上下文是用来绘制2D图形的。一旦获取了这个上下文,我们就可以在其上绘制形状、添加文本、创建图像等。
[qzdypre]let ctx=canvas.getContext("2d");[/qzdypre]
这行代码的意思是:从HTML文档中获取一个Canvas元素(这里命名为
canvas),并获取其2D渲染上下文(Context)。
之后我们来绘制画布的左边框和下边框:
[qzdypre]
ctx.strokeStyle="red"; //设置颜色
ctx.lineWidth=4;
ctx.moveTo(0,0);
ctx.lineTo(0,canvasHeight);
ctx.lineTo(canvasWidth,canvasHeight);
ctx.stroke();
[/qzdypre]
代码详解:
首先我们需要运算数据。
我们提供以下五个等级,并且赋予不同等级不同的人数
[qzdypre]let data=[["A",5],["B",15],["C",20],["D",12],["E",18],["F",9]];[/qzdypre]
根据元素数量来遍历data数组,以此来获取柱形的个数,高度等。
再创建一个颜色数组,以此来表示每个柱形不同的颜色,更美观更好区分。
[qzdypre]let colors=["red","green","blue","pink","brown","yellow","black","grey"];[/qzdypre]
根据思路,第二个柱形需要2个间隙和1个柱形宽,那么第n个柱形需要n个间隙和(n-1)个柱形宽,由此我们设置间隙宽度(偏移量)offset,柱形宽度barWidth和size。
[qzdypre]
let len=data.length;
let offset=canvasWidth*0.5/(len+1);
let barWidth=canvasWidth*0.5/len;
let size=barWidth/4;
[/qzdypre]
之后我们通过创建一个总数变量来获取数据的总数,因为data为二维数组,我们需要获取其人数总数,所以我们设置total为:
[qzdypre]
let total=0;
for (let i=0;i<len;i++){
total+=data[i][1];
}
[/qzdypre]
之后求出其数值后,来确定他的百分比,这里需要将多位小数转换为一位小数和四舍五入,在JavaScript中,Math.round方法用来四舍五入,那我们需要考虑如何才能将多位小数变为百分数。
首先创建一个百分比数组
[qzdypre]let percent=[];[/qzdypre]
然后我们通过循环来将计算的比例转化为百分数
[qzdypre]
for (let i=0;i<len;i++){
percent.push(Math.round(data[i][1]/total*100*10)/10);
}
[/qzdypre]
push的作用是将一个或多个元素添加到数组的末尾,并返回新的长度。
在给定的代码段中,[qzdypre]percent.push(Math.round(data[i][1]/total*100*10)/10);[/qzdypre]用于将计算得到的数据添加到percent数组的末尾。具体来说,这段代码计算每个数据元素(data[i][1])占总数(total)的百分比(data[i][1]/total*100*10),然后四舍五入到最近的十分之一(Math.round(...)),最后将结果除以10。这个结果是作为一个整数添加到
percent数组的。
设计柱形图的最大高度:
思路:我们将百分比最大的(即占比最大的柱形)设置为整个画布高度的80%,之后所有按照顺序依次按比例调整高度。
首先找出最大的百分比,代码如下:
[qzdypre]let maxPercent=Math.max(...percent);[/qzdypre]
Math.max可以传入一个数组或数字,这点值得注意。
之后将最大的柱形高度设置为整高度的80%
[qzdypre]let maxBarHeight=0.8*canvasHeight; //设置最大高度为画板的80%[/qzdypre]
一切准备就绪,下面来绘制柱形图:
[qzdypre]
for (let i=0;i<len;i++){
ctx.fillStyle=colors[i];
ctx.fillRect((i+1)*offset+i*barWidth,canvasHeight-percent[i]/maxPercent*maxBarHeight,barWidth,percent[i]/maxPercent*maxBarHeight-ctx.lineWidth/2);
ctx.fillText(percent[i],(i+1)*(offset+barWidth)-0.6*barWidth,canvasHeight-percent[i]/maxPercent*maxBarHeight-10);
ctx.fillRect(ctx.lineWidth*2,size/2*(i+1)+i*size,size,size);
ctx.fillText(`${data[i][0]}${data[i][1]}`,ctx.lineWidth*2+size*1.5,size/2*(i+1)+i*size+size/1.5);
}
[/qzdypre]
首先通过循环调用不同的颜色来代表不同的柱形,每个条形图的颜色是数据对应的百分比所决定的。
文章评论