使用canvas画图—基本用法、2D上下文

一、<canvas>元素

1、要使用<canvas>元素必须首先设置其width和height属性,制定可以绘图区域的大小,出现在开始和结束标签后面的是当浏览器不支持这个元素时显示的信息

2、getcontext()方法

  通过传入上下文的名字,取得绘图上下文对象的引用,传入“2d”

// 在html中给canvas标签的ID名是drawing
var drawing = document.getElementById("drawing"); 
// 确定浏览器是否支持<canvas>元素
if(drawing.getContext){
var context = drawing.getContext("2d");
// 更多代码
};

3、toDataURL()方法

  导出在<canvas>元素上绘制的图像,接受一个参数,即图像的MIME类型格式

二、2D上下文

 2D上下文坐标开始于<canvas>元素的左上角,原始坐标为(0,0)

  1. 填充和描边

    填充属性—fillStyle

    描边属性——strokeStyle

    这两个属性可以是字符串、渐变对象或者模式对象,默认值是#000000

  2、绘制矩形

    1、矩形是唯一可以直接在2D上下文中绘制的图像,与矩形有关的方法包括fillRect(),strokeRect()和clearRect(),这3个方法都接受4个参数:矩形的x坐标,y坐标,矩形的宽度和矩形的高度。,这些参数单位都是像素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <input type="button" value="Export" id="export-btn" >

    <script>
        window.onload = function() {

            //取得绘图上下文
            var drawing = document.getElementById("drawing"),
                btn = document.getElementById("export-btn");

            //检测浏览器是否支持<canvas>元素
            if (drawing.getContext) {

                // 取得2d上下文对象
                var context = drawing.getContext("2d");

                // 绘制红色矩形
                context.fillStyle = "#ff0000";  // 颜色填充
                context.fillRect(10, 10, 50, 50);    //绘制矩形

                // 绘制半透明的蓝色矩形
                context.fillStyle = "rgba(0,0,255,0.5)";
                context.fillRect(30, 30, 50, 50);
            };

            btn.onclick = function () {

                // 导出在画布上绘制的图像的数据URI
                var imgURI = drawing.toDataURL();  // 图像为png格式

                //显示图像并放置图像
                var image = document.createElement("img");
                img.src = imgURI;
                document.body.appendChild(image);
            };
        };

    </script>

    <p>This example based on <a href="http://developer.mozilla.org/en/docs/Canvas_tutorial:Basic_usage">Mozilla's documentation</a></p>
    <p>Click <strong>Export</strong> to export the image to an <code>img</code> element. Then, you can right-click and save the image locally.</p>
</body>
</html>

 

 

    2、lineWidth属性——控制描边线条的宽度

    3、lineCap属性——控制线条末端的形状是平头(“butt”)、圆头(“round”)还是方头(“square”)

    4、lineJoin属性——控制线条相交的方式是圆交(“round”)、斜交(“bevel”)还是(“miter”’)

    5、clearRect()方法——用于清除画布上的矩形区域

