html5 canvas基础用法

canvas 是html5新增的一个比较强大的功能,简直是一个画图工具一样。


写这篇文章只是方便以后用的时候可以快速上手。


canvas的操作基本是用js来完成的,下面开始讲一些基本用法。


一.最基本的用法

要用画布,先要写出画布标签。

<canvas height="500" width="700" style="border:1px solid black" id="canvas">浏览器不支持canvas</canvas>

标签 包裹内容为当浏览器不支持canvas时显示的内容

这里要注意,定义canvas宽高时建议用标签的属性height、width。经测试,如果在style内设置width,height会使绘图环境(下面会讲什么是绘图环境)缩放,使得绘图环境不好控制。

要在canvas上画画,要用到js

<script>
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext("2d");
        //开始一个绘画路径
        ctx.beginPath();
        //描边颜色
        ctx.strokeStyle = "red";
        ctx.fillStyle = "blue";
        ctx.moveTo(20, 20);
        ctx.lineTo(50, 50);
        ctx.lineTo(40, 20);
        //连接回最初的起点
        ctx.closePath();
        //对路径进行描边
        ctx.stroke();
        ctx.fill();
</script>
 这里用getContext()来获得一个绘图环境。后面就是用这个绘图环境做各种绘图。 

beginPath()是标志开始一段新的路径绘画。strokeStyle是定义描线的颜色。fillStyle是定义填充的颜色。moveTo(x, y)是定义路径起点。lineTo(x, y)是画路径。这里之所说是画路径,而不是说画线,是因为lineTo(包括后面说到的rect,arc)只是程序定义了一个作图的路线,并没有在这条路线上做任何动作,所以上面的程序如果没有后面的stroke()或fill(),画布内是不会显示任何东西的。这里一定要理解好,不然后面你会凌乱的。

closePath()是闭合当前路径(并不是关闭),即把当前路径的终点和路径起点连接起来。然后就是上面说到的stroke(),stroke()是对当前的路径进行描边(即画线)。当前路径指的是从beginPath()开始,所以每画一个图形的开头,最好都加上beginPath(),这样可以防止第一个图形的路径终点连接到第二个图形的路径起点。

fill()是填充当前路径的闭合区域。

二.画基本图形

<script>
        //矩形
	ctx.beginPath();
        ctx.fillStyle = "red";
        //填充一个矩形(x, y, 宽, 高)
        //方法一:
        ctx.fillRect(20, 50, 100, 70);
        //方法二:
	ctx.rect(130, 50, 100, 70);
	ctx.fill();
</script>
上面的方法一跟方法二效果是一样的(只有矩形的坐标不同)。fillRect直接生产一个填充了的矩形,而rect是定义了一个矩形的路径,还没有画出来。

在实际应用中,建议先把图形的路径画好了,再去填充或描线。因为描边和填充会消耗大量资源,所以尽量把路径都弄好一次过描边或填充。

<script>
        //圆形
	ctx.beginPath();
        ctx.fillStyle = "red";
	//圆形(x,y,半径,起始角,结束角,绘图方向:true逆时针,false顺时针)
	ctx.arc(40,220,50,0,2*Math.PI,false);
	ctx.fill();
</script>
arc是一个画圆弧的方法,参数的介绍代码中已经有了。

<script>
        //椭圆形
	ctx.beginPath();
        ctx.save();
        ctx.scale(1, 0.5);
        ctx.fillStyle = "blue";
        ctx.arc(240,360,50,0,2*Math.PI,false);
	ctx.fill();
        ctx.restore();
</script> 

 没有直接画椭圆的方法,上面代码是通过把一个圆给压缩得到一个椭圆。 

save()是保存当前画面的各种状态包括画笔颜色、填充颜色、画面旋转角度、画面基点坐标、画面缩放等……。restore()则是恢复到save()保存的状态。代码中可以出现多个save(),restore()是把画面恢复到离它最近的一个save()的状态。

注意这里我说的是画面,而不是画布。画布即canvas标签,这里的画面指的是getContext("2d")对象,即上面说的绘图环境。

scale(x, y)是对画面进行缩放,后面再来介绍。

三.绘图环境的缩放、旋转、基点坐标改变。

1.改变基点(translate)

先说一下基点坐标。默认的基点坐标是(0, 0),即画布的左上角坐标。上面说到的rect()方法中的前两个参数x, y就是相对于基点坐标(0, 0)而言的。

<script>
        //改变基点坐标
        ctx.beginPath();
	ctx.save();
	ctx.rect(300,300,100,90);
	ctx.translate(20,20);
	ctx.rect(300,300,100,90);
	ctx.stroke();
        ctx.restore();
</script>
可以看到,上面两个rect()的参数是一样的,但是画出来的矩形却不在同一位置上。因为第二个矩形在定义路径之前,绘图环境的基点坐标被改变了,所以第二个rect的前两个参数是基于新的基点坐标来定位。

注意,这里是先改变基点坐标,再去画路径。包括后面的缩放和旋转都是要先改变,再画路径。

