首页 > 技术文章 > HTML5 Canvas学习

jsStudyjj 2015-12-05 22:49 原文

一.SVG(Scalable Vector Graphics,可伸缩矢量图形)Canvas对比

 

1.Canvas本质上是一个位图画布,其上绘制的图形是不可缩放的,不能像SVG那样可以被放大缩小。

 

2.用Canvas绘制出的对象不属于页面DOM结构或者任何命名空间——这点被认为是一个缺陷。SVG图像却可以在不同的分辨率下流畅的缩放,并且支持单击检测(能检测到鼠标点击了图像上的哪个点)。

 

虽然Canvas有这些不足,但是Canvas API有两方面的优势可以弥补:首先,不需要将所绘制图像中的每个图元当做对象存储,因此执行性能非常好。

 

其次,在其他编程语言现有的优秀二维绘制API的基础上实现Canvas API相对来说比较简单。毕竟,二鸟在林不如一鸟在手。

 

二.Canvas概述

 

1.canvas是什么

 

<canvas></canvas>

 

默认创建一块矩形区域,宽300,高150像素,可设置border style使其可见。

 

使用canvas编程,首先要获取其上下文(context.然后在上下文中执行动作,最后将这些动作应用到上下文中。

 

2.Canvas坐标

 

Canvas坐标从左上角开始,x轴水平右延伸,y轴垂直下延伸。左上角坐标为x=0,y=0,称作原点。

 

3.浏览器支持

 

检测浏览器支持代码:

 

try{

document.createElement(“canvas”).getContext(“2d”);

document.getElementById(“support”).innerHTML=

“HTML5 Canvas is supported in your browser.”;

}catch(e){

document.getElementById(“support”).innerHTML=

“HTML5 Canvas is not supported in your browser.”;

}

 

 

不支持时替代内容写法:

 

<canvas>

Update your browser to enjoy canvas!

</canvas>

 

 

4.在页面中加入canvas

 

1.画直线

 

html

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title>canvas</title>

    <script  type="text/javascript" src="../js/canvas/canvas1.js"></script>

</head>

<body>

<canvas id="diagonal" width="200" height="200" style="border:1px solid;">

    update your browser to support canvas

</canvas>

</body>

</html>

 

 

Js:

 

window.addEventListener("load",drawcans,true);

 

function drawcans() {

    var canvs = document.getElementById("diagonal");

    var context = canvs.getContext("2d");

    context.beginPath();

    context.moveTo(70, 140);

    context.lineTo(140, 70);

    context.stroke();

}

 

 

2.变换

 

平移,缩放,旋转等

 

下面的js代码使用translate函数实现上面同样的对角线

 

function drawDiagonal(){

  var canvas = document.getElementById("diagonal");

    var context = canvas.getContext("2d");

    context.save() ;

    context.translate(70,140);

    context.beginPath();

    context.moveTo(0,0) ;

    context.lineTo(70,-70);

    context.stroke() ;

    context.restore();

} 

 

 

3.路径

 

  •  moveTo(x,y):不绘制,只是将当前位置移动到新的目标坐标(x,y)

 

  • lineTo(x,y):不仅将当前位置移动到新坐标(x,y,而且在两个坐标之间画一条直线。

 

简而言之,上面两个函数的区别在于,moveTo就像是提起画笔,移动到新位置,而lineTo告诉canvas用画笔从纸上的旧坐标画条直线到新坐标。不过,提醒大家,不管调用那个,都不会真正画出图形,因为还没有调用stroke或者fill函数。目前只是在定义路径的位置,以便后面绘制时使用。

 

closePath会将起始坐标自动作为目标坐标,和lineTo很像。还会通知canvas当前的图形已经闭合或者形成了完全封闭的区域,这对将来填充和描边非常有用。

 

   

context.beginPath();

    context.moveTo(-25,-50);

    context.lineTo(-10,-80);

    context.lineTo(-20,-80);

    context.lineTo(-5,-110);

    context.lineTo(-15,-110);

 

    context.lineTo(0,-140);

 

    context.lineTo(15,-110);

    context.lineTo(5,-110);

    context.lineTo(20,-80);

    context.lineTo(10,-80);

    context.lineTo(25,-50);

    context.closePath() ;

 

 

以上js代码可以绘制出一个松树的树冠。

 

4.描边样式

 

//设置使用描边样式

//加宽线条

context.lineWidth=4;

//平滑路径接合点

context.lineJoin = 'round';

//将颜色改成棕色

context.strokeStyle='#663300';

//最后绘制树冠

 context.stroke();

 

 

5.填充样式

 

  

 //填充树颜色为绿色

    context.fillStyle="#339900";

   context.fill();

 

 

 

 

6.填充矩形区域

 

//将填充色设为棕色

  context.fillStyle=’#663300’;

//填充用作树干的矩形区域

   context.fillRect(-5,-50,10,50);

 

 

7.绘制曲线

 

 

 

 

   context.save();

    context.translate(-10,350);

    context.beginPath();

    //第一条曲线向右上方弯曲

    context.moveTo(0,0);

    context.quadraticCurveTo(170,-50,260,-190);

 

    //第二条曲线向右下方弯曲

    context.quadraticCurveTo(310,-250,410,-250);

 

    //使用棕色的粗线条来挥之路径

    context.strokeStyle="#663300";

    context.lineWidth=20;

    context.stroke();

    context.restore();

 

 

 

 

8.在canvas中插入图片

 

//保证图片加载完才调用

var Bark = new Image();

Bark.src=”bark.jpg”;

Bark.onload = function(){

drawTrails();

}

 

 

 

 

canvas中显示图像

 

context.drawImage(Bark,-5,-50,10,50);

 

 

9.渐变

 

步骤:

 

① 创建渐变对象

 

② 为渐变对象设置颜色,指明过度方式

 

③ 在context上为填充样式或者描边样式设置渐变

 

  

 var trunkGradient = context.createLinearGradient(-5,-50,5,-50);

    trunkGradient.addColorStop(0,'#663300');

    trunkGradient.addColorStop(0.4,'#996600');

    trunkGradient.addColorStop(1,'#552200');

    context.fillStyle=trunkGradient;

    context.fillRect(-5,-50,10,50);

    //接下来,创建垂直渐变,以用作树冠在树干上的投影

    var canopyShadow = context.createLinearGradient(0,-50,0,0);

    canopyShadow.addColorStop(0,'rgba(0,0,0,0.5)');

    //方向垂直向下,渐变色在很短的距离内迅速渐变为完全透明,这段长度之外的树干上没有投影

    canopyShadow.addColorStop(0.2,'rgba(0,0,0,0.0)');

 

    //在树干上填充投影渐变

    context.fillStyle=canopyShadow;

    context.fillRect(-5,-50,10,50);

 

 

10.背景图

 

使用createPattern函数替代之前的drawImage函数

 

var Bark = new Image();

Bark.src=”bark.jpg”;

Bark.onload = function(){

drawTrails();

}

//用背景图替代棕色的粗线条

context.strokeStyle = context.createPattern(Bark,’repeat’);

context.lineWidth=20;

Context.stroke();

 

 

11.缩放canvas对象

 

 

 //在(130,250)的位置绘制第一棵树

    context.save();

    context.translate(130,250);

    drawTree(context);

    context.restore();

 

    //在(260,500)的位置绘制第二棵树

    context.save();

    context.translate(260,500);

 

    //将第二棵树的宽高分别放大至原来的2倍

    context.scale(2,2);

    drawTree(context);

    context.restore();

 

 

12.Canvas变换

 

   

    context.save();

    //X值随着Y值的增加而增加,借助拉伸变换,可以创建一颗用作阴影的倾斜的数,应用了变换以后,所有坐标都与矩阵相乘

    context.transform(1,0,-0.5,1,0,0);

    //在Y轴方向,将阴影的高度压缩为原来的60%

    context.scale(1,0.6);

    //使用透明度为20%的黑色填充树干

    context.fillStyle='rgba(0,0,0,0.2)';

    context.fillRect(-5,-50,10,50);

    //使用已有的阴影效果重新绘制树

    createCanopyPath(context);

    context.fill();

    context.restore();

 

 

 

 

运用上面的所有变换后的图形:

 

 

 

 

 

13.canvas文本

 

Context对象的文本绘制功能由两个函数组成:

 

  •  fillText(text,x,y,maxwidth);

 

  • strokeText(text,x,y,maxwidth);

 

Maxwidth是可选的,用于限制字体的大小,它将文字强制收缩到指定尺寸。

 

 

 

 

 

//在canvas上绘制标题文本

    context.save();

    context.font='60px impact';

    //将文本填充为棕色

    context.fillStyle='#996600';

    //将文本设为居中对齐

    context.textAlign='center';

    //在canvas顶部中央的位置以大字体的样式显示文本

    context.fillText('Merry  Christmas!',200,60,400);

    context.restore();

 

 

最后显示如下,是不是很欢快的感觉,绘制的还是很不错的。

 

 

 

14.应用阴影

 

 

 

 

  //设置文字阴影的颜色为黑色,透明度为20%

    context.shadowColor ='rgba(0,0,0,0.2)';

    //将阴影向右移动15px,向上移动10px

    context.shadowOffsetX=15;

    context.shadowOffsetY = -10;

    //轻微模糊阴影

    context.shadowBlur=2;

 

 

 

最终效果图:

 

三.完整代码

JS:

 

 window.addEventListener("load",drawTrails,true);
//绘制松树树冠
function createCanopyPath(context){
    context.beginPath();
    context.moveTo(-25,-50);
    context.lineTo(-10,-80);
    context.lineTo(-20,-80);
    context.lineTo(-5,-110);
    context.lineTo(-15,-110);

    context.lineTo(0,-140);

    context.lineTo(15,-110);
    context.lineTo(5,-110);
    context.lineTo(20,-80);
    context.lineTo(10,-80);
    context.lineTo(25,-50);
    context.closePath() ;

}
function drawTrails(){
    var canvas = document.getElementById("diagonal");
    var context = canvas.getContext("2d");
    //在(130,250)的位置绘制第一棵树
    context.save();
    context.translate(130,250);
    drawTree(context);
    context.restore();

    context.save();
    context.translate(-10,350);
    context.beginPath();
    //第一条曲线向右上方弯曲
    context.moveTo(0,0);
    context.quadraticCurveTo(170,-50,260,-190);

    //第二条曲线向右下方弯曲
    context.quadraticCurveTo(310,-250,410,-250);

    //使用棕色的粗线条来挥之路径
    context.strokeStyle="#663300";
    context.lineWidth=20;
    context.stroke();
    context.restore();
    //在(260,500)的位置绘制第二棵树
    context.save();
    context.translate(260,500);

    //将第二棵树的宽高分别放大至原来的2倍
    context.scale(2,2);
    drawTree(context);
    context.restore();

    //在canvas上绘制标题文本
    context.save();
    context.font='60px impact';
    //将文本填充为棕色
    context.fillStyle='#996600';
    //将文本设为居中对齐
    context.textAlign='center';
    //在canvas顶部中央的位置以大字体的样式显示文本

    //设置文字阴影的颜色为黑色,透明度为20%
    context.shadowColor ='rgba(0,0,0,0.2)';
    //将阴影向右移动15px,向上移动10px
    context.shadowOffsetX=15;
    context.shadowOffsetY = -10;
    //轻微模糊阴影
    context.shadowBlur=2;
    context.fillText('Merry  Christmas!',200,60,400);
    context.restore();



}


function drawTree(context){
    context.save();
    var trunkGradient = context.createLinearGradient(-5,-50,5,-50);
    trunkGradient.addColorStop(0,'#663300');
    trunkGradient.addColorStop(0.4,'#996600');
    trunkGradient.addColorStop(1,'#552200');
    context.fillStyle=trunkGradient;
    context.fillRect(-5,-50,10,50);
    //接下来,创建垂直渐变,以用作树冠在树干上的投影
    var canopyShadow = context.createLinearGradient(0,-50,0,0);
    canopyShadow.addColorStop(0,'rgba(0,0,0,0.5)');
    //方向垂直向下,渐变色在很短的距离内迅速渐变为完全透明,这段长度之外的树干上没有投影
    canopyShadow.addColorStop(0.2,'rgba(0,0,0,0.0)');

    //在树干上填充投影渐变
    context.fillStyle=canopyShadow;
    context.fillRect(-5,-50,10,50);

    createCanopyPath(context);
    context.restore() ;


    context.save();
    //设置使用描边样式
    context.lineWidth=4;
    context.lineJoin = 'round';
    context.strokeStyle='#663300';
    context.stroke();
    //填充数颜色
    context.fillStyle="#339900";
    context.fill();
    context.restore();

    context.save();
    //X值随着Y值的增加而增加,借助拉伸变换,可以创建一颗用作阴影的倾斜的数,应用了变换以后,所有坐标都与矩阵相乘
    context.transform(1,0,-0.5,1,0,0);
    //在Y轴方向,将阴影的高度压缩为原来的60%
    context.scale(1,0.6);
    //使用透明度为20%的黑色填充树干
    context.fillStyle='rgba(0,0,0,0.2)';
    context.fillRect(-5,-50,10,50);
    //使用已有的阴影效果重新绘制树
    createCanopyPath(context);
    context.fill();
    context.restore();

}

HTML:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>canvas</title>
    <script  type="text/javascript" src="../js/canvas/canvas1.js"></script>
</head>
<body>
<canvas id="diagonal" width="410" height="510" style="border:1px solid;">
    update your browser to support canvas
</canvas>
</body>
</html>

 

推荐阅读