文章目录
- canvas核心内容
-
- 1、概念
-
-
-
-
- 提示:
-
-
-
- 2、绘制直线
-
-
- 案例:
-
- 3、绘制矩形
-
-
- 案例:绘制柱状图
-
- 4、绘制曲线
-
-
- 案例一:时钟
- 案例二:饼状图
-
- 5、绘制文本信息
-
-
- 案例:
-
- 6、绘制图片
-
-
- 案例:
-
- 7、清除画布指定元素
-
-
- 案例:橡皮擦
-
canvas核心内容 1、概念 canvas是画布,其实就是h5的一个新标签,他自己有一套画图的语法标准。
canvas本身没有任何的绘图能力,所有的绘图工作都是通过js来实现的。通常我们在js通过getElementById来获取要操作的canvas(这意味着咱得给canvas设个id):
>
var c = document.getElementById("myCanvas");
//获取要操作的canvas
//操作canvas的代码...
注意最好在一开始的时候就给canvas设置好其宽高(若不设定宽高,浏览器会默认设置canvas大小为宽300、高100像素),而且不能使用css来设置(会被拉伸,有失真的风险),建议直接写于canvas标签内部:
当然,也可以在脚本中设置:
>
var c = document.getElementById("myCanvas");
c.width=200;
c.height=200;
要知道的是; 超出此大小范围的部分是不可见的。顾名思义,可以把canvas看成一块画布,其大小是咱设定好的宽高,那么无论你怎么画,画布外的地方自然是画不到的。
.getContext() 是canvas的绘图对象/方法,要让canvas执行绘图工作必须先获取canvas的.getContext()对象来执行。
.getContext()只接受一个参数,该参数用于获取canvas的绘图环境,例如.getContext(“2d”)表示该canvas的绘图环境为2D平面(可以绘制文本、直线、弧线、矩形、圆形等)。还有3D环境,自行研究。
提示: vscode中获取提示内容,在script脚本中加入:
/** @type {HTMLCanvasElement} */
上面这一行代码,表示引入canvas,就会出现提示内容。
2、绘制直线
>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//获取该canvas的2D绘图环境对象
ctx.moveTo(10,10);
//定义绘画开始的位置
ctx.lineTo(150,50);
//画一条直线,结束点坐标是x=150,y=50
ctx.stroke();
//描边
效果如下:
文章图片
- .moveTo(x坐标 , y坐标) 可以理解为定位画笔在画布上的位置(注意所有绘图方法所定义的坐标是相对canvas而言的而不是浏览器窗口,对canvas来说,最左上角的点的坐标是(0,0))
- .lineTo(x坐标 , y坐标) 顾名思义,就是画一条直线到某个点,很好理解。需要知道的是此方法仅仅做路径运动,而不存在任何视觉上的绘图效果(上色、描边)。如果不另外设置moveTo则自动把上一条边的终点作为下一条边的起点。
- .stroke() 描边方法,canvas想要运动路径轨迹能有视觉效果,需要使用相应的上色/描边方法。
- .strokeStyle = “red”;
设定描边颜色为红色,只要写在.stroke()方法前面即可。
- ctx.strokeStyle可获值的形式有三种:用的时候查一查
ctx.strokeStyle=color|gradient|pattern; //即支持 “颜色/渐变/图案笔刷” 的赋值
案例:
>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(150,50);
ctx.lineTo(20,100);
ctx.strokeStyle = "blue";
//设定描边颜色为蓝色
ctx.stroke();
ctx.beginPath();
//告诉canvas咱们要重新绘制一条全新的路径了,之前画的东西从此再无关系
ctx.moveTo(90,90);
ctx.lineTo(80,150);
ctx.strokeStyle = "red";
//设定描边颜色为红色
ctx.stroke();
效果如下:
文章图片
3、绘制矩形 canvas本身就自带绘制矩形的方法;ctx.rect(x,y,w,h);
参数说明:
- x,y:表示起点坐标,以画布左上角为坐标中心,x向右增大,y向下增大。
- w,h:分别代表矩形的宽高。
>
var canvas = document.getElementById("box");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "red";
ctx.fillStyle = "blue";
ctx.lineWidth = 5;
ctx.beginPath();
ctx.rect(100, 100, 200, 200);
ctx.closePath();
//闭合通道ctx.fill();
//填充ctx.stroke();
//描边
效果如下:
文章图片
如果我们想给一个图像不仅要填充,还要绘制边框,那我们要先填充,后绘制边框,这样我们的边框才会正常显示。
所以还有另外的方法:fillRect(x,y,w,h)和strokeRect(x,y,w,h);
>
var canvas = document.getElementById("box");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "red";
ctx.fillStyle = "blue";
ctx.lineWidth = 5;
ctx.strokeStyle = 'red';
ctx.fillRect(100, 100, 200, 200);
ctx.strokeRect(100, 100, 200, 200);
效果如上一样。
案例:绘制柱状图
>
#box {
border: 2px solid pink;
}
>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector('#box');
var ctx = canvas.getContext('2d');
var arr = [234, 535, 2343, 4266, 2345, 7895];
var arr1 = ['红烧肉', '鸡腿', '肘子', '火锅', '串串', '冒菜']
ctx.lineTo(50, 500);
ctx.lineTo(580, 500);
ctx.stroke();
var h = 450 / Math.max(...arr);
for (let i = 0;
i < arr.length;
i++) {
ctx.fillStyle = 'blue';
ctx.strokeText(arr1[i], 100 + i * 73, 520);
ctx.fillRect(100 + i * 70, 500 - h * arr[i], 50, h * arr[i]);
}
效果如下:
文章图片
4、绘制曲线 方法:ctx.arc():在当前子路经添加一条弧线;
语法:context.arc(x,y,r,sAngle,eAngle,counterclockwise);
参数 | 描述 |
---|---|
x | 圆的中心的 x 坐标。 |
y | 圆的中心的 y 坐标。 |
r | 圆的半径。 |
sAngle | 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。 |
eAngle | 结束角,以弧度计。 |
counterclockwise | 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。 |
>
#box {
border: 2px solid black;
}
>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector('#box');
var ctx = canvas.getContext('2d');
//角度转换单位度
let deg = Math.PI / 180;
//表盘的绘制
function biaopan() {
//圆心(300,300) 半径:200,从0度-360度画圆
ctx.arc(300, 300, 200, 0, 360 * deg)
//刻度
//设置开始角度6度 刻盘上每两个刻度之间的角度是6度
var startAnge = 6,
r = 200,
y1 = 300,
x1 = 300;
var kedu = 10;
//刻度的长度
for (let i = 0;
i < 60;
i++) {
var kedu = 10;
//刻度的长度,i%5为真时刻度不变,为假时长度变为二倍
let a;
if (i % 5) {
a = kedu;
} else {
a = kedu * 2;
}//计算每个刻度所在的坐标
var y2 = y1 + r * Math.sin(i * startAnge * deg);
var x2 = x1 + r * Math.cos(i * startAnge * deg);
var y3 = y1 + (r - a) * Math.sin(i * startAnge * deg);
var x3 = x1 + (r - a) * Math.cos(i * startAnge * deg);
//刻度连线
ctx.moveTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.stroke();
}}//绘制表针
function biaozhen() {
//三根针的长度
var sh = 160,
mh = 130,
hh = 100;
var s = new Date().getSeconds();
ctx.moveTo(300, 300);
//秒针
var x4 = 300 + sh * Math.cos(s * 6 * deg);
var y4 = 300 + sh * Math.sin(s * 6 * deg);
//分针,一秒钟分针转动1/10度
var x5 = 300 + mh * Math.cos(s * 1 / 10 * deg);
var y5 = 300 + mh * Math.sin(s * 1 / 10 * deg);
//时针,一秒钟分针转动1/120度
var x6 = 300 + hh * Math.cos(s * 1 / 120 * deg);
var y6 = 300 + hh * Math.sin(s * 1 / 120 * deg);
ctx.lineTo(x4, y4);
ctx.moveTo(300, 300);
ctx.lineTo(x5, y5);
ctx.moveTo(300, 300);
ctx.lineWidth = 2;
ctx.lineTo(x6, y6);
ctx.stroke();
}
setInterval(() => {
canvas.width = canvas.width;
//清除上一次的直线
biaopan()
biaozhen()
}, 1000)
效果图:
文章图片
案例二:饼状图
>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector('#box');
var ctx = canvas.getContext('2d');
//模拟数据,一个月的消费统计
var arr = [{
name: '食物',
money: 1870
},
{
name: '出行',
money: 2470
},
{
name: '衣服',
money: 3470
},
{
name: '药物',
money: 470
},
{
name: '其他',
money: 1470
},
]
//添加元素记录总金额
arr.total = 0;
for (let j = 0;
j < arr.length;
j++) {
//计算总金额
arr.total += arr[j].money;
}//开始绘制的角度位置
var start = 0;
for (let i = 0;
i < arr.length;
i++) {
//每一次绘制扇形呈现不一样的颜色,所以要开启新的轨道
ctx.beginPath()
//每一个扇形的比例
var bili = arr[i].money / arr.total * 360;
//换算一度的单位deg保存
var deg = Math.PI / 180;
//绘制扇形
ctx.arc(300, 300, 200, start * deg, (start + bili) * deg);
//每次扇形绘制的终点,为下一个扇形绘制的起点//添加文字到每个角度的中心线
var x = 300 + 230 * Math.cos(((start + bili) - bili / 2) * deg);
var y = 300 + 230 * Math.sin(((start + bili) - bili / 2) * deg);
//设置文字大小,字体样式
ctx.font = " 14px sans-serif"
//设置文字颜色
ctx.fillStyle = 'black';
//设置文字水平方向居中
ctx.textAlign = "center";
//设置垂直方向居中
ctx.textBaseline = "middle"
ctx.fillText(`${arr[i].name}`, x, y)
start = start + bili;
//每次扇形绘制的终点与圆心连接起来
ctx.lineTo(300, 300);
//生成随机色
let r = parseInt(Math.random() * (255));
let g = parseInt(Math.random() * (255));
let b = parseInt(Math.random() * (255));
ctx.fillStyle = `rgb(${r},${g},${b})`;
//填充颜色
ctx.fill()
//绘制图形
ctx.stroke()
}
效果图:
文章图片
5、绘制文本信息 1、font属性:可以设置字体的大小和字体名称。
fillText方法的作用:填充文字。
ctx.fillText("我是微软雅黑",100,100);
第一个参数:填充的文字内容。
第二、三个参数: 绘制的内容; 起点x坐标; 起点y坐标。
2、textAlign属性的作用:文字水平的对齐方式。
ctx.textAlign = "left";
3、textBaseline则指定垂直方向,可选值:top、hanging,middle,等
ctx.textBaseline='middle';
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRTI5J4b-1658633907279)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220724111833533.png)]
案例:
>
canvas{
border: 1px solid black;
}
>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//写文字
ctx.font = "30px 微软雅黑";
ctx.textAlign = "left";
ctx.fillText("我是微软雅黑",100,100);
// (100,100)是绘制文字的位置
效果如下:
文章图片
6、绘制图片 drawImage():将原图片像素的内容复制到画布上;
? 第一个参数是源图片,可以是img元素或Image构造函数创建的屏幕外图片对象;
? 三个参数时: 指定图片绘制的x、y坐标;
? 五个参数时: 指定图片绘制的x、y坐标,以及图片的宽度、高度;
? 九个参数时: 裁剪的对象 裁剪的位置(x,y); 裁剪的宽度和高度(w,h); 裁剪后图片绘制的位置(x,y); 图片显示出来的宽度和高度(w,h);
参数 | 描述 |
---|---|
img | 规定要使用的图像、画布或视频。 |
sx | 可选。开始剪切的 x 坐标位置。 |
sy | 可选。开始剪切的 y 坐标位置。 |
swidth | 可选。被剪切图像的宽度。 |
sheight | 可选。被剪切图像的高度。 |
x | 在画布上放置图像的 x 坐标位置。 |
y | 在画布上放置图像的 y 坐标位置。 |
width | 可选。要使用的图像的宽度。(伸展或缩小图像) |
height | 可选。要使用的图像的高度。(伸展或缩小图像) |
案例:
- 获取页面已经存在的图片节点,绘制到画布上。
> #box { border: 2px solid black; }
文章图片
> /** @type {HTMLCanvasElement} */ var canvas = document.querySelector('#box'); var img1 = document.querySelector('img') var ctx = canvas.getContext('2d'); img1.onload = function () { ctx.drawImage(img1, 20, 20, 100, 100); }
- 创建构造函数加载图片
> #box { border: 2px solid black; } > /** @type {HTMLCanvasElement} */ var canvas = document.querySelector('#box'); var ctx = canvas.getContext('2d'); var imgobj = new Image(); imgobj.src = 'https://www.it610.com/dom/image/flower1.png' imgobj.onload = function () { ctx.drawImage(imgobj, 20, 20, 100, 100); }
效果如下:
文章图片
JavaScript 语法:
context.clearRect(x,y,width,height);
参数 | 描述 |
---|---|
x | 要清除的矩形左上角的 x 坐标 |
y | 要清除的矩形左上角的 y 坐标 |
width | 要清除的矩形的宽度,以像素计 |
height | 要清除的矩形的高度,以像素计 |
Document - 锐客网
>
#box {
border: 2px solid black;
}.cut {
width: 60px;
height: 60px;
background: url(./image/橡皮擦.png);
background-size: cover;
/* background-color: green;
*/
position: absolute;
display: inline-block;
}
画布内点击生花,拖动右方橡皮擦擦除画布>
/** @type {HTMLCanvasElement} */var canvas = document.querySelector('#box');
var ctx = canvas.getContext("2d");
var cut = document.querySelector('.cut');
cut.addEventListener('mousedown', function (e) {
// console.log(1111);
var x = e.pageX - cut.offsetLeft;
var y = e.pageY - cut.offsetTop;
document.addEventListener('mousemove', move);
function move(e) {
cut.style.left = (e.pageX - x) + 'px';
cut.style.top = (e.pageY - y) + 'px';
ctx.clearRect(e.pageX - x, e.pageY - y, 40, 40);
}document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
})
})var imgobj = new Image();
imgobj.src = 'https://www.it610.com/dom/image/flower1.png';
//点击生花
imgobj.onload = function () {
canvas.addEventListener('click', function (e) {
var x = e.pageX - 30,
y = e.pageY - 30;
ctx.drawImage(imgobj, x, y, 60, 60);
})
}
效果如下:
文章图片
推荐阅读
- 前端|web靶场 ----- xss-labs
- vue|探索学习 Vue 组件篇 第四篇 组件的嵌套
- 前台vue|vue 实现多个视频播放 vue-video-player
- css|【玩转CSS】一文带你了解浮动
- html|学成在线官网首页完整版(含psd源文件)
- 前端|刷题,巩固基础的好方法
- 前端|web学习笔记之JavaScript(一)
- 前端笔记|TypeScript基础
- 前端|flex布局