canvas 2D 繪圖(填充识脆、描邊设联、路徑、文本)

canvas 2D 繪圖上下文

????2D 繪圖上下文提供了繪制2D圖形的方法存璃,包括矩形仑荐、弧形和路徑。2D上下文的坐標(biāo)原點(diǎn)(0纵东,0)在<canvs>
元素的左上角粘招。所有的坐標(biāo)值都相對于該點(diǎn)計算,因此x坐標(biāo)向右增長偎球,y坐標(biāo)向下增長洒扎。默認(rèn)情況下, width和height表示兩個方向上像素的最大值衰絮。

填充和描邊

????2D上下文有兩個基本繪制操作袍冷;填充和描邊。填充以指定樣式(顏色猫牡、漸變或圖像)自動填充形狀胡诗,而描邊只為圖形邊界著色。大多數(shù)的2D上下文操作有填充和描邊的變體淌友,顯示效果取決于兩個屬性
fillStyle和strokeStyle煌恢。

????這兩個屬性可以是字符串、漸變對象或圖案對象震庭,默認(rèn)值都為“#000000”.字符串可以表示顏色值瑰抵,可以是CSS支持的任意格式:名稱、十六進(jìn)制代碼器联、rgb二汛、rgba、hsl或hsla拨拓。比如

let canvas = document.getElementById('canvas');
canvas.width = 1920;
canvas.height = 1080;
if (canvas.getContext) {
    let context = canvas.getContext('2d');

    context.beginPath();
    context.moveTo(100, 100);
    context.lineTo(400, 100);
    context.lineTo(400, 400);
    // context.lineTo(100, 400);
    context.closePath();

    context.width = 2;

    context.fillStyle = '#aaa';
    context.strokeStyle = 'red';

    context.fill();
    context.stroke();
}

在這里設(shè)置之后肴颊,所有與描邊和填充相關(guān)的操作都會使用這兩種樣式,除非再次修改千元。這兩個屬性也可以是漸變或圖案苫昌。

繪制矩形

????矩形是唯一一個可以在2D繪圖上下文種hi之的形狀。與繪制矩形相關(guān)的方法有3個:fillRect()幸海、strokeRect()祟身、clearRect()。這些方法都接受4個參數(shù):矩形x坐標(biāo)物独、
矩形y坐標(biāo)袜硫、矩形寬度和矩形高度。這幾個參數(shù)的單位都是像素挡篓。 ????fillRect()方法用于以指定顏色在畫布上繪制并填充矩形婉陷。填充的顏色使用fillStyle屬性指定。

let canvas = document.getElementById('canvas');
canvas.width = 200;
canvas.height = 200;
// 確保瀏覽器支持<canvas>
if (canvas.getContext) {
    let context = canvas.getContext("2d");
    /*
    * 引自 MDN 文檔
    */
    // 繪制紅色矩形
    context.fillStyle = "#ff0000";
    context.fillRect(10, 10, 50, 50);
    // 繪制半透明藍(lán)色矩形
    context.fillStyle = "rgba(0,0,255,0.5)";
    context.fillRect(30, 30, 50, 50);
}

????以上代碼先將fillStyle設(shè)置為紅色并在坐標(biāo)點(diǎn)(10,10)繪制了一個寬高均為50像素的矩形官研。接著秽澳,使用rgba()格式將fillStyle設(shè)置為半透明藍(lán)色,并繪制了另一個
與第一個部分重疊的矩形戏羽。結(jié)果就是可以透過藍(lán)色矩形看到紅色矩形

圖 1

????stroke()方法使用通過strokeStyle屬性指定的顏色繪制矩形輪廓担神。下面是一個例子:

