日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式

發布時間:2024/3/24 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

漸變

線性漸變

在一條直線上進行漸變

  • 調用createLinearGradient()方法創建一個linearGradient對象
  • var gnt = cxt.createLinearGradient(x1, y1, x2, y2);
    • x1、y1表示漸變色開始點的坐標
    • x2、y2表示漸變色結束點的坐標
  • 添加漸變(開始)
  • gnt.addColorStop(value1,color1);
    • value1 漸變開始的位置,取值 0~1
    • color1 漸變開始的顏色
  • 添加漸變(結束)
  • gnt.addColorStop(value2,color2);
    • value2 漸變結束的位置,取值 0~1
    • color2 漸變結束的顏色

    第2和第3步可以反復多次添加多個漸變,每次漸變都以上一個漸變的結束位置為開始位置

  • 填充漸變
  • cxt.fillStyle = gnt; cxt.fill();

    fill()可以改為fillRect()或fillText()。其中fillRect()表示矩形漸變,fillText()表示文字漸變。

    var gnt = cxt.createLinearGradient(0,150, 200, 150);gnt.addColorStop(0, "HotPink");gnt.addColorStop(1, "white");cxt.fillStyle = gnt;cxt.fillRect(0, 0, 200, 150);

    var text = "綠葉學習網";cxt.font = "bold 50px 微軟雅黑";var gnt = cxt.createLinearGradient(0, 75, 200, 75);gnt.addColorStop(0, "HotPink");gnt.addColorStop(1, "LightSkyBlue");cxt.fillStyle = gnt;cxt.fillText(text, 10, 90);

    徑向漸變(用得少)

    徑向漸變,是一種從起點到終點、顏色從內到外進行的圓形漸變(從中間向外拉,像圓一樣)。徑向漸變是圓形漸變或橢圓形漸變,顏色不再沿著一條直線漸變,而是從一個起點向所有方向漸變。

  • 調用createLinearGradient()方法創建一個radialGradient對象
  • var gnt = cxt.createRadialGradient(x1,y1,r1,x2,y2,r2);
    • (x1,y1)表示漸變開始圓心的坐標,r1表示漸變開始圓心的半徑。
    • (x2,y2)表示漸變結束圓心的坐標,r2表示漸變結束圓的半徑。

      當起點圓與終點圓的圓心坐標相同時,會有一種圓形漸變的效果
  • 添加漸變(開始)
  • gnt.addColorStop(value1,color1);
    • value1 漸變開始的位置,取值 0~1
    • color1 漸變開始的顏色
  • 添加漸變(結束)
  • gnt.addColorStop(value2,color2);
    • value2 漸變結束的位置,取值 0~1
    • color2 漸變結束的顏色

    第2和第3步可以反復多次添加多個漸變,每次漸變都以上一個漸變的結束位置為開始位置

  • 填充漸變
  • cxt.fillStyle = gnt; cxt.fill();

    fill()可以改為fillRect()或fillText()。其中fillRect()表示矩形漸變,fillText()表示文字漸變。

    //畫圓cxt.beginPath();cxt.arc(80, 80, 50, 0, Math.PI * 2, true);cxt.closePath();//漸變var gnt = cxt.createRadialGradient(100, 60, 10, 80, 80, 50);gnt.addColorStop(0, "white");gnt.addColorStop(0.9, "orange");gnt.addColorStop(1, "rgba(0,0,0,0)");//填充cxt.fillStyle = gnt;cxt.fill();

    gradient = cxt.createRadialGradient(60, 60, 0, 60, 60, 60);gradient.addColorStop("0", "magenta");gradient.addColorStop("0.25", "blue");gradient.addColorStop("0.50", "green");gradient.addColorStop("0.75", "yellow");gradient.addColorStop("1.0", "HotPink");cxt.fillStyle = gradient;cxt.fillRect(0, 0, 120, 120);

    var i = 0;setInterval(function () {gradient = cxt.createRadialGradient(60, 60, 0, 60, 60, 60);gradient.addColorStop(i * 0, "magenta");gradient.addColorStop(i * 0.25, "blue");gradient.addColorStop(i * 0.50, "green");gradient.addColorStop(i * 0.75, "yellow");gradient.addColorStop(i * 1.0, "HotPink");cxt.fillStyle = gradient;i = i + 0.1;if (i >= 1) { //超過顏色點值后,自動歸0i = 0;}cxt.fillRect(0, 0, 120, 120);}, 50);

    陰影

    屬性

    說明

    shadowOffsetX

    陰影與圖形的水平距離,默認值為0。大于0時向右偏移,小于0時向左偏移

    shadowOffsetY

    陰影與圖形的垂直距離,默認值為0。大于0時向下偏移,小于0時向上偏移

    shadowColor

    陰影的顏色,默認值為黑色

    shadowBlur

    陰影的模糊值,默認值為0。該值越大,模糊度越強;該值越小,模糊度越弱

    Canvas陰影屬性使用的也是W3C坐標系,y 軸向下

    //設置左上方向的陰影cxt.shadowOffsetX = -5;cxt.shadowOffsetY = -5;cxt.shadowColor = "LightSkyBlue ";cxt.shadowBlur = 1;cxt.fillStyle = "HotPink";cxt.fillRect(30, 30, 50, 50);//設置右下方向的陰影cxt.shadowOffsetX = 5;cxt.shadowOffsetY = 5;cxt.shadowColor = "LightSkyBlue ";cxt.shadowBlur = 10;cxt.fillStyle = "HotPink";cxt.fillRect(100, 30, 50, 50);

    //定義文字var text = "綠葉學習網";cxt.font = "bold 60px 微軟雅黑";//定義陰影cxt.shadowOffsetX = 5;cxt.shadowOffsetY = 5;cxt.shadowColor = "LightSkyBlue ";cxt.shadowBlur = 10;//填充文字cxt.fillStyle = "HotPink";cxt.fillText(text, 10, 90);

    //創建image對象var image = new Image();image.src = "images/princess.png";image.onload = function () {//定義陰影cxt.shadowOffsetX = 5;cxt.shadowOffsetY = 5;cxt.shadowColor = "HotPink";cxt.shadowBlur = 10;cxt.fillRect(40, 15, 120, 120);cxt.drawImage(image, 40, 15);}


    四個方向的陰影效果,只需要shadowOffsetX和shadowOffsetY這兩個屬性的值都定義為0就可以了。

    //創建image對象var image = new Image();image.src = "images/princess.png";image.onload = function () {//定義陰影cxt.shadowOffsetX = 0;cxt.shadowOffsetY = 0;cxt.shadowColor = "HotPink";cxt.shadowBlur = 10;cxt.fillRect(40, 15, 120, 120);cxt.drawImage(image, 40, 15);}

    路徑

    方法

    說明

    beginPath()

    開始一條新的路徑

    closePath()

    關閉當前路徑

    isPointInPath()

    判斷某一個點是否存在于當前路徑內

    beginPath()

    cxt.beginPath();

    用于開始一個新路徑(同時也是結束上一個路徑),剛開始繪圖時,其實都默認執行了一次 beginPath() 開始了一個新路徑,直到再次遇到 beginPath() 才會結束默認創建的路徑,而開始一段新路徑。

    Canvas基于“狀態”繪制圖形。每一次繪制(stroke()或fill()),Canvas會檢測整個程序定義的所有狀態,這些狀態包括strokeStyle、fillStyle、lineWidth等。當一個狀態值沒有被改變時,Canvas就一直使用最初的值,當一個狀態值被改變時,需要分兩種情況考慮。

    (1)如果使用beginPath()開始一個新的路徑,則不同路徑使用不同的值。

    (2)如果沒有使用beginPath()開始一個新的路徑,則后面的值會覆蓋前面的值(后來者居上原則)。

    cxt.lineWidth = 5;//第1條直線cxt.moveTo(50, 40);cxt.lineTo(150, 40);cxt.strokeStyle = "red";cxt.stroke();//第2條直線cxt.moveTo(50, 80);cxt.lineTo(150, 80);cxt.strokeStyle = "green";cxt.stroke();//第3條直線cxt.moveTo(50, 120);cxt.lineTo(150, 120);cxt.strokeStyle = "blue";cxt.stroke();


    三條直線都屬于同一個路徑,所以cxt.strokeStyle=‘green’;會覆蓋cxt.strokeStyle=‘red’;,然后cxt.strokeStyle=‘blue’;會覆蓋cxt.strokeStyle=‘green’;。因此strokeStyle屬性最終取值為blue,即三條直線都是blue。

    cxt.lineWidth = 5;//第1條直線cxt.beginPath();cxt.moveTo(50, 40);cxt.lineTo(150, 40);cxt.strokeStyle = "red";cxt.stroke();//第2條直線cxt.beginPath();cxt.moveTo(50, 80);cxt.lineTo(150, 80);cxt.strokeStyle = "green";cxt.stroke();//第3條直線cxt.beginPath();cxt.moveTo(50, 120);cxt.lineTo(150, 120);cxt.strokeStyle = "blue";cxt.stroke();


    使用beginPath()后,三條直線將位于不同的路徑中。因此,不同路徑中定義的狀態不會像上一個例子那樣發生覆蓋。

    判斷是否屬于同一路徑的標準是:是否使用了beginPath(),而不是視覺上是否有首尾連線。

    Canvas中的繪制方法如stroke()、fill()等,都是以“之前最近的beginPath()”后面所有定義的狀態為基礎進行繪制的。

    closePath()

    cxt.closePath();

    用于關閉路徑,即將同一個路徑的起點與終點連接起來,使其成為一個封閉的圖形。
    常用于繪制多邊形的最后一步。

    如果Canvas只有一條線段的話,那么closePath()方法就什么都不做。

    cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true);cxt.stroke();cxt.closePath();

    cxt.lineWidth = 10;cxt.strokeStyle = "HotPink";cxt.moveTo(40, 60);cxt.lineTo(100, 60);cxt.lineTo(100, 30);cxt.lineTo(150, 75);cxt.lineTo(100, 120);cxt.lineTo(100, 90);cxt.lineTo(40, 90);cxt.lineTo(40, 60);cxt.stroke();


    將lineWidth定義得足夠大(10px)時,如果使用lineTo()方法來關閉圖形,會有一個如圖所示的“缺口”小問題。有兩種方法可以解決:

  • 定義lineCap屬性值為square。
  • 在stroke()方法之前使用closePath()關閉圖形(推薦)
  • isPointInPath()

    cxt.isPointInPath(x , y);

    用于判斷點 x,y 是否在當前路徑中,若在返回true,否則返回false,僅對 rect()方法有效,對 strokeRect() 和 fillRect() 無效。

    cxt.strokeStyle = "HotPink";cxt.rect(50, 50, 80, 80);cxt.stroke();if (cxt.isPointInPath(100, 50)) {alert("點(100,100)存在于當前路徑中");}

    cxt.moveTo(50, 50);cxt.lineTo(150, 50);cxt.stroke();if (cxt.isPointInPath(100, 50)) {alert("點(50,100)存在于當前路徑中");}

    上面代碼只在IE瀏覽器中運行中有效果,但是在Google瀏覽器和Firefox中不會彈出對話框。實際上,當我們想要使用isPointInPath()方法判斷某個點是否位于一條直線上時,在Goole和Firefox瀏覽器中都是無法實現的。不過可以使用isPointInPath()方法判斷某個點是否位于一個圖形(如矩形、圓形等)上面。

    狀態

    Canvas基于“狀態”來繪制圖形。每一次繪制(stroke()或fill()),Canvas會檢測整個程序定義的所有狀態,這些狀態包括strokeStyle、fillStyle、lineWidth等。當一個狀態值沒有被改變時,Canvas就會一直使用最初的值。當一個狀態值被改變時,分兩種情況考慮:

    (1)如果使用beginPath()開始一個新的路徑,則不同路徑使用不同的值。

    (2)如果沒有使用beginPath()開始一個新的路徑,則后面的值會覆蓋前面的值(后來者居上原則)。

    狀態的保存和恢復

    Canvas提供了兩個操作狀態的方法:

    • save() 保存“當前狀態”,如剪切狀態、變換狀態和繪圖狀態(各種繪圖樣式屬性),不能保存路徑狀態(開始新的路徑,只有beginPath()一個方法),也不能保存圖形(Canvas只有當前一個上下文環境,如果想要恢復圖形,就只能清空畫布再重繪。)。
    • restore() 恢復“之前保存的狀態”。

    save()和restore()一般情況下都是成對配合使用,使用場景如下:

    (1)圖形或圖片裁切。
    (2)圖形或圖片變換。
    (3)以下屬性改變的時候:fillStyle、font、globalAlpha、globalCompositeOperation、lineCap、lineJoin、lineWidth、miterLimit、shadowBlur、shadowColor、shadowOffsetX、shadowOffsetY、strokeStyle、textAlign、textBaseline。

    應用一:清除剪切區域

    創建剪切區域 clip()

    創建剪切區域后,繪制的圖形都只限于這個剪切區域之內,超出剪切區域的部分不會顯示(被剪切掉了)。

    把整個畫布(Canvas)看成一個房子,clip()方法的剪切區域則可以看成一扇窗戶。即使房子再大,最終透過窗戶所能看到的空間也就只有窗戶這么大。

    cxt.clip();
  • 繪制一個基本圖形
  • 調用 clip() 創建一個剪切區域
  • clip()方法也不支持Canvas自帶的兩個方法:strokeRect()、fillRect()。如果要使用strokeRect()和fillRect(),請使用rect()方法來代替。

    //繪制一個"描邊圓",圓心為(50,50),半徑為40cxt.beginPath();cxt.arc(50, 50, 40, 0, 360 * Math.PI / 180, true);cxt.closePath();cxt.strokeStyle = "HotPink";cxt.stroke();//使用clip(),使得"描邊圓"成為一個剪切區域cxt.clip();//繪制一個"填充矩形"cxt.beginPath();cxt.fillStyle = "#66CCFF";cxt.fillRect(50, 50, 100, 80);


    若注釋掉 cxt.clip();

    清除剪切區域

    在圖形或者圖片剪切(clip())之前使用save()方法來保持當前狀態,然后在剪切(clip())之后使用restore()方法恢復之前保存的狀態。

    如果不使用save()和restore(),即便使用clearRect()方法清空畫布,后面繪制的所有圖形或圖片也都會限制在這個剪切區域內。

    //save()保存狀態cxt.save();//使用clip()方法指定一個圓形的剪切區域cxt.beginPath();cxt.arc(70, 70, 50, 0, 360 * Math.PI / 180, true);cxt.closePath();cxt.stroke();cxt.clip();//繪制一張圖片var image = new Image();image.src = "images/princess.png";image.onload = function () {cxt.drawImage(image, 10, 20);}$$("btn").onclick = function () {//restore()恢復狀態cxt.restore();//清空畫布cxt.clearRect(0, 0, cnv.width, cnv.height);//繪制一張新圖片var image = new Image();image.src = "images/Judy.png";image.onload = function () {cxt.drawImage(image, 10, 20);}}


    刪除 cxt.save()和cxt.restore() 后效果為:

    應用二:圖片/圖形的變換

    cxt.fillStyle = "HotPink";cxt.translate(30, 30);cxt.fillRect(0, 0, 100, 50);cxt.fillStyle = "LightSkyBlue ";cxt.translate(60, 60);cxt.fillRect(0, 0, 100, 50);


    藍色矩形預期坐標為 (60,60),最終效果卻是 (90,90),因為之前 translate(30, 30),整個坐標系的原點已經發生了位移變化 !

    解決方案是使用 save()和restore()來實現

    cxt.save();cxt.fillStyle = "HotPink";cxt.translate(30, 30);cxt.fillRect(0, 0, 100, 50);cxt.restore();cxt.fillStyle = "LightSkyBlue ";cxt.translate(60, 60);cxt.fillRect(0, 0, 100, 50);


    在變換操作(平移、縮放、旋轉)中,一般都是在操作之前使用save()方法保存當前狀態,其中當前狀態包括參考坐標、圖形大小等。然后再使用restore()方法來恢復之前保存的狀態。

    Canvas對象

    屬性

    • globalAlpha 透明度
      默認值為1.0(完全不透明),取值范圍為:0.0~1.0。其中0.0表示完全透明,1.0表示完全不透明。globalAlpha屬性必須在圖形繪制之前定義才有效。
    • width 寬度
    • height 高度

    常用于文字水平居中對齊和清空畫布

    cxt.clearRect(0, 0, cnv.width, cnv.height);

    方法

    • getContext(“2d”) 獲取Canvas 2D上下文環境對象
    • toDataURL() 獲取Canvas對象產生的位圖的字符串,即將Canvas畫布轉換為圖片的base64格式的字符串。
    cnv.toDataURL(type);
    • type 可選,默認值為image/png類型

    直接在Canvas畫布上點擊鼠標右鍵,在彈出的快捷菜單中也能“另存為”圖片為本地圖片,為什么還要那么麻煩地使用toDataURL()呢?

    事實上,很多舊版本的瀏覽器并不具備這個功能。因此為了兼容性,建議使用toDataURL()方法進行處理。

    • canvas保存圖片時,谷歌瀏覽器Chrome報錯【解決方案】Not allowed to navigate top frame to data URL
      https://blog.csdn.net/weixin_41192489/article/details/124386704

    圖形的重疊模式

    默認情況下,后繪制的圖形會覆蓋之前繪制的圖形。

    通過 globalCompositeOperation 可以修改重疊模式

    cxt.globalCompositeOperation = 屬性值;

    不同屬性值,效果如下圖:

    屬性值

    說明

    source-over

    默認值,新圖形覆蓋舊圖形

    copy

    只顯示新圖形,舊圖形作透明處理

    darker

    兩種圖形都顯示,在重疊部分,顏色由兩個圖形的顏色值相減后形成

    destination-atop

    只顯示新圖形與舊圖形重疊部分以及新圖形的其余部分,其他部分作透明處理

    destination-in

    只顯示舊圖形中與新圖形重疊部分,其他部分作透明處理

    destination-out

    只顯示舊圖形中與新圖形不重疊部分,其他部分作透明處理

    destination-over

    與source-over屬性相反,舊圖形覆蓋新圖形

    lighter

    兩種圖形都顯示,在圖形重疊部分,顏色由兩個圖形的顏色值相加后形成

    source-atop

    只顯示舊與新圖形重疊部分及舊圖形的其余部分,其他部分作透明處理

    source-in

    只顯示新圖形中與舊圖形重疊部分,其他部分作透明處理

    source-out

    只顯示新圖形中與舊圖形不重疊部分,其余部分作透明處理

    xor

    兩種圖形都繪制,其中重疊部分透明處理

    cxt.globalCompositeOperation = "xor";//繪制矩形cxt.fillStyle = "HotPink";cxt.fillRect(30, 30, 60, 60);//繪制圓形cxt.beginPath();cxt.arc(100, 100, 40, 0, Math.PI * 2, true);cxt.closePath();cxt.fillStyle = "LightSkyBlue";cxt.fill();

    cxt.globalCompositeOperation = "xor";//繪制第1個矩形cxt.fillStyle = "HotPink";cxt.fillRect(30, 30, 60, 60);//繪制圓形cxt.beginPath();cxt.arc(100, 100, 40, 0, Math.PI * 2, true);cxt.closePath();cxt.fillStyle = "LightSkyBlue";cxt.fill();//繪制第2個矩形cxt.fillStyle = "HotPink";cxt.fillRect(110, 30, 60, 60);

    總結

    以上是生活随笔為你收集整理的canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。