// 接上面代码中的绘制蓝色矩形的后面
context.clearRect(40, 40, 10, 10);
// ;两个矩形重叠的地方,会清除一小块的矩形区域

  3、绘制路径

    通过路径可以创造出复杂的形状和线条

  • begintPath()——要绘制路径,首先必须调用beginPath()方法
  • arc(x,y,radius,startAngle,endAngle,counterclockwise)
  • arcTo(x1,y1,x2,y2,radius)——从上一点开始绘制一条弧线,到(x2,y2)为止,并且以给定的半径radius穿过(x1,y1)
  • bezierCurveto(c1x,c1y,c2x,c2y,x,y)——从上一点开始绘制一条曲线,到(x,y)为止,并且以(c1x,c1y)和(c2x,c2y)为控制点
  • moveTo(x,y)——将绘图游标移动到(x,y),不画线
  • lineTo(x,y)——从上一点开始绘制一条直线,到(x,y)为止

 

 

  创建了路径后,接下来有几种可能的选择:

  1. 如果想绘制一条连接到路径起点的线条,可以调用closePath();
  2. 如果路径已经完成,想用fillStyle()填充它,可以调用fill()方法
  3. 可以调用stroke()方法对路径描边,描边使用的是strokeStyle(),最后还可以调用clip()在路径上创建一个剪切区域
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    
        <script type="text/javascript">
    
            window.onload = function(){
    
                //取得绘图上下文
                var drawing = document.getElementById("drawing");
    
                //确定浏览器是否支持<canvas>元素
                if (drawing.getContext){
    
                // 取得2D上下文对象
                    var context = drawing.getContext("2d");
    
                // 开始路径
                    context.beginPath();
    
                /* 绘制外圆—圆心为(100,100),radius弧形半径为99,startAngle起始角度为0
               endAngle结束角度为2π弧度(通过Math.PI),counterclockwise为顺时针方向false
             */
                    context.arc(100, 100, 99, 0, 2 * Math.PI, false);
    
                /* 绘制内圆
                   绘制内圆之前,必须先把路径移动到内圆上的某个点
             */
                context.moveTo(194,100);
                context.arc(100,100,94,0,2 * Math.PI,false);
    
                /* 绘制分针组合使用moveTo()和lineTo()的方法,从通过moveTo移动的那一点开始               绘制一条直线,到(x,y)为止
             */
                context.moveTo(100,100);
                context.lineTo(100,15);
    
                // 绘制时针,与分针相同
                    context.moveTo(100,100);
                    context.lineTo(35,100);
                // 描边路径,调用stroke()方法,这样才能把图像绘制到画布上
                    context.stroke();
                };
    }
        </script>
    
    </body>
    </html>

4、绘制文本

  绘制文本相对比较复杂,暂时不学习

5、变换

  •  rotate(angle)——围绕原点旋转图像angle弧度
  • scale(scaleX,scaleY)——缩放图像,在x方向上乘以scaleX,在y方向上乘以scaleY,默认值都是1
  • translate(x,y)——将坐标原点移动到(x,y),原来的坐标原点为(0,0)
  • transform()
  • setTransform()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <script>

        window.onload = function() {
            var drawing = document.getElementById("drawing");

            if (drawing.getContext) {
                var context = drawing.getContext("2d");
                // 开始路径
                context.beginPath();

                /* 绘制外圆—圆心为(100,100),radius弧形半径为99,startAngle起始角度为0
                 endAngle结束角度为2π弧度(通过Math.PI),counterclockwise为顺时针方向false
                 */
                context.arc(100, 100, 99, 0, 2 * Math.PI, false);

                /* 绘制内圆
                 绘制内圆之前,必须先把路径移动到内圆上的某个点
                 */
                context.moveTo(194, 100);
                context.arc(100, 100, 94, 0, 2 * Math.PI, false);

                // 变换原点
                context.translate(100, 100);

                // 围绕原点旋转图像
                context.rotate(1);

                // 绘制分针和时针,此时所有数学计算基于(0,0)
                context.moveTo(0, 0);
                context.lineTo(0, -85);

                context.moveTo(0, 0);
                context.lineTo(-65, 0);

                // 描边路径
                context.stroke();
            };
        }
    </script>
</body>
</html>
  • save()方法和restore()方法——跟踪上下文的状态变化

调用save()方法,后,当时的所有设置都会进入一个栈结构得以保管,然后可以对上下文进行其他修改。等想要回到之前保存的设置时,可以调用restore()方法。连续调用save()方法可以一级一级的保存设置,连续调用restore()方法,则可以一级一级返回。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <script>

        window.onload = function(){
            var drawing = document.getElementById("drawing");

            if(drawing.getContext){
                var context = drawing.getContext("2d");

                // 将fillStyle设置成红色,并调用上下文保存状态
                context.fillStyle = "#ff0000";
                context.save();

                /*将fillStyle修改为绿色,并把坐标原点变换到(100,100),再调用上下文保                   存状态
                 */
                context.fillStyle = "#00ff00";
                context.translate(100,100);
                context.save();

                // 把fillStyle修改为蓝色并绘制蓝色的矩形
                context.fillStyle = "#0000ff";
                context.fillRect(0,0,100,200);    // 从点(100,100)开始绘制蓝色矩形

                // 调用restore()并绘制绿色矩形
                context.restore();
                context.fillRect(10,10,100,200);  // 从点(110,110)开始绘制绿色矩形
                     //这里的高200,多余的部分超出画布应该被隐藏 了吧

                // 调用restore()并绘制红色矩形
                context.restore();
                context.fillRect(0,0,100,200);  // 从点(0,0)开始绘制红色矩形

            };
        };

    </script>
