html5学习canvas

来源:互联网 发布:leetcode面试题js 编辑:程序博客网 时间:2024/06/05 10:32

在html5中新增了一个标签元素叫做canvas,顾名思义,canvas就是一个画布,我们可以通过canvas来在页面中绘制我们想要的元素,以及添加一些动画效果。

创建canvas

我们可以通过两种方式来创建一个canvas对象,分别使用html标签,和javascript来创建一个canvas对象。
使用html来创建canvas对象

<canvas id="canvas"></canvas>

使用javascript引入canvas

//首先获取canvas对象var canvas = document.getElementById("canvas");//获得绘制2d图形的上下文环境var context = canvas.getContext("2d");

绘制简单图形

绘制直线

这里我们先绘制一条直线。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>canvas</title>    <style type="text/css">        canvas{            margin: 0 auto;            display: block;            border: 1px #ff9875 solid;        }    </style>    <script type="text/javascript">        window.onload = function(e) {            //得到canvas对象            var canvas = document.getElementById("canvas");            //设置当前canvas的宽和高            canvas.width = 600;            canvas.height = 600;            //获取用于绘制2d图形的上下文            var context = canvas.getContext("2d");            //描述具体的绘制路径            context.moveTo(100,100);//首先将画笔移动到100,100这个点,该点是相对于当前canvas对象的,即0,0点是当前canvas的左上角            //从上一个点描述一条直线到500,500改点            context.lineTo(500,500);            //真正的绘制            context.stroke();        }    </script></head><body>    <canvas id="canvas"></canvas></body></html>

效果如下:
这里写图片描述

为画笔设置样式

//设置当前画笔的宽度context.lineWidth = 10;//设置当前画笔的样式,这里为颜色context.strokeStyle = '#ff0000'

可以看到,这里我们设置属性都是通过context上下文环境来设置的,此时效果如下:
这里写图片描述

画三角形

//得到canvas对象var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");//获取用于绘制2d图形的上下文context.moveTo(150,75);context.lineTo(225,225);context.lineTo(75,225);context.lineTo(150,75);//真正的绘制context.stroke();

此时效果如下:
这里写图片描述

beginPath改变画笔颜色

这里我已经绘制了一个三角形了,那么如果还需要在底部绘制一条直线,并且为该直线设置不同的颜色,应该怎么做呢??看下如下代码:

//得到canvas对象var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.lineWidth = 10;//所有的线条宽度都是10,所以设置一次即可//beginPath表示将要进行一段全新的路径绘制context.beginPath();            context.moveTo(150,75);context.lineTo(225,225);context.lineTo(75,225);context.lineTo(150,75);context.strokeStyle = "red";context.stroke();context.beginPath();context.moveTo(20,280);context.lineTo(280,280);context.strokeStyle = "green";context.stroke();

PS:这里在每次更换画笔属性,之前都必须调用context.beginPath()方法,新设置的属性才会生效。 此时效果如下:
这里写图片描述
但是这里有一个问题,就是由于三角形是封闭的图像,在结束的时候由于我们当前的宽度是10,所以会有5px的空隙流出来,解决该问题,只需要在描述需要绘制的所有的点,之后添加一个context.closePath()方法即可。

context.beginPath();context.moveTo(150,75);context.lineTo(225,225);context.lineTo(75,225);context.lineTo(150,75);context.closePath()context.strokeStyle = "red";context.stroke();

此时效果如下:
这里写图片描述

为多边形设置填充

另外context中还有如下属性,可以用来设置多边形的填充颜色:
fillStyle :设置需要填充的颜色
fill() :填充
同样是上面的三角形:

context.beginPath();context.moveTo(150,75);context.lineTo(225,225);context.lineTo(75,225);context.closePath()context.strokeStyle = "red";context.fillStyle= "#876508"; //设置多边形填充颜色context.fill(); //填充context.stroke();

此时效果如下:
这里写图片描述

canvas常用API

绘制矩形

canvas为我们提供了如下方法,用来绘制矩形:
rect(x,y,widht,height) //绘制一个矩形的边
fillRect(x,y,widht,height) //绘制一个实心的具有fillstyle的矩形
strokeRect(x,y,widht,height) //绘制一个空心,具有strokeStyle的矩形

使用rect绘制矩形

//得到canvas对象var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");//起点是20,20 宽度和高度都是260context.rect(20,20,260,260); context.stroke();

效果如下:
这里写图片描述

使用fillRect绘制矩形

//得到canvas对象var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.fillStyle = "#ab8975";//直接使用fillRect方法绘制实心矩形context.fillRect(20,20,260,260); 

效果如下:
这里写图片描述

使用strokeRect绘制矩形

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.strokeStyle = "#ff0080";context.strokeRect(20,20,260,260); 

效果如下:
这里写图片描述

lineCap属性

首先看下常用的线条属性lineCap,该属性用来设置线条两端的形状,有如下三个值:
butt: 默认值
round :两端为圆形
square :两端为方形
这里我写了一段代码来区分这三个属性的不同之处:

//得到canvas对象var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");//首先画两条竖线,用来方便观察不同的lineCap属性的区别context.moveTo(50,0);context.lineTo(50,300);context.moveTo(250,0);context.lineTo(250,300);context.stroke();context.lineWidth = 40;//为所有的线条设置相同的宽度context.strokeStyle = "#ab0249"; //为所有的线条设置填充颜色//默认的lineCap buttcontext.beginPath();context.moveTo(50,60);context.lineTo(250,60);context.stroke();//lineCap设置为roundcontext.beginPath();context.moveTo(50,140);context.lineTo(250,140);context.lineCap = "round";context.stroke();//lineCap设置为squarecontext.beginPath();context.moveTo(50,220);context.lineTo(250,220);context.lineCap = "square";context.stroke();

此时效果如下:
这里写图片描述

canvas图形变换

translate平移

这里我写了一个简单的demo来展示平移的效果:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.lineWidth = 5;context.beginPath();context.fillStyle = "#aaa"; //context.translate(50,50); //表示将当前图形的左上角x和y轴分别平移50pxcontext.fillRect(0,0,100,100);

可以看到,添加translate方法之后对比的效果如下:
这里写图片描述

translate的叠加效果

此时我再在当前画布上绘制一个红色的实心矩形,并且将其x和y轴分别平移100,100的像素。

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.lineWidth = 5;context.beginPath();context.fillStyle = "#aaa"; context.translate(50,50); //表示将当前图形的左上角x和y轴分别平移50pxcontext.fillRect(0,0,100,100);context.beginPath();context.fillStyle = "#ff0000";//此时该rect的xy轴,实际上移动了150px,这就说明了translate的叠加效果 context.translate(100,100); context.fillRect(0,0,100,100);

效果如下:
这里写图片描述
可以看到translate平移默认是有叠加效果的,即后边的移动,会将前面的所有移动叠加,然后再次进行平移。

解决translate的叠加效果

使用translate(-x,-y)

为了防止这样的事情发生,我们可以在每次移动translate(x,y)指定距离之后,在使用translate(-x,-y)平移回到初始位置,这样,后边的平移就不会受到影响了。

context.beginPath();context.fillStyle = "#aaa"; context.translate(50,50); //表示将当前图形的左上角x和y轴分别平移50pxcontext.fillRect(0,0,100,100);context.translate(-50,-50); context.beginPath();context.fillStyle = "#ff0000";context.translate(100,100); context.fillRect(0,0,100,100);context.translate(-100,-100); 

此时效果如下:
这里写图片描述

使用save()和restore()

我们可以在每次绘制之前,先使用save()方法保存之前的图形,然后在绘制完成之后,在调用restore方法恢复到保存之前的图形。

context.save();context.beginPath();context.fillStyle = "#aaa"; context.translate(50,50); //表示将当前图形的左上角x和y轴分别平移50pxcontext.fillRect(0,0,100,100);context.restore();context.save();context.beginPath();context.fillStyle = "#ff0000";context.translate(100,100); context.fillRect(0,0,100,100);context.restore();

可以看到,在save和restore方法中间,可以随意的更改canvas的绘制,都不会影响到后边的绘制。

scale方大缩小

这里我绘制了三个正方形,来演示rotate方法:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 400;canvas.height = 400;var context = canvas.getContext("2d");context.lineWidth = 5;context.save();context.beginPath();context.scale(1,1); context.strokeRect(50,50,50,50);context.restore();context.save();context.beginPath();context.scale(2,2); //表示将x和y同时放大2倍context.strokeRect(50,50,50,50);context.restore();context.save();context.beginPath();context.scale(3,3); //表示将x和y同时放大3倍context.strokeRect(50,50,50,50);context.restore();

此时效果如下:
这里写图片描述
奇怪:可以看到,左上角的偏移量也跟着放大了,而且边框也跟着放大了。

渐变

线性渐变

渐变可以填充在矩形, 圆形, 线条, 文本等等, 各种形状可以自己定义不同的颜色。创建一个线性渐变:

createLinearGradient(x,y,x1,y1) 

当我们使用渐变对象,必须使用两种或两种以上的停止颜色。
addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是0至1.

线性渐变demo

这里我创建一个简单的从白色到黑色的渐变:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");var linear = context.createLinearGradient(0,0,300,300);linear.addColorStop(0.0,'#fff');linear.addColorStop(1.0,'#000');context.fillStyle = linear;context.fillRect(0,0,300,300);

可以看到,这里我的渐变是和canvas的大小相同的,此时效果如下:
这里写图片描述

添加多个addColorStop

另外,在上面的demo中,我们也可以添加多个colorStop,来设定不同时候渐变的颜色。

linear.addColorStop(0.0,'#fff');linear.addColorStop(0.35,'#ff0');linear.addColorStop(0.7,'#0ff');linear.addColorStop(1.0,'#000');

此时效果入下:
这里写图片描述

设置渐变方向

同时我们还可以设置渐变的方向:

//表示水平渐变,从0,0渐变到300,0var linear = context.createLinearGradient(0,0,300,0);

这里写图片描述

//表示竖直渐变,从0,0渐变到0,300var linear = context.createLinearGradient(0,0,0,300);

这里写图片描述

径向渐变

径向渐变是以一个同心圆为中心进行的渐变,创建径向渐变:

createRadialGradient(x,y,r,x1,y1,r1) //创建一个径向/圆渐变

其中x,y,r表示第一个圆的圆心和半径
x1,y1,r1表示第二个圆的圆心和半径
径向渐变的效果就发生在这两个圆之间。

径向渐变demo

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");var radial = context.createRadialGradient(150,150,0,150,150,100);radial.addColorStop(0.0,'#fff');radial.addColorStop(0.35,'#ff0');radial.addColorStop(0.7,'#0ff');radial.addColorStop(1.0,'#000');context.fillStyle = radial;context.fillRect(0,0,300,300);

可以看到我在createRadialGradient指定渐变是从当前canvas的中心到半径为100的圆之间发生渐变的。效果如下:
这里写图片描述

使用createPattern绘制图片

同样,我们可以使用createPattern来绘制图片到canvas中。创建createPattern如下:

createPattern(canvas,repeat-style)//canvas 这里表示需要绘制的图片//repeat-style 表示重复的样式,取值和css中的background是一样的

createPattern简单demo

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");var backImage = new Image();backImage.src = "car.jpg";backImage.onload = function() {    var pattern = context.createPattern(backImage,"no-repeat");    context.fillStyle = pattern;    context.fillRect(0,0,300,300);}

这里我们new了一个image,并且在该image被加载进dom中时候,执行
context.fillStyle = pattern;
context.fillRect(0,0,300,300);
这样的填充和绘画代码,效果如下:
这里写图片描述

绘制曲线

使用arc函数绘制圆形

先看下arc函数的定义:

arc(x,y,r,start,stop,anticlockwise)

x,y表示绘制圆弧的中心
r 表示绘制圆弧的半径
start ,stop 表示绘制圆弧的起始和结束角度
anticlockwise 表示是否逆时针绘制
绘制圆形代码:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.beginPath();context.lineWidth = 5;context.arc(150,150,100,0,2 * Math.PI,false);context.strokeStyle = "#ec7654";context.fillStyle= "#092376"; //设置多边形填充颜色context.fill(); //填充context.stroke();

可以看到,这里我选取当前canvas的中心点作为圆心,100位半径,从0到2pi,效果如下:
这里写图片描述

绘制文本

canvas同时为我们提供了绘制文本的方法:

  • font字体设置
  • fillText(text,x,y) - 在 canvas 上绘制实心的文本
  • strokeText(text,x,y) - 在 canvas 上绘制空心的文本
    这里text表示需要绘制的文本,x,y表示绘制文本的左上角坐标。
var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.font = "30px Arial"; //设置字体类型和大小//context.fillStyle = "#ef9087"; //设置字体填充色context.fillText("hello canvas",50,100); //绘制字体

这里写图片描述

阴影的绘制

canvas中并没有提供绘制阴影的方法,而是给我们提供了下面几个属性,当我们为context(绘制的上下文)设置了这样的属性以后就会有阴影效果了。

  • context.shadowColor //阴影的颜色
  • context.shadowOffsetX //x方向阴影的偏移量
  • context.shadowOffsetY //y方向阴影的偏移量
  • context.shadowBlur //阴影的模糊程度,值越大,越模糊

    这里,我写了一个简单的带阴影的矩形:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.shadowColor = "#ff9087";context.shadowOffsetX = 10;context.shadowOffsetY = 10;context.shadowBlur = 20;context.fillStyle = "red";context.fillRect(100,100,100,100);

这里写图片描述

globalAlpha属性

globalAlpha用来设置当前整个画布的透明度,之前我们绘制的所有的图形的透明度都是globalAlpha的默认值1,也就是不透明。为了展示globalAlpha属性的作用,这里我先随机绘制很多圆。

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 600;canvas.height = 600;var context = canvas.getContext("2d");var R;var G;var B;for (var i = 0; i < 80; i++) {    R = Math.floor(Math.random()*255);    G = Math.floor(Math.random()*255);    B = Math.floor(Math.random()*255);    context.fillStyle = "rgb("+R+","+G+","+B+")";    context.beginPath();    context.arc(Math.random()*canvas.width,Math.random()*canvas.height,Math.random()*80,0,2 * Math.PI,false);    context.fill();};

可以看到这类绘制的所有的圆的:圆心,半径,以及填充色都是随机生成的,此时效果如下:
这里写图片描述
此时是没有透明度的,后绘制的圆会将先绘制的遮盖住,此时只需要为context增加globalAlpha属性,并设置相应的透明度值即可。

context.globalAlpha = 0.7;

此时效果如下:
这里写图片描述

globalCompositeOperation属性

globalCompositeOperation属性,表示绘制的图形在重叠时候的显示方式。默认值如下:
globalCompositeOperation = “source-over”
这里,source表示后绘制的图形,source-over表示后绘制的遮挡住先绘制的图形。
该属性有如下一些值可以设置:
这里写图片描述
举个例子:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.globalCompositeOperation = "source-over";context.beginPath();context.fillStyle = "#fe9876";context.fillRect(50,100,200,100);context.beginPath();context.fillStyle = "#f58798";context.arc(150,150,70,0,2 * Math.PI,false);context.fill();

效果如下:
这里写图片描述
可以看到这里设置globalCompositeOperation 属性为默认值,也就是后绘制的圆会遮盖住先绘制的矩形重叠的部分。

其他属性值的效果如下:
这里写图片描述
具体可以参考http://www.w3school.com.cn/tags/canvas_globalcompositeoperation.asp

clip()方法

clip()方法的功能是在当前的canvas中剪切出来一块区域,后边的绘制都是在该区域内进行的,而不是默认的整个canvas。举个栗子:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;var context = canvas.getContext("2d");context.beginPath();context.fillStyle = "#000";context.fillRect(0,0,300,300);context.beginPath();context.fillStyle = "#fff";context.arc(150,150,80,0,2 * Math.PI,false);context.fill();//剪切出当前圆的区域,后边的绘制都在改区域内进行,超出部分不显示context.clip();context.font = "40px Arial";context.fillStyle = "#ef9087";context.textAlign = "center"; //水平居中context.textBaseline = "middle"; //竖直居中context.fillText("hello world",canvas.width/2,canvas.height/2);

此时效果如下:
这里写图片描述

获取鼠标点击位置相对canvas

我们可以获取鼠标的点击位置相对于canvas的位置,通过如下代码获得:

var canvas = document.getElementById("canvas");//设置当前canvas的宽和高canvas.width = 300;canvas.height = 300;canvas .addEventListener('click', function(e){    var x = event.clientX - canvas.getBoundingClientRect().left;    var y = event.clientY - canvas.getBoundingClientRect().top;    alert(x + "  === " +y)}, false);

ok,今天关于html5的canvas学习就到这里了,希望大家喜欢。
源码下载

1 0
原创粉丝点击