let canvas = document.getElementById('canvas');
canvas.width = 200;
canvas.height = 200;
// 確保瀏覽器支持<canvas>
if (canvas.getContext) {
    let context = canvas.getContext("2d");
    /*
    * 引自 MDN 文檔
    */
    // 繪制紅色輪廓的矩形
    context.strokeStyle = "#ff0000";
    context.strokeRect(10, 10, 50, 50);
    // 繪制半透明藍(lán)色輪廓的矩形
    context.strokeStyle = "rgba(0,0,255,0.5)";
    context.strokeRect(30, 30, 50, 50);
}

????以上代碼同樣繪制了兩個重疊的矩形,不過只有輪廓始花,而不是實心的

圖 2

注意:描邊寬度由lineWidth屬性控制妄讯,它可以是任意整數(shù)值。類似地酷宵,lineCap屬性控制線條端點(diǎn)的形狀["butt"(平頭)亥贸、"round"(出圓頭)或"square"(出方頭)],
而lineJoin屬性控制線條交點(diǎn)的形狀["round"(圓轉(zhuǎn))浇垦、"bevel"(取平)或"miter"(出尖)]炕置。

????使用clearRect() 方法可以擦除畫布中的某個區(qū)域。該方法用于把繪圖上下文中的某個區(qū)域變透明男韧。通過先繪制形狀再擦除指定區(qū)域朴摊,可以創(chuàng)建出有趣的效果,比如從已有矩形
中開個孔煌抒。來看下面的例子:

let canvas = document.getElementById('canvas');
canvas.width = 200;
canvas.height = 200;
// 確保瀏覽器支持<canvas>
if (canvas.getContext) {
    let context = canvas.getContext("2d");
    /*
    * 引自 MDN 文檔
    */
    // 繪制紅色矩形
    context.fillStyle = "#ff0000";
    context.fillRect(10, 10, 50, 50);
    // 繪制半透明藍(lán)色矩形
    context.fillStyle = "rgba(0,0,255,0.5)";
    context.fillRect(30, 30, 50, 50);

    //在前兩個矩形重疊的區(qū)域擦除一個矩形區(qū)域
    context.clearRect(40, 40, 10, 10);
}

????以上代碼在兩個矩形重疊的區(qū)域擦除了一個小矩形仍劈,如下圖所示:

圖 3

繪制路徑

????2D繪制上下文支持很多在畫布上繪制路徑的方法。通過路徑可以創(chuàng)建復(fù)雜的形狀和線條寡壮。要繪制路徑贩疙,必須首先調(diào)用beginPath()方法 以表示要開始繪制新路徑。然后况既,再調(diào)用下列方法來繪制路徑这溅。

  • arc(x,y,radius,startAngle,endAngle,counterclockwise): 以坐標(biāo)(x,y)為圓心,以radius為半徑繪制一條弧線棒仍,起始角度為startAngle悲靴,結(jié)束角度為endAngle(都是弧度)
    。最后一個 參數(shù)counterclockwise表示是否逆時針計算起始角度和結(jié)束角度(默認(rèn)為順時針)

  • arcTo(x1,y1,x2,y2,radius): 以給定半徑radius莫其,經(jīng)由(x1,y1)繪制一條從上一點(diǎn)到(x2,y2)的弧線癞尚。

  • bezierCurveTo(c1x,c1y,c2x,c2y,x,y): 以(c1x,c1y)和(c2x,c2y)為控制點(diǎn)耸三,繪制一條從上一點(diǎn)到(x,y)的弧線(三次貝塞爾曲線)。

  • lineTo(x,y): 繪制一條從上一點(diǎn)到(x,y)的直線浇揩。

  • moveTo(x,y): 不繪制線條仪壮,只把繪制光標(biāo)移動到(x,y).

  • quadraticCurveTo(cx,cy,x,y): 以(cx,cy)為控制點(diǎn),繪制一條從上一點(diǎn)到(x,y)的弧線(二次貝塞爾曲線)

  • rect(x,y,width,height): 給定寬度和高度在坐標(biāo)點(diǎn)(x,y)繪制一個矩形胳徽。這個方法與strokeRect()和fillRect()的區(qū)別在于积锅,它創(chuàng)建的是一條路徑,而不是獨(dú)立的圖形养盗。