</body>
</html>

6、绘制图像

 1、drawImage()方法——把一副图像绘制到画布上。可以传入9个参数及以下。除了给drawImage传入HTML<img>元素外,还可以传入另一个<canvas>元素作为其第一个参数。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <img id="smiley" src="smile.gif" border="1" title="Image tag" />

    <script>

        window.onload = function(){
            var drawing = document.getElementById("drawing");
            if(drawing.getContext){
                var context = drawing.getContext("2d");

                // 取得文档中的图像
                var image = document.getElementById("smiley")

                /*绘制到上下文中,起点为(10,10)。绘制到画布上的图像与原图像一样大小,如果想改           变大小,则可以再传入两个参数,分别表示目标高度和宽度
                 */
                context.drawImage(image,10,10);
                context.drawImage(image,50,10,20,30);  // 绘制出来的图像变成20*30像素

                /*
                 绘制图像的某个区域,drawImage()方法需要传入9个参数
                 */
                context.drawImage(image,0,10,50,50,0,100,40,60);
            }
        }

    </script>
</body>
</html>

7、阴影

2D上下文根据以下几个属性的值,自动为形状或路径绘制出阴影。只要在绘制前,为这些属性设置默认的值,就能自动产生阴影。

  • shadowColor——用css颜色格式表示的阴影颜色,默认为黑色
  • shadowOffsetX——x轴方向的阴影偏移量,默认为0
  • shadowOffsetY——y轴方向的阴影偏移量,默认为0

shadowBlur——模糊的像素数,默认为0,即不模糊

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <script>
        window.onload = function(){
            var drawing = document.getElementById("drawing");
            if (drawing.getContext){
                var context  =drawing.getContext("2d");

                // 添加阴影
                context.shadowOffsetX = 5;
                context.shadowOffsetY = 5;
                context.shadowBlur = 2;
                context.shadowColor = "rgba(0,0,0,0.5)";


                // 绘制红色和蓝色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10,10,50,50);
                context.fillStyle = "rgba(0,0,255,1)";
                context.fillRect(30,30,50,50);
            }

        }
    </script>
</body>
</html>

 8、渐变

1、渐变由CanvasGradient实例表示,通过2D上下文创建和修改。要创建一个新的线性渐变,可以调用createLinearGradient()方法。接受4个参数:起点和终点的x和y坐标;

2、创建渐变对象后,第二步是使用addColorStop()方法来指定色标。接受两个参数:色标位置和CSS颜色值,色标位置是一个0(开始的颜色)到1(结束的颜色)之间的数字;

3、要注意的是:使用画布的时候,确保坐标匹配很重要,例如渐变中,要确保矩形和渐变的坐标匹配才行;

4、为了确保渐变与形状对齐,有时候考虑用函数来确保坐标合适。例如:

function createRecrLinearGradient(context,x,y,width,height){
    return context.createLinearGradient(x,y,x+width,y+height);       
};
// 一些代码
context.fillRect(x,y,width,height); 
// 因为上面的函数,从而可以直接在fillRect()中使用相同的值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <script>
        window.onload = function(){
            var drawing = document.getElementById("drawing");
            if(drawing.getContext){
                var context = drawing.getContext("2d");

                /*为确保渐变与形状对齐,使用createRectLinearGradient函数来确保坐标合适
                 此函数返回线性渐变,从而可以在fillRect()中使用相同的值
                 */
                function createRectLinearGradient(context,x,y,width,height){
                    return context.createLinearGradient(x,y,x+width,y+width);
                };

                // 在取得2d上下文对象后,通过调用createLinearGradient()创建一个新的渐变
                var gradient = createRectLinearGradient(context,30,30,50,50);

                // 创建渐变后,使用addColorStop()方法指定色标
                gradient.addColorStop(0,"white");
                gradient.addColorStop(1,"black");

                // 绘制红色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10,10,50,50);

                // 绘制渐变矩形
                context.fillStyle = gradient;
                context.fillRect(30,30,50,50)

            };
        };
    </script>

