<canvas>标签的使用(图形学初步?)

来源:互联网 发布:小论文数据大多造假 编辑:程序博客网 时间:2024/06/02 04:15

文中例子来源:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes,在这里表示感谢。

由于Web课程的Demo想做iPone的购买界面,原因是我觉得苹果的设计实在漂亮。就去学习,有用到Canvas标签,这个苹果引领起来的标签实在强大。学习记录在此。

用法

<canvas>标签的用法是在<body>中放好位置,然后在js中进行配置。简单的Demo代码如下,忘记了看到可以尽快上手:

<head>    <meta charset="UTF-8">    <title>CanvasTest</title>    <script type="text/javascript">        function draw() {            var canvas = document.getElementById("canvas");            if(canvas.getContext)            {                var ctx = canvas.getContext("2d");                ctx.fillStyle = "rgb(200, 0, 0)";   //颜色                ctx.fillRect(10, 10, 55, 50);       //位置和大小                ctx.fillStyle = "rgba(0, 0, 200, 0.5)";   //颜色,透明度                ctx.fillRect (30, 30, 55, 50);            //位置和大小            }        }    </script>    <style type="text/css">        canvas {            border: 1px solid black;        }    </style></head><body onload="draw()"><canvas id="canvas" width="150" height="150">//这里存放替代内容,可以用文本与图片</canvas></body>

矩形绘制

矩形绘制有三种常用方法

fillRect(x, y, width, height)   //绘制一个填充的矩形strokeRect(x, y, width, height) //绘制一个矩形的边框clearRect(x, y, width, height)  //清除指定矩形区域,让清除部分完全透明。

绘制例子:

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext) {    var ctx = canvas.getContext('2d');    ctx.fillRect(25,25,100,100);    ctx.clearRect(45,45,60,60);    ctx.strokeRect(50,50,50,50);  }}

绘制矩形例子

另外还可以用react()函数绘制矩形。

rect(x, y, width, height)       //绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。

当该方法执行的时候,moveTo()方法自动设置坐标参数(0,0)。也就是说,当前笔触自动重置会默认坐标。

绘制路径

非基本的图形可以由路径绘制。绘制路径是图形绘制里的一个基本内容。通俗的讲就是为想画的图形画边界。

用路径绘制图形步骤如下:

  1. 首先,你需要创建路径起始点。
  2. 然后你使用画图命令去画出路径。
  3. 之后你把路径封闭。
  4. 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

接下来是绘制图形所用到的函数:

beginPath() //新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。(相当于 文件-新建)closePath() //闭合路径之后图形绘制命令又重新指向到上下文中。stroke()    //通过线条来绘制图形轮廓。fill()      //通过填充路径的内容区域生成实心的图形。填充时会自动闭合。

用路径绘制一个三角形的例子:

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    ctx.beginPath();    ctx.moveTo(75,50);    ctx.lineTo(100,75);    ctx.lineTo(100,25);    ctx.fill();  }}

路径绘制三角形例子

其中moveTo()函数是一个移动笔触,用来将笔触移动到指定坐标上,十分有用。
lineTo是绘制直线的函数,绘制一条到坐标位置的直线。

下面是一个灵活运用移动笔触绘制笑脸的例子:

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    ctx.beginPath();    ctx.arc(75,75,50,0,Math.PI*2,true); // 绘制    ctx.moveTo(110,75);    ctx.arc(75,75,35,0,Math.PI,false);   // 口(顺时针)    ctx.moveTo(65,65);    ctx.arc(60,65,5,0,Math.PI*2,true);  // 左眼    ctx.moveTo(95,65);    ctx.arc(90,65,5,0,Math.PI*2,true);  // 右眼    ctx.stroke();  }}

笔触绘制笑脸

例子中的arc()方法用来绘制弧线。使用方法如下:

arc(x, y, radius, startAngle, endAngle, anticlockwise) //画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。arcTo(x1, y1, x2, y2, radius)                          //根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点(这个方法不推荐使用)。

arc()函数六个函数分别为:横纵坐标、半径、始末弧度、旋转方向(正逆否顺)
需要注意的是arc指的是弧度而不是角度,计算公式:radians=(Math.PI/180)*degrees