????創(chuàng)建路徑之后缚陷,可以使用closePath()方法來繪制一條返回起點(diǎn)的線。如果路徑已經(jīng)完成往核,則既可以指定fillStyle屬性并調(diào)用fill()方法
來填充路徑箫爷,也可以指定strokeStyle屬性并調(diào)用stroke()方法來描畫路徑,還可以調(diào)用clip()方法基于已有路徑創(chuàng)建一個剪切區(qū)域铆铆。

????下面這個例子使用前面提到的方法繪制了一個不帶數(shù)字的表盤:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
            <title>18.3.3 繪制路徑</title>
            <style>
                #canvas {
                /*border: 1px solid #aaaaaa;*/
                display: block;
                margin: 50px auto;
            }
            </style>
    </head>
    <body>
        <canvas id="canvas"></canvas>
        <script>
            const canvas = document.getElementById('canvas');
            canvas.width = 200;
            canvas.height = 200;
            if (canvas.getContext) {
            let context = canvas.getContext('2d');
            //創(chuàng)建路徑
            context.beginPath();

            //繪制外圓
            context.arc(100, 100, 99, 0, 2 * Math.PI, false);

            //繪制內(nèi)圓
            context.moveTo(194, 100);
            context.arc(100, 100, 94, 0, 2 * Math.PI);

            //繪制分針
            context.moveTo(100, 100);
            context.lineTo(100, 15);

            //繪制時針
            context.moveTo(100, 100);
            context.lineTo(35, 100);
            //描畫路徑
            context.stroke();
        }
        </script>

    </body>
</html>

????這個例子使用arc()繪制了兩個圓形蝶缀,一個外圓和一個內(nèi)圓,以構(gòu)成表盤的邊框薄货。外圓半徑99像素翁都,原點(diǎn)為(100,100),也就是畫布的中心。要繪制完整的圓形谅猾,必須從 0 弧度繪制到 2Π 弧度(
使用數(shù)學(xué)常量Math.PI)柄慰。而在繪制內(nèi)圓之前,必須先把路徑移動到內(nèi)圓上的一點(diǎn)税娜,以避免繪制出多余的線條坐搔。第二次調(diào)用arc()時使用了稍小一點(diǎn)的半徑,以呈現(xiàn)邊框效果敬矩。然后概行,在組合運(yùn)用moveTo()
和lineTo()分別繪制分針和時針,最后一步是調(diào)用stroke(),得到如下圖所示的圖像弧岳。

圖 4

????路徑是2D上下文的主要繪圖機(jī)制凳忙,為繪制結(jié)果提供了很多控制。因為路徑經(jīng)常被使用禽炬,所以也有一個isPointInPath()方法涧卵,接受x軸和y軸作為參數(shù)。這個方法用于確定指定的點(diǎn)是否在路徑上腹尖,
可以在關(guān)閉路徑前隨時調(diào)用柳恐,比如:

let context = canvas.getContext('2d');
//創(chuàng)建路徑
context.beginPath();

//繪制外圓
context.arc(100, 100, 99, 0, 2 * Math.PI, false);

//繪制內(nèi)圓
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI);

//繪制分針
context.moveTo(100, 100);
context.lineTo(100, 15);

//繪制時針
context.moveTo(100, 100);
context.lineTo(35, 100);

if (context.isPointInPath(100, 100)) {
    alert("Point (100,100) is in the path.")
}

//描畫路徑
context.stroke();

???? 2D上下文的路徑API非常可靠,可用于創(chuàng)建設(shè)計各種填充樣式乐设、描述樣式的復(fù)雜圖像讼庇。

繪制文本

