JavaScript Canvas——“2D上下文”的注重要点

Canvas支撑基本绘图才能的2D上下文,以及基于WebGL的3D上下文

基本用法

  • canvas元素:定义画布

  • getContext()要领:定义2D、3D上下文

  • toDataURL()要领:天生图片花样猎取URL链接(支撑“image/png”;有浏览器也支撑“image/jpeg”)

要运用canvas元素,必需先设置其width和height属性,指定能够绘图的地区大小.出现在最先和完毕标签中的内容是后备信息,假如浏览器不支撑就显现这些信息:


<canvas id="drawing" width="600" height="400">Canvas here.</canvas>

要在这块画布上绘图,须要获得绘图上下文,则须要挪用getContext()要领并传入上下文的名字,比方传入”2d”;

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
}

能够运用toDataURL()要领导出在canvas元素上绘制的图象如:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    //获得图象数据的URL
    var imgURL = drawing.toDataURL("image/png");

    //显现图象
    var image = document.createElement("img");
    image.src = imgURL;
    document.body.appendChild(image);
}

举个例子:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.fillStyle = "gray";
    context.fillRect(100, 100, 100, 100);

    context.fillStyle = "#ccc";
    context.fillRect(100, 10, 100, 100);

    //获得图象数据的URL
    var imgURL = drawing.toDataURL("image/png");

    //显现图象
    var image = document.createElement("img");
    image.src = imgURL;
    document.body.appendChild(image);
}

添补和描边(基本操纵)

添补,就是用指定的款式添补图形;描边,就是只在图形的边沿画线,离别涉及到两个属性:

  • fillStyle:添补

  • strokeStyle:描边

这两个属性吸收值是字符串、渐变对象或形式对象,默许值是“#000000”:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    //描边色彩
    context.strokeStyle = "red";
    //添补色彩
    context.fillStyle = "#ccc";
    //描边矩形
    context.strokeRect(10, 10, 50, 50);
    //添补矩形
    context.fillRect(10, 10, 50, 50);
}

绘制矩形

基本要领

  • fillRect()添补矩形

  • strokeRect()描边矩形

  • clearRect()消灭矩形

四个要领都是吸收4个参数:矩形的x坐标,矩形的y坐标,矩形的宽度和矩形的高度.这些参数的单元都是像素;

如添补一个矩形:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.fillStyle = "orange";
    context.fillRect(10, 10, 50, 50);
}

如描边一个矩形:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.strokeStyle = "red";
    context.strokeRect(10, 10, 50, 50);
}

又如消灭画布上的矩形地区:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.fillStyle = "red";
    context.fillRect(10, 10, 50, 50);
    context.clearRect(12, 12, 46, 46);
}

掌握描边的线条

  • lineWidth属性:恣意整数作为参数;

  • lineCap属性:掌握线条末尾的外形是(“butt”平头、“round”圆头、“square”方头)

  • lineJoin属性:线条香蕉的体式格局是(“round”圆交、“bevel”斜交、“miter”斜接)

绘制途径

要绘制途径,起首必需挪用beginPath()要领,示意要最先绘制新途径.然后,再经由过程挪用以下要领来现实的绘制途径

  • beginPath():该要领示意最先绘制途径

其次运用下面的要领绘制途径:

  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘制一条弧线,弧线的半径为radius,肇端和完毕角度(用弧度示意)离别为startAngle和endAngle.末了一个参数示意startAngle和endAngle是不是按逆时针方向盘算,值为false示意按顺时针方向盘算.

  • arcTo(x1, y1, x2, y2, radius):从上一点最先绘制一条弧线,到(x2, y2)为止,而且以给定的半径radius穿过(x1, y1)

  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点最先绘制一条曲线,到(x,y)为止,而且以(c1x, c1y)和(c2x, c2y)为掌握点.

  • lineTo(x, y):从上一点最先绘制一条直线,到(x, y)为止.

  • moveTo(x, y):将绘图游标挪动到(x, y),不画线.

  • quadraticCurveTo(cx, cy, x, y):从上一点最先绘制一条二次曲线,到(x, y)为止,而且以(cx, cy)作为掌握点.

  • rect(x, y, width, height):从点(x, y)最先绘制一个矩形,宽度和高度离别由width和height指定.这个要领绘制的是矩形途径,而不是strokeRect()和fillRect()所绘制的自力的外形.

完毕绘制途径之前,能够检测某个坐标是不是在途径轨迹上:

  • isPointInPath():返回布尔值

