美文网首页Canvas
js前端开发—canvas篇—2D上下文(未完待续)

js前端开发—canvas篇—2D上下文(未完待续)

作者: BeYanJin | 来源:发表于2017-03-09 16:32 被阅读0次

    参考资料

    《Javascript高级层序设计》(第3版)

    前言

    本人菜鸟,入IT只为当鼓励师。本编文章旨在总结《Javascript高级层序设计(第3版)》一书中第15章canvas的一些api。第(一)篇只总结2D上下文。

    一、<canvan>元素

    出处:HTML5。
    用途:设定一个区域,通过JS动态地在区域上绘制图形。
    组成:由几组API构成,可分为 2D上下文(基本绘图能力) 和 3D上下文(WebGL)。

    兼容性

    • 浏览器:IE9+、Firefox1.5+、Safari2+、Opera9+、Chrome、IOS版Safari、Android版WebKit。
    • 操作系统:Windows XP因缺少必要的绘图程序,不管用什么浏览器都不支持。

    二、基本用法

    1. 建立区域

    要使用<canvas>元素,必须设置width和height属性,指定可以绘图的区域大小。设置完后,如果浏览器兼容<canvas>标签,则建立的区域应是空白的;否则,会显示其中的文本:A drawing of something。

    <canvas id="drawing" width="200" height="200">A drawing of something</canvas>
    

    2. 取得绘图上下文(<canvas>元素的DOM对象)

    要在这块画布上绘图,需要取得绘图上下文。绘图上下文也就是取得相应<canvas>元素的DOM对象。

    // 取得DOM对象,也为canvas对象
    var drawing = document.getElementById("drawing");
    

    3. 取得2D上下文对象 getContext("2d")

    只取得DOM对象还不行,还要调用<canvas>DOM对象拥有的 getContext(param) 方法。其中传入参数为一个字符串,因为本篇文章总结的是2D上下文(平面),故传入"2d",获得2D上下文对象。后面一切关于绘图的方法和属性,其实都是围绕着2D上下文对象开展的,也就是代码示例中的context

    method param return
    getContext(param) 上下文对象的类型,有如下选择:</br>"2d"(2d上下文)</br>"3d"(3d上下文) 上下文对象

    在调用该方法之前,为了保证程序的健壮性,最好加入检测代码。

    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) {
        // 取得2D上下文对象
        var context = drawing.getContext("2d");
        // 更多代码
    }
    

    4. 导出在<canvas>元素上绘制的图像

    当在<canvas>元素上绘制完图像后,可以调用DOM对象的 toDataURL(param) 方法,将该图像导出成为一张图片,传入参数为欲导出图片的MIME类型,例如:image/pngimage/jpeg 等等。拥有该方法的对象是<canvas>元素的DOM对象,并不是2d上下文对象context,两者要区分开来

    method param return compatibility
    toDataURL(param) 图像的MIME类型格式,有如下选择:</br>"image/jpeg"(Firefox和Opera默认)</br>"image/png"(其他默认) 图像的数据URI IE9+、Firefox3.5+ 、Opera10
    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) {
        // 取得图像的数据URI
        var imgURI = drawing.toDataURI("image/png");
       
        // 显示图像
        var image = document.createElement("img");
        image.src = imgURI;
        document.body.appendChild(image);
    }
    

    三、2D上下文 context

    (0, 0)为<canvas>元素所占区域的原点坐标,x向右递增,y向下递增

    1. 填充和描边

    attribute value effect
    fillStyle String类型:颜色名、十六进制码、rgb等,如"#0000ff" 设置填充颜色
    strokeStyle String类型:颜色名、十六进制码、rgb等,如"red" 设置描边颜色
    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) {
        var context = drawing.getContext("2d");
        // 以红色描边 
        context.strokeStyle = "red"; 
        // 以蓝色填充 
        context.fillStyle = "#0000ff"; 
        // 绘制描边矩形 
        context.strokeRect(10, 10, 50, 50); 
        // 绘制填充矩形 context.fillRect
        (65, 10, 50, 50);
    }
    

    2. 绘制矩形

    2.1 填充矩形

    method param effect
    fillRect(param1,param2, param3,param4) param1:矩形的x坐标</br>param2:矩形的y坐标</br>param3:矩形的宽度</br>param4:矩形的高度 绘制填充矩形,默认为黑色,可给fillStyle赋值改变其填充颜色
    // 填充
    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) { 
        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);
     }
    

    2.2 描边矩形

    method param effect
    strokeRect(param1, param2, param3, param4) param1:矩形的x坐标</br>param2:矩形的y坐标</br>param3:矩形的宽度</br>param4:矩形的高度 绘制描边矩形,默认为黑色,可给strokeStyle赋值改变其边框颜色
    // 描边
    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) {
        var context = drawing.getContext("2d");
        // 以红色描边 
        context.strokeStyle = "#ff0000"; 
        // 绘制描边矩形 
        context.strokeRect(10, 10, 50, 50); 
        // 以蓝色描边 
        context.strokeStyle = "rgba(0, 0, 255, 0.5)"; 
        // 绘制描边矩形 context.strokeRect(30, 30, 50, 50); 
    }
    

    2.3 清除矩形

    method param effect
    clearRect(param1, param2, param3, param4) param1:矩形的x坐标</br>param2:矩形的y坐标</br>param3:矩形的宽度</br>param4:矩形的高度 清除一块矩形区域
    // 清除矩形区域 
    var drawing = document.getElementById("drawing");  
    
    // 确定浏览器支持<canvas>元素 
    if(drawing.getContext) { 
          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); 
    
          // 在两个矩形重叠的地方清楚一个小矩形 
          context.clearRect(40, 40, 10, 10); 
    }
    

    3. 绘制路径

    3.1 创建路径

    method param effect
    arc(x,y,radius,startAngle,counterclockwise) (x, y):圆心的坐标</br>radius:弧线半径</br>startAngle:起始角度</br>endAngle:结束角度</br>counterclockwise:角度的方向(true:逆时针方向,false:顺时针方向 给定圆心(x,y)和半径radius、起始和结束的角度、方向,绘制一条弧线
    arcTo(x1,y1,x2,y2,radius) (x1, y1):需穿过的点的坐标</br>(x2, y2):终点坐标</br>radius:以给定的半径穿过(x1, y1) 从上一点绘制一条弧线,到(x2,y2)为止,并且以给定的半径穿过(x1, y1)
    bezierCurveTo(c1x,c1y,c2x,c2y,x,y) (c1x,c1y):控制点</br>(c2x,c2y):另一个控制点</br>(x, y):终点坐标 从上一点绘制一条弧线,到(x,y)为止,并且以(c1x,c1y)和(c2x,c2y)为控制点
    lineTo(x,y) (x,y):终点坐标 从上一点开始绘制一条直线,到(x,y)为止
    moveTo(x,y) (x,y):绘图游标移动到的点的坐标 将绘图游标移动到(x,y),不画线
    quadraticCurveTo(cx,cy,x,y) (cx,cy):控制点</br>(x,y):终点坐标 从上一点开始绘制一条二次曲线,到(x,y)为止,并且以(cx,cy)为控制点
    rect(x,y,width,height) (x,y):起点坐标</br>width:矩形的宽</br>height:矩形的高 从点(x,y)开始绘制一个矩形,宽高分别为width和height。这个方法绘制的是矩形路径,而不是strokeRect()和fillRect()所绘制的独立形状

    3.2 处理路径

    method param effect
    beginPath() null 开始创建路径
    closePath() null 关闭路径,回到起点
    fill() null 用fillStyle来填充路径
    stroke() null 用strokeStyle来对路径描边
    clip() null 在路径上创建一个剪切区域

    3.2.1 用上面某些方法描绘一个时钟

     var drawing = document.getElementById("drawing");  
    
    // 确定浏览器支持<canvas>元素 
    if(drawing.getContext) { 
        var context = drawing.getContext("2d");  
    
        // 开始路径 
        context.beginPath();  
    
        // 绘制外圆 
        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.moveTo(100, 100);
      context.lineTo(100, 15);  
    
      // 绘制时针
      context.moveTo(100, 100); 
      context.lineTo(35, 100);  
    
      // 为路径描边 
      context.stroke(); 
    }
    

    3.2.2 用fill()方法填充路径

    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素 
    if(drawing.getContext) {  
        var context = drawing.getContext("2d");  
    
        // 开始路径 
        context.beginPath();  
    
        // 绘制圆 
        context.arc(100, 100, 99, 0, 2*Math.PI, false);  
    
        // 填充路径 
        context.fill();
    }
    

    3.2.3 当路径不闭合时fill()方法无效

    var drawing = document.getElementById("drawing"); 
    
    // 确定浏览器支持<canvas>元素 
    if(drawing.getContext) { 
        var context = drawing.getContext("2d"); 
    
        // 绘制一条对角线 
        context.moveTo(0, 0); 
        context.lineTo(200, 200); 
    
        // 填充路径 
        context.fill(); 
    }
    

    3.3 判断路径点

    method param effect
    isPointInPath(x,y) (x,y):某一任意点的坐标 在路径被关闭前确定判断画布上的点(x,y)是否在路径上

    4. 绘制文本

    4.1 2d上下文的文本属性

    attribute value effect
    font String类型,如"bold 14px Arial" 字体粗细、大小和样式
    textAlign String类型,有如下选择:</br>"start"(x坐标表示文本左端),"center"(正中),"end"(右端) 文本的水平对齐方式
    textBaseline String类型,有如下选择:</br>"top"(y坐标表示文本顶端),"middle"(正中),"bottom"(底端),"hanging"、"alphabetic"、"ideographic"(y坐标指向特定基线坐标) 文本的垂直对齐方式

    其实,fillText()和strokeText()方法都可以接受第四个参数,表示文本的最大像素宽度,如果传入字符串大于最大宽度,会收缩以适应最大宽度。但这个可选参数尚未得到大多数浏览器的支持

    4.2 用fillText()绘制数字12

    method param effect
    fillText(string,x,y) string:要绘制的文本字符串</br>x:x坐标可选的最大像素宽度</br>y:y坐标可选的最大像素宽度 使用fillStyle属性绘制文本
    strokeText(string,x,y) string:要绘制的文本字符串</br>x:x坐标可选的最大像素宽度</br>y:y坐标可选的最大像素宽度 使用strokeStyle属性为文本描边
    var drawing = document.getElementById("drawing");  
    
    // 确定浏览器支持<canvas>元素
    if(drawing.getContext) { 
        var context = drawing.getContext("2d");  
    
        // 开始路径 
        context.beginPath();  
    
        // 绘制外圆 
        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.moveTo(100, 100); 
        context.lineTo(100, 15);
    
        // 绘制时针 
        context.moveTo(100, 100); 
        context.lineTo(35, 100);  
    
        // 为路径描边 
        context.stroke();  
    
        // 绘制数字12 
        context.font = "bold 14px Arial"; 
        context.textAlign = "center"; 
        context.textBaseline = "middle"; 
        context.fillText("12", 100, 20); 
    }
    

    </br>

    4.3 给定宽度的区域,找到文本合适的字体大小

    method param return effect
    mearsureText(string) string类型:要确定大小的文本字符串 object:返回一个对象,该对象只有一个width属性 获得存有文本大小的对象
    var fontSize = 100, 
          context.font = fontSize + "px Arial"; 
    if (context.measureText) { 
        while(context.measureText("Hello world!").width > 140) { 
            fontSize--; 
            context.font = fontSize + "px Arial"; 
        } 
    }  
    context.fillText("Hello world!", 10, 10);
    context.fillText("Font size is " + fontSize + "px", 10, 50);
    

    上面的代码从100像素的字体大小开始递减,最终会找到合适的字体大小,在一个140像素的矩形区域中绘制文本 Hello world!

    5. 变换

    5.1 用translate()方法变换原点位置

    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素 
    if (drawing.getContext) { 
        var context = drawing.getContext("2d");  
        
        // 开始路径 
        context.beginPath(); 
    
        // 绘制外圆 
        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.moveTo(0,0); 
        context.lineTo(0, -85); 
    
        // 绘制时针 
        context.moveTo(0, 0); 
        context.lineTo(-65, 0); 
    
        // 绘制路径 
        context.stroke(); 
    }
    

    可以看出结果与3.2.1的图形相同,但把原点变换到时钟表盘中心点(100, 100)后,在同一方向上绘制线条的数学计算就变得简单起来了。

    5.2 用rotate()方法旋转表针

    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素 
    if (drawing.getContext) { 
        var context = drawing.getContext("2d");  
        
        // 开始路径 
        context.beginPath(); 
    
        // 绘制外圆 
        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.moveTo(0,0); 
        context.lineTo(0, -85); 
    
        // 绘制时针 
        context.moveTo(0, 0); 
        context.lineTo(-65, 0); 
    
        // 旋转表针,旋转弧度值为1,2π对应360°,则1对应(360/2π)°,约为57.30°
        context.rotate(1);
    
        // 绘制路径 
        context.stroke(); 
    }
    

    图中红色的部分不存在,是我做给大家的提示和比较而已,用来指明不加最后一句代码的指针原来的位置。


    5.3 跟踪上下文的状态变化

    栈:先进后出。

    method param effect
    save() null 当下所有设置都会进入一个栈结构
    restore() null 在保存设置的栈结构中向前返回一级
    var drawing = document.getElementById("drawing");
    
    // 确定浏览器支持<canvas>元素
    if (drawing.getContext) {
    
        var context = drawing.getContext("2d");
    
        context.fillStyle = "#ff0000"; 
        context.save();  
    
        context.fillStyle = "#00ff00"; 
        context.translate(100, 100); 
        context.save();  
    
        context.fillStyle = "#0000ff"; 
        //从点(100,100)开始绘制蓝色矩形  
        context.fillRect(0,0,100,200); 
    
        context.restore();  
        //从点(110,110)开始绘制绿色矩形  
        context.fillRect(10,10,100,200);
    
        context.restore(); 
        //从点(0, 0)开始绘制红色矩形
        context.fillRect(0,0,100,200); 
    }
    

    6. 绘制图像

    把一幅图像绘制到画布上,可以使用drawImage()方法。

    method param effect
    drawImage(image,</br>tx,ty) image:要绘制的图像</br>tx:目标图像的x坐标</br>ty:目标图像的y坐标 把图像绘制到画布上,起点坐标为(tx,ty)
    drawImage(image,</br>tx,ty,twidth,theight) image:要绘制的图像</br>tx:目标图像的x坐标</br>ty:目标图像的y坐标</br>twidth:目标图像的宽度</br>theight:目标图像的高度 把图像绘制到画布上,起点坐标为(tx,ty),绘制到画布上的图像的宽度为twidth,高度为theight
    drawImage(image,</br>sx,sy,swidth,sheight,</br>tx,ty,twidth,theight) image:要绘制的图像</br>sx:源图像的x坐标</br>sy:源图像的y坐标</br>swidth:源图像的宽度</br>sheight:源图像的高度</br>tx:目标图像的x坐标</br>ty:目标图像的y坐标</br>twidth:目标图像的宽度</br>theight:目标图像的高度 先对源图像做一些处理,该处理为:以(sx,sy)为起点截取宽度为swidth,高度为sheight的新图像。处理后再把新图像绘制到画布上,起点坐标为(tx,ty),绘制到画布上的新图像的宽度为twidth,高度为theight

    7. 阴影

    attribute value effect
    shadowColor String类型:颜色名、十六进制码、rgb等,如"#0000ff",默认为黑色 用CSS颜色格式表示的阴影颜色
    shadowOffsetX Number类型,默认为0 形状或路径x轴方向的阴影偏移量
    shadowOffsetY Number类型,默认为0 形状或路径y轴方向的阴影偏移量
    shadowBlur Number类型,默认为0,即不模糊 模糊的像素数

    8. 渐变

    method param return
    createLinearGradient 起点的x坐标</br>起点的y坐标</br>终点的x坐标</br>终点的y坐标 返回CanvasGradient对象的实例

    9. 模式

    10. 使用图像数据

    11. 合成

    相关文章

      网友评论

        本文标题:js前端开发—canvas篇—2D上下文(未完待续)

        本文链接:https://www.haomeiwen.com/subject/aktggttx.html