????文本和圖像混合也是常見的繪圖需求,因此2D繪圖上下文還提供了繪制文本的方法伤提,即fillText()和strokeText()巫俺。這兩個方法都接受4個參數(shù):要繪制的字符串认烁、
x坐標(biāo)肿男、y坐標(biāo)和可選的最大像素寬度。并且却嗡,這兩個方法最終繪制的結(jié)果都取決于以下3個屬性舶沛。

  • font:以CSS語法指定的字體樣式、大小窗价、字體族等如庭,比如 "10px Arial"。

  • textAlign: 指定文本的對齊方式撼港,可能的值包括 "start" 坪它、"end" 、"left"帝牡、 "right" 和 "center"往毡。推薦使用 "start" 和 "end" ,不使用 "left" 和 "right"
    靶溜,因為前者無論在從左到從右 書寫的語言還是從右到左書寫的語言中含義都更明確开瞭。

  • textBaseLine: 指定文本的基線,可能的值包括 "top"罩息、 "handing" 嗤详、"middle"、 "alphabetic"瓷炮、 "ideographic" 和 "bottom"葱色。

????這些屬性都有相應(yīng)的默認(rèn)值,因此沒必要每次繪制文本時都設(shè)置它們娘香。fillText()方法使用fillStyle屬性繪制文本苍狰,而strokeText()方法使用strokeStyle屬性
。通常fillText()方法是使用最多的茅主,因為它模擬了在網(wǎng)頁中渲染文本舞痰。例如,在表盤頂部繪制數(shù)字 "12":

context.font = 'bold 14px Arial';
context.textAlign = "center";
context.textBaseline = 'middle';
context.fillText('12', 100, 15);

????結(jié)果就得到了如下圖所示的圖像:


圖 5

????因為把textAlign設(shè)置為了"center",把textBaseLine設(shè)置為了 "middle"诀姚,所以(100,20)表示文本水平和垂直中心點(diǎn)的坐標(biāo)响牛。如果textAlign是"
start", 那么x坐標(biāo)在從左到右書寫的語言中表示文本的左側(cè)坐標(biāo),而"end"會讓x坐標(biāo)在從左到右書寫的語言中表示文本的右側(cè)坐標(biāo)。例如:

//正常
context.font = 'bold 14px Arial';
context.textAlign = "center";
context.textBaseline = 'middle';
context.fillText('12', 100, 15);

//與開頭對齊
context.textAlign = 'start';
context.fillText('12', 100, 40);
//與末尾對齊
context.textAlign = 'end';
context.fillText('12', 100, 60);
圖 6

????字符串 "12" 被繪制了3次呀打,每次使用的坐標(biāo)都一樣矢赁,但textAlign值不同。為了讓每個字符串不至于重疊贬丛,每次繪制的y坐標(biāo)都會設(shè)置的大一些撩银。結(jié)果就是上圖所示的圖像。

????因為表盤中垂直的線條是居中的豺憔,所以文本的對齊方式就一目了然了额获。類似地,通過修改textBaseline屬性恭应,可以改變文本的垂直對齊方式抄邀。 比如,設(shè)置為"top"
意味著y坐標(biāo)表示文本頂部昼榛,bottom表示文本底部境肾,"hanging"、"alphabetic"胆屿、"ideographic"分別引用字體中特定的基準(zhǔn)點(diǎn)奥喻。

????由于繪制文本很復(fù)雜,特別是想把文本繪制到特定區(qū)域的時候非迹,因此2D上下文提供了 用于輔助確定文本大小的measureText()方法环鲤。這個方法接受一個參數(shù),
即要繪制的文本彻秆,然后返回一個TextMetrics對象楔绞,這個返回的對象目前只有一個屬性width,不過將來應(yīng)該會增加更多的度量指標(biāo)唇兑。