完毕绘制途径以后,能够挑选运用下面的要领进一步处置惩罚:

  • closePath():绘制一条连接到途径出发点的线条;

  • fill():应用fillStyle添补;

  • stroke():应用strokeStyle描边;

  • clip():建立一个剪切地区;

如:

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();
}

绘制文本

绘制文本一般有两个要领:

  • fillText()(引荐运用)

  • strokeText()

  • measureText():一个参数,即要绘制的文本

这两个要领都能够吸收4个参数:要绘制的文本字符串,x坐标,y坐标和可选的最大像素值.而且这三个要领都以以下3个属性为基本:

  • font:示意文本款式,大小及字体,用CSS中指定字体的花样来指定.

  • textAlign:示意文本对其体式格局.能够的值有”start”,”end”,”left”,”right”和”center”.不引荐运用”left”和”right”.

  • textBaseline:示意文本的基线.能够的值有”top”,”hanging”,”middle”,”alphabetic”,”ideographic”和”bottom”.值为top,y坐标示意文本顶端,值为”bottom”,y坐标示意文本底端,值为hanging,alphabetic和ideographic,则y坐标离别指向字体的特定基线坐标.

如:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
    if (drawing.getContext) {
        var context = drawing.getContext("2d");
        //font款式
        context.font = "24px monospace";
        //对齐体式格局
        context.textAlign = "start";
        //基线位置
        context.textBaseline = "bottom";
        //添补款式
        context.fillStyle = "red";
        context.fillText("hello there",100,100);
        //描边款式
        context.strokeStyle = "yellow";
        context.strokeText("hello there",100,100);
    }

关于measureText()要领,会返回丈量字符串相干数据的一个对象,现在只要width属性

console.log(context.measureText("Hello world")); //返回TextMetrics对象,该对象现在只要width属性

变更

  • rotate(angle):缭绕原点扭转图象angle弧度.

  • scale(scaleX, scaleY):缩放图象,在X方向乘以scaleX,在y方向乘以scaleY.scaleX和scaleY的默许值是1.0

  • translate(x, y):将坐标原定挪动到(x, y).实行这个变更以后,坐标(0,0)会变成之前由(x,y)示意的点.

  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修正变更矩阵,

要领是乘以以下矩阵:

m1_1 m1_2 dx
m2_1 m2_2 dy
0      0    1
  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变更矩阵重置为默许状况,然后再挪用transform

如:

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.beginPath();
    context.arc(100, 100, 90, 0, 2 * Math.PI, false);
    //变更原点
    context.translate(100, 100);
    context.moveTo(0, 0);
    //扭转
    context.rotate(1);        
    context.lineTo(0, -80);
    context.stroke();
}

而我们能够经由过程

  • save()

在客栈中保留设置,而经由过程

  • restore()

要领恢复上一级状况.我们能够一连运用save()和restore()要领。

var drawing = document.getElementById("drawing");
//肯定浏览器是不是支撑canvas元素
if (drawing.getContext) {
    var context = drawing.getContext("2d");
    context.fillStyle = "red";
    context.save(); //第一次存储

    context.fillStyle="yellow";
    context.translate(100,100);
    context.save(); //第二次存储

    context.fillStyle = "blue";
    context.fillRect(0,0,100,200); //由于translate把原点放在了100,100所以,从这个点最先绘制

    context.restore(); //第一次恢复
    context.fillRect(10,10,100,200); //绘制黄色图形由于运用了一次restore();

    context.restore(); //第二次恢复
    context.fillRect(0,0,100,200); //原点恢复为0,0,绘制赤色图形,由于又运用了一次restore();
}

要注重的是,save()保留的只是对绘图上下文的设置和变更,不会保留绘图上下文的内容。

绘制图象

运用

  • drawImage()

要领来绘制图象.有三种差别的参数组合:

  • 传入一个HTML<img>元素,以及绘制该图象的出发点的x和y坐标.

如:

context.drawImage(img, 0, 0); //从0,0处插进去绘制图片
  • 再多传两个参数,离别示意目的宽度和目的高度(举行缩放,不影响上下文的变更矩阵)

如:

context.drawImage(img, 0, 0,300,200); //从0,0处插进去绘制图片;长度为300高度为200;
  • 再多传4个参数,示意目的图象的x,y坐标和目的图象的宽度和高度(并没有举行缩放):

如:

context.drawImage(img, 0, 0, 300, 200,100,100,100,80); //从0,0处插进去绘制图片;长度为300高度为200;绘制到上下文的100,100处,宽度为100高度为80;

