HTML5之Canvas

Canvas API

  • 在网页上使用cnavas元素时,会创建一块矩形区域,默认大小是300*150px
  • 坐标从左上角开始的,x轴沿着水平方向向右延伸,y轴垂直方向向下延伸
  • 检测浏览器对canvas的支持情况:
    <!DOCTYPE html>
    

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas API</title>
</head>
<body>
<div id="support"></div>
</body>
<script>
try{
document.createElement("canvas").getContext("2d");
document.getElementById("support").innerHTML="HTML5 Canvas is supported in you browser.";
}catch (e){
document.getElementById("support").innerHTML="HTML5 Canvas is not supported in you browser.";
}
</script>
</html>

* 绘制简单的对角线:(对上下文的操作不会立即反应在页面上,只有对路径应用绘制(stroke)或填充(fill)方法时,结果才会显示出来)
以直接绘制的方式来绘制
```html
 <!DOCTYPE html>
 <html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Canvas API</title>
</head>
<body>
  <canvas id="diagonal" style="border: 1px solid;" height="200" width="200"></canvas>
</body>
<script>
  function drawDiagonal() {
      //取得canvas元素及其绘图上下文
      var canvas = document.getElementById('diagonal');
      var context = canvas.getContext('2d');

      //用绝对坐标来创建一条路径
      context.beginPath();
      context.moveTo(70,140);
      context.lineTo(140,70);

      //将这条线绘制到canvas上
      context.stroke();
  }

  window.addEventListener("load",drawDiagonal,true);
</script>
</html>

以转换的方法进行绘制(translate() 方法重新映射画布上的 (0,0) 位置。)

//保存你当前绘图状态
     context.save();

     //向右下方移动绘图上下文
     context.translate(70,140);

     //以原点为起点,绘制与前面相同的线段
     context.beginPath();
     context.moveTo(0,0);
     context.lineTo(70,-70);
     context.stroke();

     //恢复原有的绘图状态
     context.restore();
  • 下面以绘制带树的跑道为例,写一段完成的程序
  1. html部分代码
<canvas id="trails" style="border: 1px solid;" height="500" width="400"></canvas>
  1. JS部分代码
 //加载砾石背景图片
    var gravel = new Image();
    gravel.src = "gravel.jpg";
    gravel.onload = function () {
        drawTrails();
    };

    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 drawTree(context) {
        //给树创建树影
        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();

        //恢复之前的canvas状态
        context.restore();
        createCanopyPath(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);

        //投影渐变的起点是透明度设为50%的黑色
        canopyShadow.addColorStop(0.2, '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);

        //加宽线条
        context.lineWidth = 4;

        //平滑路径的接合点 round/bevel/miter
        context.lineJoin = 'round';

        //将颜色改为棕色
        context.strokeStyle = '#663300';
        context.stroke();

        //将填充色设置为绿色并填充树冠(填充是在绘图之前进行的,所以不会覆盖线条宽度,如果在绘图之后填充,就会覆盖线条宽度)
        context.fillStyle = "#339900";
        context.fill();
    }

    function createCurvePath(context) {

        //保存canvas的状态并绘制路径
        context.save();

        context.translate(-10, 350);
        context.beginPath();

        //第一条曲线向右上方弯曲(第一组xy坐标是曲线的控制点,第二组xy坐标是曲线的终点)
        context.moveTo(0, 0);
        context.quadraticCurveTo(170, -50, 260, -190);

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

        //用背景图替代棕色粗线条
        context.strokeStyle = context.createPattern(gravel, 'repeat');

        //使用棕色的粗线条来绘制路径
//        context.strokeStyle='#663300';
        context.lineWidth = 20;
        context.stroke();

        //恢复之前的canvas状态
        context.restore();
    }

    function drawTrails() {
        var canvas = document.getElementById('trails');
        var context = canvas.getContext('2d');
        //在(130,250)的位置绘制第一颗树
        context.save();
        context.translate(130, 250);
        drawTree(context);
        //绘制当前路径
//        context.stroke();
        context.restore();

        //在(260,500)的位置绘制第二颗树
        context.save();
        context.translate(260, 500);

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

        //绘制小路
        createCurvePath(context);

        //在canvas上绘制标题文本
        context.save();

        //字号为60px,字体为impact
        context.font = "60px impact";

        //将文本填充为棕色
        context.fillStyle = '#996600';
        //将文本设置为居中对齐
        context.textAlign = 'center';
        //设置文字阴影的颜色为黑色,透明度为20%
        context.shadowColor = 'rgba(0,0,0,0.2)';

        //将阴影向右移动15px,向上移动10px
        context.shadowOffsetX = 15;
        context.shadowOffsetY = -10;

        //轻微模糊阴影
        context.shadowBlur = 2;

        //在canvas顶部中央的位置以大字体的形式显示文本
        context.fillText('Happy Trails!', 200, 60, 400);
        context.restore();
    }
  1. 附示例程序中用到的图片


    gravel.jpg

程序技术点分解:

  • 树冠的绘制是通过moveTo lineTo的方法,在原点进行绘制,然后用translate方法移动位置
    样式的修改:lineWidth(线宽) lineJoin(连接点的平滑度) strokeStyle(颜色) lineCap(线条末端)
  • 曲线的绘制用quadraticCurveTo方法,第一组参数是弯曲点,第二组参数是终点
  • 渐变的制作分三步:1、创建渐变对象 trunkGradient
    2、为渐对象设置颜色,指明过渡方式 addColorStop
    3、在context上为填充样式或描边样式设置渐变 fillStyle
    4、rgba(R,G,B,A),最后一个是Alph通道透明度
  • 背景图的添加用 createPattern(img,'repeat/repeat-x/repear-y/no-repeat')
  • 缩放 scale
  • 制作阴影 transfom(a,b,c,d,e,f) 要了解矩阵的概念
  • Canvas文本 fillText strokeText
  • 应用阴影:shadowColor(颜色) shadowOffsetX(向右阴影像素值) shadowOffsetY(向下阴影像素值) shadowBlur(模糊值)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容