????measureText()方法使用font酒朵、textAlign和textBaseline屬性當(dāng)前的值計算繪制指定文本后的大小。例如扎附,假設(shè)要把文本"Hello world蔫耽!"
放到一個140像素寬的矩形 中,可以使用以下代碼留夜,從100像素的字體大小開始計算匙铡,不斷遞減,知道文本大小合適:


let fontSize = 100;
context.font = fontSize + "px Arial";
while (context.measureText("Hello World!").width > 140) {
  fontSize--;
  context.font = fontSize + "px Arial";
}
console.log(fontSize)
context.fillText("Hello World!", 100, 25);
context.fillText("Font size is " + fontSize + "px", 100, 50,1000);

圖 7

????fillText()和strokeText()方法還有第四個參數(shù)碍粥,即文本的最大寬度鳖眼。這個參數(shù)是可選的,如果調(diào)用fillText和strokeText()時提供了此參數(shù)嚼摩,但要
繪制的字符串超過了最大寬度限制钦讳,則文本會以正確的高度繪制矿瘦,這時候字符會被水平壓縮,以達(dá)到限定寬度愿卒。

????繪制文本是一項比較復(fù)雜的操作缚去,因此支持<canvas>元素的瀏覽器不一定全部實現(xiàn)了相關(guān)的文本繪制API。

變換

????上下文變換可以操作繪制在畫布上的圖像琼开。2D繪圖上下文支持所有常見的繪制變換易结。 ????以下方法可用于繪制上下文的變換矩陣

  • rotate(angle): 圍繞原點(diǎn)把圖像旋轉(zhuǎn)angle弧度
  • scale(scaleX,scaleY):通過在x軸乘以scaleX、在y軸乘以scaleY來縮放圖像柜候。scaleX和scaleY的默認(rèn)值都是1.0
  • translate(x,y): 把原點(diǎn)移動到(x,y)搞动。執(zhí)行這個操作后,坐標(biāo)(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): 把矩陣重置為默認(rèn)值滋尉,再以傳入的參數(shù)調(diào)用transform()。

????變換可以簡單飞主,也可以復(fù)雜。例如高诺,在前面繪制表盤的例子中碌识,如果把坐標(biāo)原點(diǎn)移動到表盤中心,那再繪制表針就非常簡單那了:

    (function () {
    const canvas = document.getElementById('canvas');
    canvas.width = 200;
    canvas.height = 200;
    if (canvas.getContext) {
        let context = canvas.getContext('2d');

        //創(chuàng)建路徑
        context.beginPath();

        //繪制外圓
        context.arc(100, 100, 99, 0, 2 * Math.PI, false);

        //繪制內(nèi)圓
        context.moveTo(194, 100);
        context.arc(100, 100, 94, 0, 2 * Math.PI, false);

        //移動原點(diǎn)到表盤中心
        context.translate(100, 100);

        //繪制分針
        context.moveTo(0, 0);
        context.lineTo(0, -85);

        //繪制時針
        context.moveTo(0, 0);
        context.lineTo(-80, 0);

        //描畫路徑
        context.stroke();
    }
})();
圖8

????把原點(diǎn)移動到(100,100)虱而,也就是表盤的中心后筏餐,要繪制表針只需要簡單的數(shù)學(xué)計算即可。這是因為所有計算都是基于(100,100)了牡拇。當(dāng)然魁瞪,也可以使用rotate()方法來轉(zhuǎn)動指針:

(function () {
    const canvas = document.getElementById('canvas');
    canvas.width = 200;
    canvas.height = 200;
    if (canvas.getContext) {
        let context = canvas.getContext('2d');

        //創(chuàng)建路徑
        context.beginPath();

        //繪制外圓
        context.arc(100, 100, 99, 0, 2 * Math.PI, false);

        //繪制內(nèi)圓
        context.moveTo(194, 100);
        context.arc(100, 100, 94, 0, 2 * Math.PI, false);

        //移動原點(diǎn)到表盤中心
        context.translate(100, 100);

        //旋轉(zhuǎn)表針
        context.rotate(1);

        //繪制分針
        context.moveTo(0, 0);
        context.lineTo(0, -85);

        //繪制時針
        context.moveTo(0, 0);
        context.lineTo(-80, 0);

        //描畫路徑
        context.stroke();
    }
})();