须要注重的是:图象不能来自其他域,不然toDataURL()会抛出毛病。

暗影

  • shadowColor: 用CSS色彩花样示意的暗影色彩,默许为黑色

  • shadowOffsetX: 外形或途径x轴方向的暗影偏移量,默许为0

  • shadowOffsetY: 外形或途径y轴方向的暗影偏移量,默许为0

  • shadowBlur: 隐约的像素数,默许0,即不隐约

如:

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

    //设置暗影
    context.shadowColor ="red"; //暗影色彩
    context.shadowOffsetX = 10; //x轴偏移
    context.shadowOffsetY = 10; //y轴偏移
    context.shadowBlur = "100"; //暗影隐约的像素

    //绘制矩形
    context.fillStyle = "orange";
    context.fillRect(0,0,300,200);

}

渐变

渐变由CanvasGradient实例示意,挪用

  • createLinearGradient()要领,此要领吸收4个参数:出发点的x坐标,出发点的y坐标,尽头的x坐标,尽头的y坐标.挪用这个要领后,它就会建立一个指定大小的渐变,并返回CanvasGradient对象实例.

建立了渐变对象后,下一步就是运用

  • addColorStop()要领来指定色标.吸收两个参数:色标位置和CSS色彩值.色标位置是一个0(最先的色彩)到1(完毕的色彩)之间的数字.

如:

var drawing = document.getElementById("drawing");
var img = document.images[0];
// 肯定浏览器是不是支撑canvas元素
window.onload = function() {
    if (drawing.getContext) {
        var context = drawing.getContext("2d");

        //建立渐变
        var gradient = context.createLinearGradient(0, 100, 200, 100);
        gradient.addColorStop(0, "red");
        gradient.addColorStop(1, "orange");

        //将渐变运用到矩形
        context.fillStyle = gradient;
        context.fillRect(0,0,200,100);
    }
};

假如要绘制异常正确的渐变矩形,则能够运用下面的函数:

function createRectLinearGradient(context, x, y, width, height) {
    return context.createLinearGradient(x, y, x + width, y + height);
}

如:

function createRectLinearGradient(context, x, y, width, height) {
    return context.createLinearGradient(x, y, x + width, y + height);
}

var gradient = createRectLinearGradient(context, 0, 0, 200, 100);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "orange");

context.fillStyle = gradient;
context.fillRect(0, 0, 200, 100);

要建立径向渐变,就要挪用

  • createRadialGradient()要领,吸收6个参数:出发点圆的圆心及半径(前三个参数);尽头圆的圆心及半径(后三个参数):

如:

//挪动原点
context.translate(50, 50);
//建立径向渐变
var gradient = context.createRadialGradient(-20, -20, 10, 20, 20, 10);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "orange");
//添补矩形
context.fillStyle = gradient;
context.fillRect(-100, -100, 400, 400);

形式

形式就是反复的图象,能够用来添补或描边图形.要建立一个新形式,能够挪用:

  • createPattern()要领并传入两个参数:一个HTMLimg元素和一个示意如何反复图象的字符串.

个中,第二个参数的值与CSS的background-repeat属性值雷同,包含”repeat”,”repeat-x”,”repeat-y”,”no-repeat”;别的,该要领的第一个参数也能够传入video元素以及另一个canvas元素;

var context = drawing.getContext("2d");
//定义pattern
var pattern = context.createPattern(img,"repeat");
//添补
context.fillStyle = pattern;
context.fillRect(0,0,600,500);

运用图象数据

经由过程

  • getImageData()获得原始图象数据.这个要领吸收4个参数:要获得其数据的画面地区的x和y坐标以及该地区的像素宽度和高度:

  • setImageData()则依据图象数据,在canvas中绘制出来

如:

window.onload = function() {
    var drawing = document.getElementById("drawing");
    var imgInput = document.images[0];
    //搜检兼容性
    if (drawing.getContext) {
        var context = drawing.getContext("2d");
        //绘制原始图象
        context.drawImage(imgInput, 0, 0);
        //获得图象数据
        var imageData = context.getImageData(0, 0, imgInput.width, imgInput.height);
        var data = imageData.data;
        for (var i = 0, len = data.length; i < len; i+=4) { //i应该是0,4,8...
            var red = data[i]; //0,4,8...
            var green = data[i + 1]; //1,5,9...
            var blue = data[i + 2]; //2,6,10...
            var alpha = data[i + 3]; //3,7,11
            //求得rgb平均值
            var average = Math.floor((red + green + blue) / 3);
            //设置色彩值,通明度稳定
            data[i] = average;
            data[i + 1] = average;
            data[i + 2] = average;
        }
        //回写数据并显现结果
        imageData.data = data;
        context.putImageData(imageData, 0, 0);
    }
};