(从这里我猜测每次画路径,系统都会去读一次绘图环境的各种参数。这个我还没去研究。)

2.缩放(scale)

<script>
        //绘图环境缩放
        ctx.beginPath();
        ctx.save();
        ctx.strokeStyle = "green";
        ctx.strokeRect(20, 20, 25, 15);
        ctx.scale(2,2);
        ctx.strokeRect(20, 20, 25, 15);
        ctx.scale(2,2);
        ctx.strokeRect(20, 20, 25, 15);
        ctx.restore();
</script>
 
 
 
 
 
 

这是直接从W3C那边复制过来的代码。如果对绘图环境进行缩放,所有之后的操作也会被缩放。定位也会被缩放。

3.旋转(rotate)

<script>
        //旋转(基于基点来旋转)
        ctx.beginPath();
        ctx.save();
        ctx.strokeRect(20, 20, 170, 120);
	ctx.rotate(Math.PI/5);
        ctx.strokeRect(20, 20, 170, 120);
        ctx.restore();
</script>
就像代码中注释的,旋转是基于基点来旋转的。改变基点后旋转的效果是不同的。


四.填充渐变色

<script>
        //线性渐变(起点之前是起点色,终点之后是终点色)
	var linear = ctx.createLinearGradient(200,200,350,330);
	linear.addColorStop(0,"#fff");
	linear.addColorStop(0.5,"#f8f");
	linear.addColorStop(1,"#f0f");
	ctx.fillStyle = linear;
	ctx.fillRect(200,200,150,130);

	//径向渐变
	ctx.beginPath();
	var radial = ctx.createRadialGradient(200,480,10,200,450,50);
	radial.addColorStop(0,"#fff");
	radial.addColorStop(0.5,"#f8f");
	radial.addColorStop(1,"#f0f");
	ctx.fillStyle = radial;
	ctx.arc(200,450,50,0,Math.PI*2,0);
	ctx.fill();
</script>

渐变填充分线性渐变和径向渐变。

createLinearGradient(x1, y1, x2, y2)创建一个线性渐变对象,(x1, y1)和(x2, y2)连线部分就是渐变色区域。(这里很难表达清楚,看效果更容易理解)

addColorStop()是在区域中添加渐变色。第一个参数在0~1范围之间,表示在线段的哪个位置加渐变色。

设置好渐变对象后记得把渐变对象赋值给填充状态就好了。

createRadialGradient(x1, y1, r1, x2, y2, r2)创建径向渐变对象,所谓径向就像水上的涟漪,由圆心往外扩展。(x1, y1, r1)和(x2, y2, r2)分别表示两个圆,渐变色就是从第一个圆开始颜色渐变到第二个圆。

渐变色这部分很难解释清楚,多用一下就好理解了。


最后附上时钟代码

<html>
<canvas height="500" width="500" style="border:1px solid black;position:absolute;" id="clock_bg"></canvas>
<canvas height="500" width="500" style="border:1px solid black;position:absolute;" id="clock_point"></canvas>
<script>
	var ctx1 = document.getElementById("clock_bg").getContext("2d");
	var ctx2 = document.getElementById("clock_point").getContext("2d");

	//画钟背景
	function print_bg(){
		ctx1.save();
		ctx1.beginPath();
		ctx1.translate(200,200);
		ctx1.arc(0, 0, 2, 0, 2*Math.PI, 0);
		ctx1.fill();
		ctx1.beginPath();
		ctx1.arc(0, 0, 105, 0, 2*Math.PI, 0);
		var len = 0;
		for(var i=1;i<=60;i++)
		{
			ctx1.save();
			ctx1.rotate(2*Math.PI*i/60);
			if(i%5){
				len = 5;
			}else{
				len = 10;
				ctx1.fillText(i, -5, -110);
			}
			ctx1.moveTo(100, 0);
			ctx1.lineTo(100-len, 0);
			ctx1.restore();
		}
		ctx1.stroke();
		ctx1.restore();
	}
	
	//移动指针
	function move_point(){
		var n_date = new Date();
		var hour = n_date.getHours();
		var min = n_date.getMinutes();
		var sec = n_date.getSeconds();
		
		with(ctx2){
			clearRect(0,0,500,500);
			save();
			translate(200, 200);
			save();
			//时针
			beginPath();
			lineWidth = 3;
			rotate(2*Math.PI*hour/12);
			moveTo(0, 0);
			lineTo(0, -45);
			stroke();
			restore();
			save();
			//分针
			beginPath();
			lineWidth = 2;
			rotate(2*Math.PI*min/60);
			moveTo(0, 0);
			lineTo(0, -60);
			stroke();
			restore();
			save();
			//秒针
			beginPath();
			rotate(2*Math.PI*sec/60);
			moveTo(0, 0);
			lineTo(0, -70);
			stroke();
			restore();
			restore();
		}
	}
	print_bg();
	move_point();
	setInterval(function(){move_point()},1000);
</script>
</html>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值