要建立一个canvas,其实只要在HTML中添加标签:<canvas></canvas>
就好了。 如果考虑浏览器的兼容问题,只需在标签中加上一行文字:javascript
<canvas>
您的浏览器不支持canvas
</canvas>
复制代码
便可达到「 友好提示用户 」的效果。html
若是要“画东西”,也就是所谓的“操纵canvas元素”,则必要借助于DOM事件:java
//获取canvas
var canvas=document.querySelector('canvas标签中的id/class名');
//获取“上下文对象“
var ctx=canvas.getContext("2d");
复制代码
其中“上下文对象”你能够理解为是“绘图的环境(参数)”,而“2d”表明“要绘制2d(平面)图形” —— 一样的,“3d”表示“绘制3d(立体)图形”。canvas
canvas坑一: 若要改变canvas“画布”的大小,最好在canvas标签的style属性中或在JS中动态进行。若经过class/id-style中修改(执行),会形成“总体缩放”——包括后面说到的lineTo线条也是这样。浏览器
//style
.canvas{
border: 1px solid red;
width: 200px;
height: 200px;
}
//html
<canvas class="canvas">
您的浏览器不支持canvas
</canvas>
//JS
var canvas=document.querySelector('.canvas');
var ctx=canvas.getContext("2d");
console.log(canvas.width,canvas.height); //canvas中能够直接操做canvas所用到属性的各个CSS,这个后面还会提到
//下面三行先没必要管
ctx.moveTo(0,0);
ctx.lineTo(200,200);
ctx.stroke()
复制代码
上面说了,经过JS操做canvas元素前要先dom
下面的一些demo就省去这两行代码了。。。函数
首先,你要画好比一条线/一个图的话,假如canvas如今是你手中的一杆画笔,那你就要先“提笔” —— 从哪开始画:字体
ctx.moveTo(0,0); //移动到【画布的】(0,0)坐标处“落笔”
复制代码
moveTo的两个参数分别是:起始坐标X、Y。 而后 如果画直线,能够调用lineTo - API:动画
ctx.lineTo(100,100); //从画布的(0,0)处“画”到(100,100)处
复制代码
而后其实能够继续lineTo()...ui
ctx.lineTo(100,200); //从画布的(100,100)处“画”到(100,200)处
复制代码
这时,这些线条还只是在【内存】中,要其真正显示到页面上,则需调用stroke():
ctx.stroke();
复制代码
ctx坑二: 若要再画一条线,很多初学者可能会将以上“绘制”部分代码再CV一遍,改变坐标即“大功告成”,可是真是这样的吗? 经检验,第一条线要“深色”一些:这是由于整段代码有两个stroke() —— 即第一条线被“画”了两次。
其实若要画多个图形,只要先把moveTo、lineTo...所有完成,再调用一次 ctx.stroke();
便可。 但这样一来又有一个问题:如果就想让两条线颜色不同怎么办? canvas API提供了下面的函数:
ctx.beginPath(); //开启一条“新的”内存路径
复制代码
只要把这个函数加到“第二条绘制线”的moveTo函数前便可。
上面是画线,那么诸如圆、长方形...这些图形怎么画?
圆形:ctx.arc(参数1,参2,参3,起始弧度,终止弧度,顺时针/逆时针画);
ctx.arc(300,300,50,0,2*Math.PI,true);
ctx.stroke();
复制代码
矩形:ctx.strokeRect(左上角X,左上角Y,宽,高);
(由于是strokeRect这种stroke前缀的函数其实都是通过stroke()封装过的,因此能够直接显示在屏幕上)
其实,矩形还有两种画法:
ctx.closePath()
将图形路径闭合曾经看到好多“图片+JS雪花掉落效果”,其实这个用canvas也能够实现:
var circles = [];
setInterval(function() {
// 擦出画布
animCtx.clearRect(0, 0, animCtx.canvas.width, animCtx.canvas.height); //animCtx是canvas元素上下文对象
// 绘制下落的圆形
for(var i=0; i<=10; i++) {
if(!circles[i]) { //保证每片“雪花”垂直下落
circles[i] = {};
circles[i].radius = Math.floor(Math.random() * 5) + 1;
circles[i].y = - circles[i].radius - Math.floor(Math.random() * 10);
circles[i].x = i * 60 + Math.floor(Math.random() * 10) - 5;
circles[i].vy = Math.floor(Math.random() * 5) + 1;
}
animCtx.beginPath();
animCtx.arc(circles[i].x, circles[i].y, circles[i].radius, 0, Math.PI * 2);
animCtx.fillStyle = "rgba(255, 255, 255, 0.5)";
animCtx.fill();
circles[i].y = circles[i].y + circles[i].vy;
if(circles[i].y > animCtx.canvas.height + circles[i].radius * 2) {
circles[i] = undefined;
}
}
}, 100);
复制代码
上面的图形画着是挺爽的,就是颜色未免太单一了一些: 咱们能够经过 ctx.fill()
填充函数填充整个图形(内部)为“黑色”(默认颜色)(视觉上看“自动闭合了路径”)emmmmmmm,这样所有都变成黑色了,不过我能够在前面用 ctx.fillStyle="颜色值"
来改变整个图形的颜色。
如果要只改变图形边框的颜色呢?其实上面说的一个函数自己就有“描边”的功能:ctx.stroke()
。 你固然能够理解为“只有为图形边框添加了颜色,才能显示出来”,毫无疑问,它默认也是黑色的。不过咱们也能够用API:ctx.strokeStyle="颜色值"
来改变图形边框的颜色。 咱们还能够经过 ctx.lineWidth=数字值;
来改变边框的宽度。
canvas中容许“边框设置”和“填充设置”同时出现。
如上面“画线”所说:
ctx.moveTo(0,0);
ctx.lineTo(100,100);
ctx.stroke();
复制代码
平移:ctx.translate(X方向,Y方向);
你们能够试下分别将translate函数放在moveTo前、lineTo前、最后,分别有什么效果!
旋转:ctx.rotate(旋转角度);
—— 以弧度为单位:
//旋转45°
ctx.rotate(Math.PI / 4);
复制代码
缩放:ctx.scale(X轴缩放,Y轴缩放);
//X轴不缩放,Y轴变为原来的1/2
ctx.scale(1,0.5);
复制代码
图形变换的效果也会“自上而下叠加”!
若是以为叠加效果并非想要的,能够将某个变换片断代码放到 ctx.save()
【保存环境函数】和 ctx.restore()
【恢复环境函数】(恢复到save()函数以前的环境)的“包裹”中。
var str="hello world";
复制代码
咱们怎么把展现到canvas画布中呢?
ctx.fillText(str,0,100); //参数:文字,X坐标,Y坐标
//或
ctx.strokeText(str,0,200); //如有颜色,则上面的为填充,这里为描边(字体呈镂空效果)
复制代码
填充:
能不能改变他的样式? (开头说了一句“canvas里能直接改变元素CSS样式值”不知道你们还记得不记得)
ctx.font="50px sans-serif"; //改变字体大小
复制代码
而且加上strokeText函数:
ctx.textAlign="center"; //文字居中(水平)
复制代码
ctx.textBaseline="middle"; //文字垂直居中
复制代码
既然能控制大小和位置,确定也能获取一些自身信息:
let width=ctx.measureText(str).width; //获取文本宽度
复制代码
这样,咱们就能作一些有意义的事,好比文本X/Y坐标是多少时设置Align才能让水平居中、好比根据一个元素的width(文字字数)控制另外一个元素的位置。。。这些都在末尾demo中有用到。
很遗憾的是,canvas并不支持获取文本的“高度”
canvas做为一个“特殊的结构”,其图片的展现方式确定也不一样寻常:
//加载图片对象
let img=new Image();
//设置src属性
img.src="xxx.xx";
//展现
ctx.drawImage(img,0,0); //ctx.drawImage(img对象,左上角X坐标,左上角Y坐标);
复制代码
而后咱们“自信满满地”打开图片,发现...没有东西!!!
这是由于Image()的加载须要必定时间,而咱们直接插入了src:切记!必定要在load中完成img的“展现”。(和H5的File()加载展现同样的道理)
img.onload=function(){
ctx.drawImage(img,0,0);
}
复制代码
这样完成是完成了,但图片样式是固定的,很差看啊。 不要紧,咱们有“第二种展现方法”,能够将其进行缩放:
ctx.drawImage(img对象,左上角X坐标,左上角Y坐标,宽,高);
复制代码
而后咱们又发现缩放后图片中图标是挺好看的,但文字太模糊了,难受的一批,因而咱们想:怎么把图标单独显示出来呢? 不要紧,咱们还有“第三种展现方法”:
ctx.drawImage(img对象,截取起点X坐标,截取起点Y坐标,截取终点X坐标,截取终点Y坐标,绘制位置X坐标,绘制位置Y坐标,宽,高);
复制代码
其实“图片”的展现还有一种方式 —— 图形画刷 ,它能够将图片为背景填充展现到canvas区域:
var pattern=ctx.createPattern(img对象,"模式");
ctx.fillStyle=pattern;
复制代码
其中,“模式”和CSS中【背景图片】的展现也很相似:
ctx.shadowOffsetX=数字值;
(数字值相对于图形)ctx.shadowOffsetY=数字值;
(数字值相对与图形)ctx.shadowColor='颜色值如:rgba(0,0,0,0.2)';
ctx.shadowBlur=数字值;
阴影会做用于其下全部设置的canvas上(文本、图形、图片...)
这个在大加载量、频繁JS动画 and DOM重绘量巨大的场景下应用极广。它基于这样的原理:把涉及大量DOM重绘、频繁加载的元素(好比小球运动场景下的背景格的样式改变)单独拿出来放在某位置地方(display:none;
)本身加载,在触发操做后,经过:
真实canvas元素上下文对象.drawImage(离屏canvas元素, 起始位置X, 起始位置Y, 真实canvas元素宽, 真实canvas元素高,起始位置X, 起始位置Y, 离屏canvas元素宽,离屏canvas元素高);
复制代码
将元素的“样子”刻画到主要显示的canvas上!
要记得“适当地”擦干画布:
canvas元素上下文对象.clearRect()
代码较多,已打包到百度网盘,可直接免费下载:
连接 | 提取码 |
---|---|
pan.baidu.com/s/1EIJp0MNA… | xqwk |
本文首发于@csdn:yunxiaomeng.blog.csdn.net/article/det…