????因為原點(diǎn)已經(jīng)移動到表盤中心,所以旋轉(zhuǎn)就是以該點(diǎn)為圓心的惠呼。這相當(dāng)于把表針一頭固定在表盤中心导俘,然后向右撥了一個弧度。結(jié)果如圖18-8所示剔蹋。

圖 9

????所有這些變換旅薄,包括fillStyle和strokeStyle屬性,會一直保留在上下文中泣崩,直到再次修改它們少梁。雖然沒有辦法明確地將所有值都重置為默認(rèn)值,但是有兩個方法可以幫我們跟蹤變化矫付,可以調(diào)用save()
方法凯沪。 調(diào)用這個方法后,所有這一時刻的設(shè)置會被暫時放到一個暫存棧中买优。保存之后妨马,可以繼續(xù)修改上下文樟遣。而在需要恢復(fù)之前的上下文時,可以調(diào)用restore()中的方法身笤。這個方法會從暫存棧中取出并恢復(fù)之前保存的設(shè)置豹悬。多次調(diào)用save()方法可以
在暫存棧中存儲多套設(shè)置,然后通過restore()可以系統(tǒng)地恢復(fù)液荸。下面來看一個例子:

    (function () {
    const canvas = document.getElementById('canvas');
    canvas.width = 200;
    canvas.height = 200;
    if (canvas.getContext) {
        let context = canvas.getContext('2d');

        context.fillStyle = '#ff0000';
        context.save();

        context.fillStyle = '#00ff00';
        context.translate(100, 100);
        context.save();

        context.fillStyle = '#0000ff';
        //在(100,100)繪制藍(lán)色矩形
        context.fillRect(0, 0, 100, 200);

        context.restore();
        //在(100,100)繪制綠色矩形
        context.fillRect(10, 10, 100, 200);

        context.restore();
        //在(0,0)繪制紅色矩形
        context.fillRect(0, 0, 100, 200);
    }
})();
圖 10

????以上代碼先將fillStyle設(shè)置為紅色瞻佛,然后調(diào)用save()。接著娇钱,將fillStyle修改為綠色伤柄,坐標(biāo)移動到(100,100),并再次調(diào)用save()
,保存設(shè)置。隨后文搂,將fillStyle屬性設(shè)置為藍(lán)色并繪制一個矩形适刀。 因為此時坐標(biāo)被移動了,所以繪制矩形的坐標(biāo)實際上是(100,100)煤蹭。在調(diào)用restore()之后笔喉,fillStyle恢復(fù)為綠色,因此這一次
繪制的矩形是綠色的硝皂。而繪制的矩形的坐標(biāo)是(100,100),因為變換仍然在起作用常挚。再次調(diào)用restore()之后,變化被移除稽物,fillStyle也恢復(fù)為紅色奄毡。繪制最后一個矩形的坐標(biāo)變成了(0,0)
????注意,save()方法只保存應(yīng)用到繪圖上下文的設(shè)置和變換贝或,不保存繪圖上下文的內(nèi)容吼过。

繪制圖像

????2D繪圖上下文內(nèi)置支持操作圖像。如果想把現(xiàn)有圖像繪制到畫布上咪奖,可以使用drawImage()方法盗忱。
這個方法可以接受3組不同的參數(shù),并產(chǎn)生不同的結(jié)果赡艰。最簡單的調(diào)用時傳入一個HTML的<img>元素售淡,以及表示繪制目標(biāo)的x和y坐標(biāo),結(jié)果是把圖像繪制到指定位置慷垮。比如:

let image = document.images[0];
//表示在坐標(biāo)(0,0)的位置繪制
context.drawImage(image, 0, 0);