优化后的代码:

    window.onload = function() {
    var drawing = document.getElementById("drawing"),
        imgInput = document.images[0],
        context,
        imageData,data,i,len,
        red, green, blue, alpha, average;
    //搜检兼容性
    if (drawing.getContext) {
        context = drawing.getContext("2d");
        //绘制原始图象
        context.drawImage(imgInput, 0, 0);
        //获得图象数据
        imageData = context.getImageData(0, 0, imgInput.width, imgInput.height);
        data = imageData.data;
        for (i = 0, len = data.length; i < len; i += 4) { //i应该是0,4,8...
            red = data[i]; //0,4,8...
            green = data[i + 1]; //1,5,9...
            blue = data[i + 2]; //2,6,10...
            alpha = data[i + 3]; //3,7,11
            //求得rgb平均值
            average = Math.floor((red + green + blue) / 3);
            //设置色彩值,通明度稳定
            data[i] = average;
            data[i + 1] = average;
            data[i + 2] = average;
        }
        //回写数据并显现结果
        imageData.data = data;
        context.putImageData(imageData, 0, 0);
    }
};

或许让图片色彩反转:

window.onload = function() {
    var drawing = document.getElementById("drawing");
    var imgInput = document.images[0];
    //搜检兼容性
    if (drawing.getContext) {
        var context = drawing.getContext("2d");
        //绘制原始图象
        context.drawImage(imgInput, 0, 0);
        //获得图象数据
        var imageData = context.getImageData(0, 0, imgInput.width, imgInput.height);
        var data = imageData.data;
        var i, len, red, green, blue, alpha;

        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];
            //反转色彩
            data[i] = 255 - data[i];
            data[i + 1] = 255 - data[i + 1];
            data[i + 2] = 255 - data[i + 2];
        }
        imageData.data = data;
        context.putImageData(imageData, 0, 0);
    }
};

合成

别的另有属性:

  • globalAlpha

  • globalCompositionOperation

个中第一个属性是一个介于0-1之间的值,用来指定一切绘制的通明度,如许就能够先指定通明度,再绘图,然后再重置通明度,如:

window.onload = function() {
    var drawing = document.getElementById("drawing");
    var imgInput = document.images[0];
    //搜检兼容性
    if (drawing.getContext) {
        var context = drawing.getContext("2d");
        //绘制原始图象
        context.drawImage(imgInput, 0, 0);
        context.globalAlpha = 0.5;
        //半通明结果
        context.drawImage(imgInput, 50, 50);
        context.globalAlpha = 1;
        //不通明结果
        context.drawImage(imgInput, 100, 100);
    }
};

别的第二个属性则示意后绘制的图形如何与先绘制的图形连系:

  • source-over: 默许。在目的图象上显现源图象。

  • source-atop: 在目的图象顶部显现源图象。源图象位于目的图象以外的部份是不可见的。

  • source-in: 在目的图象中显现源图象。只要目的图象内的源图象部份会显现,目的图象是通明的。

  • source-out: 在目的图象以外显现源图象。只会显现目的图象以外源图象部份,目的图象是通明的。

  • destination-over: 在源图象上方显现目的图象。

  • destination-atop: 在源图象顶部显现目的图象。源图象以外的目的图象部份不会被显现。

  • destination-in: 在源图象中显现目的图象。只要源图象内的目的图象部份会被显现,源图象是通明的。

  • destination-out: 在源图象外显现目的图象。只要源图象外的目的图象部份会被显现,源图象是通明的。

  • lighter: 显现源图象 + 目的图象。

  • copy: 显现源图象。疏忽目的图象。

  • source-over: 运用异或操纵对源图象与目的图象举行组合。

如将第二个图片放在第一个图片下方:

window.onload = function() {
    var drawing = document.getElementById("drawing");
    var imgInput = document.images[0];
    //搜检兼容性
    if (drawing.getContext) {
        var context = drawing.getContext("2d");
        //绘制原始图象
        context.fillStyle = "red";
        context.fillRect(150, 20, 75, 50);

        context.globalCompositeOperation = "destination-over";
        
        context.fillStyle = "blue";
        context.fillRect(180, 50, 75, 50);
    }
};
    原文作者:JS菌
    原文地址: https://segmentfault.com/a/1190000004387471
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