zoukankan      html  css  js  c++  java
  • HTML5 Canvas

    HTML5 Canvas

    Canvas HTML 5中引入它,可以做很多事情:画图、动画、游戏开发等等。本篇就主要讲解一下Canvas的基本作图。

     内容摘要

    1Canvas 基础知识

    1.1 Canvas 元素

    Canvas 中文翻译为:画布。

    <canvas id=”yourCanvasId” width=”300” height=”150” />

    Canvas元素除了公用属性外,只有两个额外的属性:width, height,他们都是没有单位的,其实单位是px,但是不能写单位。如果不指定这两个属性,默认是width300height150

    众所周知,html元素的样式,都可以用css样式来指定。Canvas也不例外。

    <html>

    <head>

    <title>Canvas - 01</title>

    <style>

    body{

    background:#dddddd;

    }

    #canvas{

    margin:20px;

    padding:20px;

    background:#ffffff;

    border:thin inset #aaaaaa;

    600px;

    height:300px;

    }

    </style>

    </head>

    <body>

    <canvas id="canvas">

    Canvas not supported

    </canvas>

    <script type="text/javascript">

    var canvas = document.getElementById("canvas"),

    ctx = canvas.getContext("2d");

    ctx.font='38pt Arial';

    ctx.fillStyle='cornflowerblue';

    ctx.strokeStyle='blue';

    ctx.fillText("Hello Canvas", canvas.width/2 -150, canvas.height/2 + 15);

    ctx.strokeText("Hello Canvas stroke", canvas.width/2 -200, canvas.height/2 + 80);

    </script>

    </body>

    </html>

    我们期望的结果是这样的:

     

    而实际的执行结果:

     

    从执行结果看,它确实一个放大的hello,这是为什么呢?

    其实我认为可以这样理解它,它是一个放映布,因为真正的绘图不在它上的,而是在一个绘图板上,绘图完毕投影到放映布上。这一点,类似于我们中学时候用过的幻灯片放映机,在一张玻璃板(绘图板)上写上习题,然后投影到放映布或者白墙上(画布)。

    所以呢,这样一想,就明白了,当css样式中的width,height属性值与canvas元素的width,height的属性值不同时,会自动的将绘图板上的内容进行缩放到画布上。

    Canvas 元素目前有三个方法:

     

    通过getContext(“2d”);能够取得CanvasRenderingContext2D对象,然后就可以基于此上下文对象来作2d图了

    通过getContext(“3d”);就可以进行3d作图,3d作图底层用的是WebGL

    1.2 CanvasRenderingContext2D简介

    2、基本作图

    2.1、线条

    使用Canvas作图时,默认情况下是有这样一个坐标轴的:

     

    在使用canvas作图时,需要按照一定的顺序来编写代码。

    1)直线(Line

    要画一条线,代码编写过程一般是这样的:

    Ctx.beginPath(); // 声明要开始一条线

    Ctx.moveTo(x,y);// 指定线的起点。moveTo,就像是将画笔移动到某个点。

    Ctx.lineTo(x,y);// 指定线的终点

    Ctx.lineCap=”round”;// 设置线的两端(线帽),可选值有:butt,round,square

    Ctx.lineWidth=15;// 指定线的宽度

    Ctx.strokeStyle=”#ff0000”;// 设置线的颜色,不设置则根据当前颜色。默认是黑色。

    Ctx.stroke(); // 开始描边

    2)曲线(Curves

    使用canvas可以做的曲线主要包括:圆弧、bezier曲线、quadratic曲线。

    2.1) 圆弧(arc

    要做一条圆弧,编码的顺序一般是这样的:

    Ctx.beginPath(); // 声明要开始一条新的path

    Ctx.arc(x,y,radius,startAngle,endAngle,antiClockwise); //指定弧线path

    Ctx.lineWidth=15;// 指定线的宽度

    Ctx.strokeStyle=’black’; // 指定线的颜色

    Ctx.lineCap=”square”;// 指定线帽

    Ctx.stroke();// 开始描边

    在做圆弧时,最主要的就是ctx.arc

    该方法的参数列表:

    参数

    描述

    x

    圆的中心的 x 坐标。

    y

    圆的中心的 y 坐标。

    r

    圆的半径。

    startAngle

    起点的弧值。(弧的圆形的三点钟位置是 0 度)。

    endAngle

    终点的弧值。

    antiClockwise

    是否逆时针绘图,可选。False = 顺时针,true = 逆时针。

    这里用的是弧度,不是角度。可能大家对角度都比较熟悉。

    从起点,按照顺时针(或者逆时针)方向转一周,是360度(角度)。

    如果以弧度来表示,则是按照顺时针(或者逆时针)方向转一周,弧度是 2*PI

    既然这里要求的是弧度值,大家熟悉的是角度,那么怎么将角度转换为弧度呢?

    假定 f(x) => 360x = 2*PI 可以很容易推导出x=PI/180。也就是1度(角度)=PI/180弧度。

    那么90o  = 90 * PI /180= 0.5 PI; 180o = PI; 360o = 2*PI

    下图是一张按照顺时针转动的弧度:

     

    2.2)二次方曲线(quadratic curves

    二次方曲线,也称为抛物线。

    维基百科时有关二次方曲线的描述:

    https://en.wikipedia.org/wiki/Quadratic_function

    Ctx.beginPath(); // 开始画线

    Ctx.moveTo(x,y)// 起点

    Ctx.quadraticCurveTo(cx,cy,ex,ey);// 指定要画抛物线

    Ctx.lineWidth=12; // 指定线宽带

    Ctx.strokeStyle=”black”;// 指定线颜色

    Ctx.lineCap=’butt’; // 指定线帽

    Ctx.stroke(); // 开始描边

    其中quadraticCurveTocx,cy,ex,ey)前两个参数表示控制点坐标,后两个参数表示终点坐标。

     

    下面是一个demo:

     

     

     

    2.3)三次方曲线(Bezier Curve

    Quadratic curve 有一个控制点,而Bezier curve 有两个控制点。

    指定画bezier曲线的方法是:

    Ctx.bezierCurveTo(c1x,c1y, c2x, c2y, ex, ey)

     

    3) Path

    在画line,curve时,我们都用beginPath()来表示要启动一条path,然后进行画直线或者曲线。其实可以将他们串连起来。

     

     

    在多条线串联的地方,称为lineJoin,它有三种形式:

     

    4) 矩形(rectangle

    4.1 绘制矩形

    绘制矩形,有两种方式:

    Ctx.rect(x,y, width, height);

    Ctx.strokeRect(x,y,width, height)

    区别是第一种需要beginPath(),第二种不需要。

     

     

    4.2 填充矩形

    绘制并填充矩形。

    Ctx.fillRect(x,y,width, height);

    4.3 清理rect

    会把指定矩形内的内容全部清空。

    Ctx.clearRect(x,y,widht, height);

    5) 线条样式

     

     

     从图上很容易看出来,butt,round,square的区别来。

    2.2、文本

    2.1 文本样式

    css中,设置问题的属性有:

     

     

    然而并不能通过css style设定canvas中文本的样式。

    Canvas中的text有自己的一套设置格式:

     

    Ctx.font=”${font-style} ${font-size} ${font-family}” // 指定文本样子,大小,字体

    Ctx.fillStyle=”blue” ;// 指定文本颜色

    Ctx.textAlign=”center”; // 指定水平方向上的对齐方式

    Ctx.textBaseline=”middle” 指定竖直方向上的对齐方式

    Ctx.strokeStyle=”blue”; // 指定文本stroke颜色

     

    2.2 填充文本

     

    Ctx.fillText(text, x, y);

    canvas中填充的文本,是不会自动折行的,所以如果文本太长的话,需要自己控制折行显示。

     

     

     

    2.3、图像、视频

     

    canvas加入图像、画布、视频,,使用drawImage即可。在将图像、画布、视频放到canvas时,可以整体放入,也可以剪切后放入。在使用API时,也有三种用法:

    假设要添加的图像、画布、视频为源:

    1drawImage(img,x,y);

    将源放到canvasx,y处。

    2)drawImage(img,x,y,width,height);

    将源放到x,y处,并将源以width,height的尺寸来缩放显示。

    3drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

    将源从sx,sy出开始截取swidth,sheight的内容,然后缩放到width,height的尺寸,放到canvasx,y处。

    Image:要使用的图片、画布、视频

    Sx,sy:从源的sx,sy坐标处剪切

    Swidth,Sheight:源的宽,

    X,y:放到canvasx位置

    2.4、填充样式

    在填充时,可以有三种填充方式:

    ·color 填充为某种颜色

    ·gradient 填充为渐变颜色

    ·按pattern进行填充(使用它可以填充图片)

    http://www.w3school.com.cn/tags/canvas_fillstyle.asp

    3、坐标平移、转换、旋转

    默认情况下,坐标原点是在Canvas左上角。有时我们需要移动坐标轴、或者xy轴转换来进行操作。

    3.1 translate 平移

    该方法是对坐标平移,不是坐标系

     

    从效果上,给人的感觉是:在执行完 translate后,坐标轴原点位置由原来的 (0,0)变为原来的(70,70)。之后的作图,就以新的坐标原点为(0,0)

    那么想要再将坐标原点重置,则需要将坐标轴再进行平移。

    其实应该这样理解: (x0,y0) 进行一定的运算后成为(x1,y1),然后再进行沿着x,y轴进行平移xt,yt个单位到(x2,y2)

    那么上面的代码,fillRect(10,10,100,50)就可以理解为:先在坐标系内以 (10,10)为起点画一个 长 100,宽50的矩形。

    那么 矩形的四个角的点是:

    (10, 10) , (110, 10),

    (10, 60) , (110, 60)

    然后对每个点的沿着x轴平移 70,再沿着 y轴平移 70,那么就变成了:

    (80,80),(180,80)

    (80,130),(180,130)

     用矩阵来表示坐标平移:

    Translate(tx,ty),实际在作图(点,线,面)时,会对grid内每一个要做图点,基于(tx,ty)进行平移运算。这个其实是向量运算。也可以看作是矩阵加运算。

     (x,y) 经过 (tx, ty) 平移后的点的计算,使用矩阵运算就是:

    [ x         + [tx   => [x+tx]

    [y ]            ty]        [y+ty]

     

    3.2 scale 缩放

    scale(xPercent, yPercent) 参数是x,y轴的缩放百分比。 大于1是放大,小于1是缩小。

    假设默认是 1个长度占用1个像素。假设画一条长度为 10的直线,就是占用10个像素。

    使用scale放大到200%后,画一条长度为 10的直线,就是占用20个像素。

    也就是缩放的是坐标轴的长度

     

    [x                           [sx*x

    y] * [sx, sy] =>       sy * y]

    3.3 skew 拉伸                       

     canvas API中,是没有这个方法的。

    上面是一条线段(A,B),围绕起点(A)沿着x,y轴方向进行拉伸。

    线段AB上的所有点(x,y),沿着x 轴方向进行拉伸后,坐标变为:(x + y * tan&,y)

    线段AB上的所有点(x,y),沿着y 轴方向进行拉伸后,坐标变为:(x , x * tanβ+ y)

    用矩阵来表示拉伸,就是:

    [ x     * [1 ,tanβ          => [x+y*tan&

      y]       tan&,1]                 x*tanβ+ y ]

    3.3 rotate 旋转

    该方法是对坐标轴旋转

    rotateangle)参数是弧度。之前已经说过了,1度(角度)=PI/180弧度,那么假设你想转90o,那么应该是rotate90 * Math.PI/180 )。

     

     rotate 是坐标系旋转,参数是弧度值。

     相关理论,可以参考:https://en.wikipedia.org/wiki/Rotation_matrix

    用矩阵来表示:

    [ x                                             [x*cosθ-y*sinθ

      y]   *   =>    x*sin θ  + y*cos ]

    3.3 transform 变换

    线性方程: y = ax + b ;可以表示为 x 放大 a倍后,沿着y轴向上平移 b,

     

     [a    c  e        [x         x' = ax + cy + e 

      b   d   f      *  y    =>    y' = bx +dy +f

     0    0   1 ]      1]            1 =  1

     

    transform(xscala,yskew,xskew,yscala,xtranslate,ytranslate) 该方法是对坐标系进行平移、缩放、旋转的综合的操作。

    xscala:x轴缩放

    yskew:沿y轴方向拉伸

    xskew:沿x轴方向拉伸

    yscala:y轴缩放

    xtranslate:沿x轴平移

    ytranslate:沿y轴平移

    矩阵中的a,b,c,d,e,f分别代表:

     a = xscale

     b= yskew

     c =xskew

     d= yscale

    e = xtranslate

    f = ytranslate

    <!DOCTYPE html>
    <html>
    <body>
    
    <canvas id="myCanvas" width="3000" height="1500" style="border:1px solid #d3d3d3;">
    Your browser does not support the HTML5 canvas tag.
    </canvas>
    
    <script>
    
    var c=document.getElementById("myCanvas");
    var ctx=c.getContext("2d");
    
    var length = 200, width = 20, height =80;
    var angle= Math.PI/8;
    var yskew = angle;
    var xskew = Math.PI/2 - yAxisRarote;
    
    var xTanslate = 240;
    var yTanslate = 140;
    
    var deltaYTranslate  = width,  deltaXTranslate = deltaYTranslate / Math.tan(angle) ;
     // 后面
    ctx.transform(1,0,0,1,xTanslate ,yTanslate );
    ctx.fillStyle="red";
    ctx.fillRect(0,0,length,height);
     // 复原
    ctx.transform(1,0,0,1, 0 - xTanslate , 0-yTanslate );
    
     // 前面
    ctx.transform(1,0,0,1,xTanslate + deltaXTranslate ,yTanslate + deltaYTranslate  );
    ctx.fillStyle="green";
    ctx.fillRect(0,0,length,height);
     // 复原
    ctx.transform(1,0,0,1,0-(xTanslate + deltaXTranslate), 0-(yTanslate + deltaYTranslate));
    
     // 左面
    ctx.fillStyle="yellow";
    ctx.transform(1,Math.tan(angle),0,1,xTanslate ,yTanslate );
    ctx.fillRect(0,0, deltaXTranslate,height);
     // 复原
    ctx.transform(1,-Math.tan(angle),0,1,0,0);
    ctx.transform(1,0,0,1, 0-xTanslate , 0-yTanslate );
    
     // 顶面
    ctx.fillStyle="#ACE";
    ctx.transform(1,0,Math.tan(Math.PI/2 - angle),1, xTanslate ,yTanslate);
    ctx.fillRect(0,0,length,width);
     // 复原
    ctx.transform(1,0,-Math.tan(Math.PI/2 - angle),1,0,0);
    ctx.transform(1,0,0,1, 0-xTanslate , 0-yTanslate );
    
    </script>
    
    </body>
    </html>

     

    下面是一个 Canvas transform 和 CSS transform 对照的例子:

     

     

     

     

  • 相关阅读:
    asp.net2.0系列视频教程
    Android入门教程(三十一)SQLite分页读取(转)
    sql语句大全
    判断是不是ie浏览器 加上ie11
    字节面试题
    泛型
    线程和
    sysbench工具
    自定义集合类
    类型通配符
  • 原文地址:https://www.cnblogs.com/f1194361820/p/7423319.html
Copyright © 2011-2022 走看看