????以上代碼獲取了文本中的第一個圖像揖闸,然后在畫布上的坐標(biāo)(0,0)處將它繪制了出來。繪制出來的圖像與原來的圖像一樣大料身。如果想改變所繪制圖像的大小
可以再傳入另外一個參數(shù):目標(biāo)寬度和目標(biāo)高度汤纸。這里的縮放只影響繪制的圖像,不影響上下文的變換矩陣芹血。比如下面的例子:

let image = document.images[0];
//表示在坐標(biāo)(0,0)的位置繪制
context.drawImage(image, 0, 0贮泞,1920, 1080
)
;

????執(zhí)行之后楞慈,圖像會被縮放到1920像素寬、1080像素高啃擦。
????還可以只把圖像繪制到上下文中的一個區(qū)域囊蓝。此時,需要給drawImage()提供9個參數(shù):要繪制的圖像令蛉、源圖像x坐標(biāo)聚霜、源圖像y坐標(biāo)、源圖像寬度珠叔、源圖像高度
目標(biāo)區(qū)域x坐標(biāo)蝎宇、目標(biāo)區(qū)域y坐標(biāo)、目標(biāo)區(qū)域?qū)挾群湍繕?biāo)區(qū)域高度祷安。這個重載后的drawImage()方法可以實現(xiàn)最大限制的控制姥芥,

context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);

????最終,原始圖像中只有一部分會繪制到畫布上汇鞭。這一部分從(0,10)開始凉唐,50像素寬、50像素高虱咧。而繪制到畫布上時熊榛,會從(0,100)開始,變成40像素寬腕巡、60像素高。
????第一個參數(shù)除了可以是HTML的<img>元素血筑,還可以是另一個<canvas>元素绘沉,這樣就會把另一個畫布的內(nèi)容繪制到當(dāng)前畫布上。
????結(jié)合其他一些方法豺总,drawImage()方法可以方便地實現(xiàn)常見的圖像操作车伞。操作的結(jié)果可以使用toDataURL()方法獲取

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市喻喳,隨后出現(xiàn)的幾起案子另玖,更是在濱河造成了極大的恐慌,老刑警劉巖表伦,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谦去,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹦哼,警方通過查閱死者的電腦和手機(jī)鳄哭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纲熏,“玉大人妆丘,你說我怎么就攤上這事锄俄。” “怎么了勺拣?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵奶赠,是天一觀的道長。 經(jīng)常有香客問我药有,道長毅戈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任塑猖,我火速辦了婚禮竹祷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羊苟。我一直安慰自己塑陵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布蜡励。 她就那樣靜靜地躺著令花,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凉倚。 梳的紋絲不亂的頭發(fā)上兼都,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音稽寒,去河邊找鬼扮碧。 笑死,一個胖子當(dāng)著我的面吹牛杏糙,可吹牛的內(nèi)容都是我干的慎王。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼宏侍,長吁一口氣:“原來是場噩夢啊……” “哼赖淤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谅河,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤咱旱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绷耍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吐限,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年锨天,在試婚紗的時候發(fā)現(xiàn)自己被綠了毯盈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡病袄,死狀恐怖搂赋,靈堂內(nèi)的尸體忽然破棺而出赘阀,到底是詐尸還是另有隱情,我是刑警寧澤脑奠,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布基公,位于F島的核電站,受9級特大地震影響宋欺,放射性物質(zhì)發(fā)生泄漏轰豆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一齿诞、第九天 我趴在偏房一處隱蔽的房頂上張望酸休。 院中可真熱鬧,春花似錦祷杈、人聲如沸胸墙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惊楼。三九已至校哎,卻和暖如春琅轧,著一層夾襖步出監(jiān)牢的瞬間猎提,已是汗流浹背厌殉。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踩叭,地道東北人磕潮。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像容贝,于是被迫代替她去往敵國和親揉抵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容