</body>
</html>

9、模式

1、模式就是重复的图像,要创建一个新模式,可以调用createPattern()方法,并传入两个参数,:一个HTML元素和一个表示如何重复图像的字符串,其中第二个参数的值和css的background-repeat的属性值相同,包括“repeat”、“repeat-x”、“repeat-y”、“no-repeat”

2、模式与渐变一样,都是从画布的原点(0,0)开始,将填充样式fillStyle设置为模式对象,只表示在fillRect规定中的特定区域内显示重复的图像

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <img id="smiley" src="smile.gif" border="1" title="Image tag" />

    <script>
        window.onload = function(){
            var drawing = document.getElementById("drawing");
            if(drawing.getContext){
                var context = drawing.getContext("2d");

                //取得一个HTML<img>元素或者<video>元素或者<canvas>元素
                // 创建一个新模式,调用createPattern()方法
                var image = document.getElementById("smiley"),
                    pattern = context.createPattern(image,"repeat");
                // 绘制矩形
                context.fillStyle = pattern;
                context.fillRect(10,10,150,150);
            };
        };
    </script>
</body>
</html>

10、使用图像数据

1、通过getImageData()取得原始图像数据,接受4个参数:把取得其数据的画面区域的x和y坐标,以及该区域的像素高度和宽度,然后返回的对象是一个ImageData的实例,有3个属性,width,height和data,其中data属性是一个数组,保存着图像中每一个像素的数据;

2、在data数组中,每一个像素用4个元素来保存,分别表示红。绿、蓝和透明度值,因此,第一个像素的数据就保存在数组的第0到第3个元素中

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>This example won't run locally due to security restrictions. You load this example from a web server.</p>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <img id="smiley" src="smile2.gif" border="1" title="Image tag" />
    <script>
        window.onload = function(){
            var drawing = document.getElementById("drawing");
            if(drawing.getContext){
                var context = drawing.getContext("2d"),
                    image = document.images[0],
                    imageData, data,
                    i, len, average,
                    red, green, blue, alpha;

                // 取得第一幅图像后在画布上绘制原始图像
                context.drawImage(image,0,0);

                // 取得原始图像的imageData对象
                imageData = context.getImageData(0, 0, image.width, image.height);

                /*data属性是一个数组,保存着图像中每一个像素的数据,取得imageData对象的                  的数据
                */
                data = imageData.data;

                /*通过for循环,遍历图像数据中的每一个像素,因为第一个像素的数据就保存在                    数组的第0到第3个元素中
                 */
                for (i=0, len=data.length; i < len; i+=4){
                    red = data[i];
                    green = data[i+1];
                    blue = data[i+2];
                    alpha = data[i+3];
                }

                // 在上面得到每一个像素的颜色的数据后,求rgb的平均值,向下取整
                average = Math.floor((red+green+blue)/3);

                // 设置颜色值,透明度不变
                data[i] = average;
                data[i+1] = average;
                data[i+2] = average;

                /*在把data数组回写到imageData对象后,再调用putImageData()方法把图像数                  据绘制到画布上
                 */
                imageData.data = data;
                context.putImageData(imageData, 0, 0);
            };
        };
    </script>

</body>
</html>

 

10、合成

1、globalAlpha属性——是一个介于0和1之间的值,用于指定在它后面的所有绘制的透明度,默认值为0;

2、globalCompositionOperation属性——后绘制的图形怎样与先绘制的图像相结合

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <script>
        window.onload = function(){
            var drawing = document.getElementById("drawing");

            if (drawing.getContext){

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

                //绘制红色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10, 10, 50, 50);

               /* // 修改全局透明度
                context.globalAlpha = 0.5;*/

                // 设置合成操作
                context.globalCompositeOperation = "destination-over";

                //draw a blue rectangle
                context.fillStyle = "rgba(0,0,255,1)";
                context.fillRect(30, 30, 50, 50);
            }
        };

    </script>
</body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2017-04-16 15:38  FernLi  阅读(632)  评论(0)    收藏  举报