下面是12个不同角度与填充圆弧的例子:

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    for(var i=0;i<4;i++){      for(var j=0;j<3;j++){        ctx.beginPath();        var x              = 25+j*50;               // x 坐标值        var y              = 25+i*50;               // y 坐标值        var radius         = 20;                    // 圆弧半径        var startAngle     = 0;                     // 开始点        var endAngle       = Math.PI+(Math.PI*j)/2; // 结束点        var anticlockwise  = i%2==0 ? false : true; // 顺时针或逆时针        ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);        if (i>1){          ctx.fill();        } else {          ctx.stroke();        }      }    }  }}

弧度例子

贝塞尔曲线

贝塞尔曲线用来绘制复杂有规律的图形,具体图像参考维基百科:https://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A。
贝塞尔曲线的使用函数:

quadraticCurveTo(cp1x, cp1y, x, y)          //绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) //绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。

贝塞尔曲线
上图是两种贝塞尔曲线的图示。在图中,蓝点为起始点,结束点(x, y),控制点(cpx, cpy)。

二次贝塞尔曲线

这个例子使用多个贝塞尔曲线来渲染对话气泡。

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext) {    var ctx = canvas.getContext('2d');    // 二次贝尔赛曲线    ctx.beginPath();    ctx.moveTo(75,25);    ctx.quadraticCurveTo(25,25,25,62.5);    ctx.quadraticCurveTo(25,100,50,100);    ctx.quadraticCurveTo(50,120,30,125);    ctx.quadraticCurveTo(60,120,65,100);    ctx.quadraticCurveTo(125,100,125,62.5);    ctx.quadraticCurveTo(125,25,75,25);    ctx.stroke();  }}

二次贝塞尔曲线用例

三次贝塞尔曲线

这个例子使用贝塞尔曲线绘制心形。

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    //三次贝塞尔曲线    ctx.beginPath();    ctx.moveTo(75,40);    ctx.bezierCurveTo(75,37,70,25,50,25);    ctx.bezierCurveTo(20,25,20,62.5,20,62.5);    ctx.bezierCurveTo(20,80,40,102,75,120);    ctx.bezierCurveTo(110,102,130,80,130,62.5);    ctx.bezierCurveTo(130,62.5,130,25,100,25);    ctx.bezierCurveTo(85,25,75,37,75,40);    ctx.fill();  }}

三次贝塞尔曲线用例

(根据向同学请教的经验:贝塞尔曲线是用来画曲线的,如果你想自己画哪种曲线的画,可以把起点终点确定,控制点靠试)

组合使用

这个是MDN上组合使用的例子,教程说实际上很简单,你们随意感受下……

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    roundedRect(ctx,12,12,150,150,15);    roundedRect(ctx,19,19,150,150,9);    roundedRect(ctx,53,53,49,33,10);    roundedRect(ctx,53,119,49,16,6);    roundedRect(ctx,135,53,49,33,10);    roundedRect(ctx,135,119,25,49,10);    ctx.beginPath();    ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);    ctx.lineTo(31,37);    ctx.fill();    for(var i=0;i<8;i++){      ctx.fillRect(51+i*16,35,4,4);    }    for(i=0;i<6;i++){      ctx.fillRect(115,51+i*16,4,4);    }    for(i=0;i<8;i++){      ctx.fillRect(51+i*16,99,4,4);    }    ctx.beginPath();    ctx.moveTo(83,116);    ctx.lineTo(83,102);    ctx.bezierCurveTo(83,94,89,88,97,88);    ctx.bezierCurveTo(105,88,111,94,111,102);    ctx.lineTo(111,116);    ctx.lineTo(106.333,111.333);    ctx.lineTo(101.666,116);    ctx.lineTo(97,111.333);    ctx.lineTo(92.333,116);    ctx.lineTo(87.666,111.333);    ctx.lineTo(83,116);    ctx.fill();    ctx.fillStyle = "white";    ctx.beginPath();    ctx.moveTo(91,96);    ctx.bezierCurveTo(88,96,87,99,87,101);    ctx.bezierCurveTo(87,103,88,106,91,106);    ctx.bezierCurveTo(94,106,95,103,95,101);    ctx.bezierCurveTo(95,99,94,96,91,96);    ctx.moveTo(103,96);    ctx.bezierCurveTo(100,96,99,99,99,101);    ctx.bezierCurveTo(99,103,100,106,103,106);    ctx.bezierCurveTo(106,106,107,103,107,101);    ctx.bezierCurveTo(107,99,106,96,103,96);    ctx.fill();    ctx.fillStyle = "black";    ctx.beginPath();    ctx.arc(101,102,2,0,Math.PI*2,true);    ctx.fill();    ctx.beginPath();    ctx.arc(89,102,2,0,Math.PI*2,true);    ctx.fill();  }}// 封装的一个用于绘制圆角矩形的函数.function roundedRect(ctx,x,y,width,height,radius){  ctx.beginPath();  ctx.moveTo(x,y+radius);  ctx.lineTo(x,y+height-radius);  ctx.quadraticCurveTo(x,y+height,x+radius,y+height);  ctx.lineTo(x+width-radius,y+height);  ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);  ctx.lineTo(x+width,y+radius);  ctx.quadraticCurveTo(x+width,y,x+width-radius,y);  ctx.lineTo(x+radius,y);  ctx.quadraticCurveTo(x,y,x,y+radius);  ctx.stroke();}

这里写图片描述

Path2D 对象

Path2D对象用于记录图像,使图像成为一个对象,方便之后使用。之前的路径方法都可以在Path2D中使用。

new Path2D();     // 空的Path对象new Path2D(path); // 克隆Path对象new Path2D(d);    // 从SVG建立Path对象

下面是一个Path2D的使用例子:

function draw() {  var canvas = document.getElementById('canvas');  if (canvas.getContext){    var ctx = canvas.getContext('2d');    var rectangle = new Path2D();    rectangle.rect(10, 10, 50, 50);    var circle = new Path2D();    circle.moveTo(125, 35);    circle.arc(100, 35, 25, 0, 2 * Math.PI);    ctx.stroke(rectangle);    ctx.fill(circle);  }}

Path2D实例

SVG(Scalable Vector Graphics) path

可伸缩向量图形(Scalable Vector Graphics)是另外一种绘制的方法,操作方法为定点(Mx y)——水平移动(h x)——下移(v x)——左移(h x)——回到原点(z)。这将存储为一个SVG data path 供Path2D使用。例子如下:

var p = new Path2D("M10 10 h 80 v 80 h -80 Z");
原创粉丝点击