canvas:画布,h5新标签;
-
canvas本身没有任何外观,只是在文档中创建了一个画板;
-
ie9之前的版本不支持canvas;
-
画布的宽度和高度要用canvas的属性设置,不要直接在css里面定义;
-
画布的
getContext()
方法返回一个“绘制上下文”对象; 绝大多数的画布绘制API来自这个对象; 也就是说画布元素和他的上下文对象是两个完全不同的概念; 调用该方法时,传递的参数是“2d”,也就是getContext('2d')
,可以在画布上绘制二维图像; 3d绘制就相对比较复杂了,具体实现还在规范中;
坐标是按左上角(0,0)来计算的
canvas的常用方法:
1.绘制线段的API是上下文对象的方法;
2.beginPath:开始定义一条新的路径;
3.moveTo:开始定义一条新的子路径,该方法确定了线段的起点;
4.lineTo:将上面定义的线段起点和指定的新的点连接起来;
5.到这里只是规划好了思路,还没有在画布上画出任何图形;
6.fill():填充区域,此时只是填充,起点和终点并没有连接起来;
7.closePath:会把起点和终点连接起来;
8.stroke():开始绘制图形,当前路径下的所有子路经都会绘制出来;
9.如果要接着绘制新的路径,记得调用beginPath()方法;
下面来看看我写的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style>
#box {
border: 1px black solid;
}
</style>
<body>
<canvas id="box" height="700" width="700"> </canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("#box")
var ctx = canvas.getContext("2d")
var arr = [57, 76, 24, 67, 78, 15, 34, 19, 25, 87]
var res = []
setInterval(() => {
arr.push(parseInt(Math.random()*100))
for(i=arr.length-11;i<arr.length-1;i++){
res=arr.slice(-10)
}
console.log(res)
}, 500)
setInterval(() => {
canvas.height = 700
huabu()
ctx.beginPath()
for(i=0;i<res.length;i++){
ctx.lineTo(i*50+50,400-res[i])
}
ctx.strokeStyle="red"
ctx.stroke()
}, 500)
var jianju = 10
function huabu() {
for (var i = 0; i < parseInt(700 / jianju); i++) {
ctx.moveTo(0, i * jianju)
ctx.lineTo(700, i * jianju)
ctx.moveTo(i * jianju, 0)
ctx.lineTo(i * jianju, 700)
}
ctx.stroke()
ctx.beginPath()
ctx.lineWidth = 5
ctx.moveTo(50, 650)
ctx.lineTo(650, 650)
ctx.moveTo(625, 625)
ctx.lineTo(650, 650)
ctx.moveTo(625, 675)
ctx.lineTo(650, 650)
ctx.moveTo(50, 650)
ctx.lineTo(50, 50)
ctx.moveTo(25, 75)
ctx.lineTo(50, 50)
ctx.moveTo(75, 75)
ctx.lineTo(50, 50)
ctx.stroke()
}
</script>
</body>
</html>
思路讲解:
第一步:我们要画出来背景板也就是一个表格,我们使用for循环来画画布,先设定好表格的间距,for的次数小于canvas的宽度除以我们的间距,然后用x=i*间距,y从0开始到画布高度,x从0开始到画布高度,y=i*间距,就画出了画板样式,然后我们另起一个轨迹去我们的坐标轴,将这一块代码保存在一个函数当中,为什么要保存在一个函数当中呢?接下来会讲解
第二步:我们设置一个数组,使用定时器不断的往这个数组里面添加数据,但是呢,就面临了一个问题,什么问题呢?这个数组越来越大,但是我们的canvas画板的大小是有限的,所以定义了一个新的数组,这个数组保存的是切片,切片从第一个数组的最后第十个开始一直到最后,以保证每次都能够去取到最后十位数也保证了能够取到最新的数据。
第三步:开始绘制,绘制也要放在定时器里面,为什么呢?因为我们要清空画板,如果不清空画板,轨迹重合的地方颜色就会越来越重,我使用的是重置宽度的办法来清空画板,清空画板之后,重新调用我们第一步的函数来制作画板,然后另外开启一条轨迹来开始绘制,使用for循环来使横坐标增大,纵坐标则使用第二个数组里面保存的数据。
给出的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>q
<style>
#box {
border: 1px gray solid;
/* width:200px;
height: 200px; */
}
</style>
<canvas id="box" width="600" height="600">
如果你不认我 我就会显示出来
</canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector('#box')
var ctx = canvas.getContext("2d")
var x=60
var arr=[30,60,80,90,70,45,50,66,30,49,80,40,70,70,20,40,50,30,60,50,40,50,50]
setInterval(()=>{
arr.push(Math.random()*(320-10)+10)
// arr.shift(1)
})
setInterval(()=>{
//清除画板
canvas.width=600
x-=(30/(1000/300))
drawori()
draw()
},300)
function draw(){
//开启另外套轨迹
ctx.beginPath()
ctx.lineWidth=5
ctx.strokeStyle="green"
for(let i=0;i<arr.length;i++){
if(i*30+x<-30){continue}
ctx.lineTo(i*30+x,400-arr[i])
}
ctx.stroke()
}
function drawori(){
//开启一套轨迹
ctx.beginPath()
ctx.lineWidth=1
ctx.strokeStyle="gray"
var m=10
for(var i=0;i<parseInt(600/m);i++){
ctx.moveTo(0,i*m)
ctx.lineTo(600,i*m)
ctx.moveTo(i*m,0)
ctx.lineTo(i*m,600)
}
ctx.stroke()//绘制
//开启另外套轨迹
ctx.beginPath()
ctx.lineWidth=3
ctx.strokeStyle="grey"
ctx.moveTo(50,50)
ctx.lineTo(50,500)
ctx.lineTo(580,500)
ctx.lineTo(550,510)
ctx.moveTo(580,500)
ctx.lineTo(550,490)
ctx.moveTo(50,50)
ctx.lineTo(60,80)
ctx.moveTo(50,50)
ctx.lineTo(40,80)
ctx.stroke()//绘制
}
</script>
</body>
</html>
tip:清空画板的方式很多:
1.canvas高度或宽度被重设时,画布内容就会被清空,也就是我代码中使用的办法(利用的是浏览器重绘的方法)
2.使用clearRect方法:(官方清理画布的方法)
this.board = this.canvas.getContext("2d");
clean() {
this.board.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
3. 使用颜色填充清空画布:(利用取巧的办法)