1、什么是canvas?
html5 《canvas》 是专门用来绘制图像的(通过脚本 通常是javascript),它的性能比xml好的多的多。不过canvas元素本身并没有绘制能力(它仅仅是图形的容器) - 你必须使用脚本来完成实际的绘图任务。getContext()方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。提供完整的getContent(“2d”)对象的属性和方法,可用于画布上绘制文本、线条、矩形、圆形、图片等等。 注意:canvas绘制出来的是像素,所以放大的时候会失真。
// 当然canvas 三要素 id 宽度 高度
// 当然 我们没办法直接在style里面设置宽度和高度
// 如何 理解不同?
<!--
canvas是一个画板和一张纸,画板相当于容器,画图是在画纸上进行的,
比如:画板和画纸的默认高度为 300*300 ,当画板和画纸等高的时候,图像就不会被拉伸,当画板和画纸不一样高的时候图像就会被拉伸。
width=“300” height=“300” 即画板的高度为 300 * 300 画纸的高度也是300*300
但是如果我们在 style里面设置 canvas的高度为600 * 600 ,也就是说 此时的画板是 600 *600 而画纸还是 300 * 300,画纸不会让画板空出一大片 于是画纸连同图像就要一起拉伸到跟画板大小一样。这就导致了图像的拉伸现象。
-->
<div class="canvas" style="background-color: red">
<canvas height="300" id="mycanvas" width="300"></canvas>
</div>
2、canvas的浏览器版本支持
canvas是h5正式发布的也就是2014年,但是2011年的时候canvas已经出来了。
( 比较先进的引擎:白鹭(游戏)、thress(全景360度)、虚幻4(吃鸡))
3、canvas容易忘记的知识总结
颜色填充
-
属性 | 描述 |
fillStyle = " red " | 设置或者返回用于填充绘制的颜色、渐变或者模式 |
strokeStyle = "red" | 设置或者返回用于路径的颜色、渐变或者模式 |
shadowColor | 设置或者返回用于阴影的颜色 |
shadowBlur | 设置或者返回用于阴影的模糊程度 |
shadowOffsetX | 设置或者返回阴影与性状的水平距离 |
shadowOffsetY | 设置或者返回阴影与性状的垂直距离 |
CSDN输入不同红色的字体
路径
-
方法 | 描述 |
fill() | 填充当前绘图 |
stroke() | 绘制已定义的路径 |
beginPath() | 起始一条路径,或者重置当前路径 |
moveTo() | 把路径移动到当前画布指定的点,不创建线条 |
closePath() | 创建从当前点回到起始点点路径 |
lineTo() | 添加一个新点,然后在画布中创建从该点到最后指定点的线条 |
clip() | 从原始画布剪切任意形状的尺寸的区域 |
quadraticCurveto() | 创建两次贝塞尔曲线 |
bezierCureveTo() | 创建三次贝塞尔曲线 |
arc() | 创建弧度/曲线/圆形 |
arcTo() | 创建两切线之间的弧度/曲线 |
isPointLnPath() | 如果指定的点位于当前路径中,则返回true,否则返回false |
线条样式
-
属性 | 取值 | 描述 |
lineCap | round 、butt、squaresquare | 设置或返回线条的结束端点样式 |
lineJoine | round、miter、bevel | 设置或返回两条线相交时,所创建的拐角类型 |
lineWidth | 1、2、3、4...... | 设置或返回当前的线条宽度 |
miterLimit | 1、2、3 | 设置或返回最大斜接长度 |
转换
-
|方法| 描述 |
|--|--|--|
| scale()|缩放当前绘图至更大或更小 |
| rotate() |旋转当前绘图|
| translate() |重新映射当前画布(0,0)的位置|
| transform() |替换绘图的当前转化矩阵|
| setTransform() |将当前转化重置为单位矩阵,然后运行 transform()|
4、canvas绘制内容总结
- 矩形
- 圆形
- 线、线段
- 文字
- 图片
- 颜色(渐变)
var c = document.getElementById("mycanvas"); var ctx = c.getContext("2d");
4.1 - 线段
ctx.moveTo(x0,y0)
ctx.lineTo(x1,y1)
ctx.lineTo(x2,y2)
ctx.stroke() // 上色
4.2 - 圆形
ctx.arc(x0,y0,r,0,Math.PI,true)// x0 y0 开始起始位置 r半径 0 Math.PI 圆的弧度 从什么位置到什么位置 true 为顺时针旋转画圆。
4.3 - 绘制矩形
ctx.beginPath() // 开始新的路径绘制图片
ctx.rect(x0,y0,x1,y1) // 开始点 和 结束点
ctx.fillStyle = "red" // 矩形填充颜色
ctx.fill() // 执行绘制填充
ctx.lineWidth = 10 // 绘制路径的宽度
ctx.strokeStyle = "yellow" // 渲染路径的颜色
ctx.stroke() // 执行渲染
ctx.closePath() // 绘制当前图像结束点
// 直接 绘制矩形
ctx.fillStyle = 'red'
ctx.fillReact(100,100,100,100)
4.4 - 文字属性
// 设置 文字 阴影
ctx.shadowBlur = 20 // 设置阴影大小
ctx.shadowColor = 'rgba(0,0,0,1)'
ctx.shadowOffsetX = 10
ctx.shadowOffsetY = 10
// 绘制文字
ctx.font = "16px 微软雅黑";//设置文字大小字体
ctx.fillText = ("hello word",0,100,500) //实心字体 内容 位置 和 最大宽度超过这个宽度就会文字收缩
ctx.fillStyle = "red" // 设置颜色
ctx.strokeText("hello word" ,0 ,100 ,100) // 空心字体
ctx.strokeStyle = "red"
// 文字 渐变
var gradient = ctx.createLinearGradient(0,0,canvas.width,0)
gradient.addColorStop("0","yellow")
gradient.addColorStop("0.5","blue")
gradient.addColorStop("1","red")
ctx.strokeStyle = gradient
// 文字 水平方向
ctx.textAlign = "center"
ctx.textAlign = "left"
// 文字垂直
ctx.baseLine = "top"
ctx.textBaseline = "middle"
4.5 - 绘制图片
var img = new Image()
img.src = "tupian.png"
img.onload = funtion(){
//第一种 定位绘制图片
ctx.drawImage(img , 0 , 0)
// 第二种 裁剪绘制
ctx.drawImage(img,0,0,100,100)
// 第三种 裁剪(位置 大小) 加 绘制(位置 大小)
ctx.drawImage(img , x0, y0 ,width , height , x1,y1,white , height )
}
获取元素像素点getImageData()
var imgData = content.getImageData(x,y,width,height) // 截取图片大小
ctx.putImageData(imgData,0,100) // 绘制截取的大小 和 内容
成型绘制
1、绘制 钟表
<!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>
<style>
</style>
</head>
<body>
<div class="canvas" style="background-color: #000">
<canvas height="800" id="mycanvas" width="650"></canvas>
</div>
</body>
</html>
<script>
var c = document.getElementById("mycanvas");
var ctx = c.getContext("2d");
function getTime() {
ctx.clearRect(0, 0, 800, 800);
ctx.save();
// 0 0 坐标位于原点
ctx.translate(300, 150);
ctx.rotate((-2 * Math.PI) / 4);
ctx.save();
// 绘制圆形
function getCircle(x0, y0, R, startR, endR, flag, width, color) {
this.x0 = x0;
this.y0 = y0;
this.R = R;
this.startR = startR;
this.endR = endR;
this.flag = flag;
this.width = width;
this.color = color;
}
// 封装 绘制 空心 圆形
getCircle.prototype.render = function () {
ctx.beginPath();
ctx.arc(this.x0, this.y0, this.R, this.startR, this.endR, this.flag);
ctx.lineWidth = this.width;
ctx.strokeStyle = this.color;
ctx.stroke();
ctx.closePath();
};
// 封装 绘制 实心 圆形 方法
getCircle.prototype.renders = function () {
ctx.beginPath();
ctx.arc(this.x0, this.y0, this.R, this.startR, this.endR, this.flag);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
};
class Scale {
constructor(rotate, x0, y0, x1, y1, width, color) {
this.rotate = rotate;
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
this.width = width;
this.color = color;
}
getScale() {
ctx.rotate(this.rotate);
ctx.beginPath();
ctx.moveTo(this.x0, this.y0);
ctx.lineTo(this.x1, this.y1);
ctx.strokeStyle = this.color;
ctx.lineWidth = this.width;
ctx.stroke();
ctx.closePath();
}
getHMS() {
ctx.beginPath();
ctx.rotate(this.rotate);
ctx.moveTo(this.x0, this.y0);
ctx.lineTo(this.x1, this.y1);
ctx.lineWidth = this.width;
ctx.strokeStyle = this.color;
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
}
}
class FillText {
constructor( rotate , font , fillStyle , fillText , x0 , y0 ){
this.rotate = rotate
this.font = font // 文字 大小
this.fillText = (fillText, x0 , y0) // 文字内容
this.fillStyle = fillStyle // 文字颜色
this.x0 = x0
this.y0 = y0
}
getText(){
ctx.beginPath()
ctx.rotate(this.rotate)
ctx.font = this.font
ctx.fillText = (this.fillText , this.x0 , this.y0)
ctx.fillStyle = this.fillStyle
ctx.stroke(); // 绘制 路径
ctx.closePath();
ctx.restore(); //从栈中弹出存储的图形状态并恢复 对象的属性、剪切路径和变换矩阵的值
ctx.save();
}
}
//绘制 60 的刻度线
for (var i = 0; i < 60; i++) {
var secondScale = new Scale(Math.PI / 30, 80, 0, 67, 0, 1, "white");
secondScale.getScale();
}
ctx.restore();
ctx.save();
//绘制刻度
for (var i = 0; i < 12; i++) {
var firstScale = new Scale(Math.PI / 6, 40, 0, 30, 0, 3, "white");
firstScale.getScale();
}
var litterScircle = new getCircle(
0,
0,
88,
0,
2 * Math.PI,
false,
"",
"white"
);
var litterScircles = new getCircle(
0,
0,
82,
0,
2 * Math.PI,
false,
"",
"white"
);
litterScircle.render();
ctx.restore();
ctx.save();
litterScircles.render();
ctx.restore();
ctx.save();
//获得当前的时间
var date = new Date();
var houre = date.getHours();
var min = date.getMinutes();
var sec = date.getSeconds();
var year = date.getFullYear();
var mon = date.getMonth() + 1;
var day = date.getDate();
var week = date.getDay();
var stu = [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
];
houre = houre > 12 ? houre - 12 : houre;
class drawHMS extends Scale {
constructor(rotate, x0, y0, x1, y1, width, color) {
super(rotate, x0, y0, x1, y1, width, color);
}
}
//绘制秒针
var s = new drawHMS(((2 * Math.PI) / 60) * sec, 0, 0, 30, 0, 1, "white");
s.getHMS();
//绘制分针
var m = new drawHMS(
((2 * Math.PI) / 60) * min + ((2 * Math.PI) / 3600) * sec,
0,
0,
25,
0,
3,
"white"
);
m.getHMS();
//绘制时针
var h = new drawHMS(
((2 * Math.PI) / 12) * houre + ((2 * Math.PI) / 12 / 60) * min,
0,
0,
20,
0,
4,
"white"
);
h.getHMS();
ctx.restore();
ctx.restore();
// ctx.beginPath()
// // 绘制文字 内容
// const timers = [1,2,3,4,5,6,7,8,9,10,11,12]
// var filltext = new FillText(Math.PI / 60 , '16px 宋体' , ('2321321' ,25, 30), 'red')
// filltext.getText()
}
getTime();
setInterval(() => {
getTime();
}, 1000);
</script>