整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML5(五)-Canvas API

          么是 Canvas API?

          Canvas API(畫布)提供了一個通過 javascript 和 html 的 canvas 元素來在網頁上實時繪制圖形的方式。可用于動畫、游戲、圖標、圖片編輯等多個方面。

          使用前,首先需要新建在網頁上新建 canvas 元素。

          <canvas id="mycanvas" width="400" height="400">
           您的瀏覽器不支持canvas!
          </canvas>

          上述代碼,如果瀏覽器不支持 canvas,就會顯示標簽中間的文字--您的瀏覽器不支持 canvas!標簽通常指定一個 id 屬性,width、height 屬性一般定義畫布的大小。

          每個 canvas 元素都有一個對應的 context 對象(上下文對象),Canvas API 定義在 context 對象上,使用 getContext 方法來獲取對象。

          var canvas = document.getElementById("mycanvas");
          var ctx = canvas.getContext("2d")

          getContext 方法指定參數2d,表示 canvas 用于生成平面圖案,如果是 3d,表示 canvas 用于生成3d立體圖像。

          繪圖方法

          canvas 畫布提供了一個畫圖的平面空間范圍,每個點都有自己的坐標,原點位于畫布的左上角,x表示橫坐標,y表示縱坐標。

          2.1 繪制路徑

          • ctx.beginPath - 開始繪制路徑
          • ctx.moveTo( x,y ) - 設置路徑起點
          • ctx.lineTo( x,y ) - 繪制一條線到(x,y)點
          • ctx.closePath - 閉合圖形
          • ctx.stroke - 對路徑進行著色
          • ctx.fill - 對路徑進行填充

          eg:繪制一條線寬為5像素的紅色線條,代碼如下:

          var canvas = document.getElementById("mycanvas");
          var ctx = canvas.getContext("2d")
          ctx.beginPath();
          ctx.moveTo(0,0)
          ctx.lineTo(400,400)
          ctx.lineWidth = 5
          ctx.strokeStyle = "red"
          ctx.stroke()

          eg:繪制一個綠色三角形,代碼如下:

          var canvas = document.getElementById("mycanvas");
          var ctx = canvas.getContext("2d")
          ctx.beginPath();
          ctx.moveTo(0,0)
          ctx.lineTo(400,400)
          ctx.lineTo(0,400)
          ctx.closePath()
          ctx.lineWidth = 5
          ctx.strokeStyle = "red"
          ctx.stroke()
          ctx.fillStyle = "green"
          ctx.fill()

          2.2 繪制矩形

          • ctx.rect(x,y,width,height) - 繪制矩形路徑
          • ctx.strokeRect(x,y,width,height) - 繪制矩形
          • ctx.fillRect(x,y,width,height) - 繪制填充矩形
          • ctx.clearRect(x,y,width,height) - 清除矩形區域

          上述繪制矩形的方法中均有四個參數,其中x,y表示矩形的左上角頂點,也算起點,width、height 為矩形的寬高。strokeRect 與 strokeStyle 配合使用,fillRect 與 fillStyle 配合使用。

          eg:繪制一個帶有紅色邊框的矩形,代碼如下:

          var canvas = document.getElementById("mycanvas")
          var ctx = canvas.getContext('2d')
          ctx.strokeStyle="red";
          ctx.strokeRect(100,100,200,100)

          上述 stroke 替換成fill便可繪制一個紅色矩形。

          2.3 繪制圓形 / 弧

          • ctx.arc(x,y,radius,start,end,anticlockwise) - 繪制圓形或扇形

          上述的參數中,x,y 表示圓心的坐標,radius 是半徑,start 開始弧度,end 結束弧度,anticlockwise 表示是否是逆時針。

          eg:繪制一個帶有紅色描邊的黑色圓,代碼如下:

          <canvas id="circle" width="400" height="400"></canvas>
          <script>
           var canvas = document.getElementById("circle")
           var ctx = canvas.getContext('2d')
           ctx.arc(200,200,100,0,Math.PI*2,false);
           ctx.lineWidth=10
           ctx.strokeStyle = "red"
           ctx.stroke()
           ctx.fillStyle="#000"
           ctx.fill()
          </script>

          2.4 繪制文本

          • strokeText(string,x,y) - 繪制空心文字
          • fillText(string,x,y) - 繪制實心文字

          上述兩個方法均帶有三個參數,第一個 string 是需要繪制的內容,x,y 是文字的位置,需要注意的是 y 坐標是以文字的基線處開始算距離的,并非是文字頂部。文字的其他樣式可通過 font 屬性設置,與 css 的 font 類似。

          eg:繪制實心的文字,并設置文字加粗、大小20像素是微軟雅黑字體。代碼如下:

          var canvas = document.getElementById("mycanvas")
          var ctx = canvas.getContext('2d')
          ctx.fillStyle="red";
          ctx.font = "bold 40px 微軟雅黑"
          ctx.fillText("我愛前端",100,100)

          注意:繪制文本的時候無法換行,如果需要換行的時候就需要多次繪制文字,達成換行目的。

          2.5 設置漸變色

          • createLinearGradient(x1,y1,x2,y2) - 設置漸變色

          其中 x1,y1 表示起點,x2,y2 表示終點,通過不同坐標可控制漸變方向。

          eg:給文字設置漸變色,代碼如下:

          var canvas = document.getElementById("mycanvas")
          var ctx = canvas.getContext('2d')
          var grd = ctx.createLinearGradient(0,0,400,400)
          grd.addColorStop(0,"#4dffff")
          grd.addColorStop(1,"#8e12aa")
          ctx.fillStyle=grd;
          ctx.font = "bold 40px 微軟雅黑"
          ctx.fillText("我愛前端",100,100)

          2.6 設置陰影

          • shadowOffsetX - 設置水平位移
          • shadowOffsetY - 設置垂直位移
          • shadowBlur - 設置模糊度
          • shadowColor - 陰影顏色

          eg:制作一個帶有陰影的矩形,代碼如下:

          var canvas = document.getElementById("mycanvas")
          var ctx = canvas.getContext("2d")
          ctx.shadowOffsetX = 5;
          ctx.shadowOffsetY = 5
          ctx.shadowBlur = 10;
          ctx.shadowColor = "rgba(0,0,0,0.5)"
          ctx.fillStyle="red"
          ctx.fillRect(0,0,200,100);

          圖片處理

          3.1 drawImage

          drawImage(img,x,y) - 對圖片進行重繪

          drawImage方法接受三個參數,第一個是圖片文件的 DOM 元素,x,y 表示繪制圖片的起始位置,也是圖片的左上角。由于圖片加載需要時間,drawImage 方法只能在圖片加載完成后才能調用。

          eg:把一張圖片重繪到 canvas 上,代碼如下:

          var canvas = document.getElementById("mycanvas")
          var ctx = canvas.getContext("2d")
          var img = new Image()
          img.src="https://zhengxin-pub.cdn.bcebos.com/financepic/cc840df83f7b47551e080410cc6c484c_fullsize.jpg"
          img.onload = function(){
           ctx.clearRect(0,0,canvas.width,canvas.height)
           ctx.drawImage(img,0,0) 
          }

          3.2 getImageData、putImageData

          getImageData(0,0,canvas.width,canvas.height)

          getImageData 用來讀取 canvas 的內容,返回一個對象,包含了每個像素的信息。

          var info = ctx.getImageData( 0 , 0 , canvas.width , canvas.height )

          putImageData( info , 0 , 0 )

          putImageData 是將 getImageData 獲取到的信息,重新繪制到 canvas。

          3.3 toDataURL

          對圖像數據做出修改后,使用 toDataURL 方法,將 canvas 數據重新轉化成一般的圖像文件格式,然后可以進行另存本地或轉發功能。

          eg:將 canvas 繪制的矩形轉成一張圖片,顯示到網頁上,代碼如下:

          <canvas id="mycanvas" width="400" height="400"></canvas>
          <img src="" alt="" id="picture">
          <script>
           var canvas = document.getElementById("mycanvas")
           var ctx = canvas.getContext('2d')
           ctx.strokeStyle="red";
           ctx.strokeRect(100,100,200,100)        
           var img = document.getElementById("picture")
           img.src= canvas.toDataURL("image/png")
          </script>

          3.4 save、restore

          • save - 保存上下文環境
          • restore - 恢復到上一次保存的上下文環境

          eg:下面代碼先用 save 方法,保存了當前設置,然后繪制了一個有陰影的矩形。接著,使用 restore 方法,恢復了保存前的設置,繪制了一個沒有陰影的矩形。

          布 (canvas) 是 JavaScript 庫,用于在網頁中創建交互式圖形和動畫。它提供一個繪圖上下文,用于繪制各種圖形元素。


          畫布 API

          畫布 API 提供以下方法:

          • getContext():獲取繪圖上下文。
          • fillRect():繪制一個矩形。
          • strokeRect():繪制一個矩形的邊框。
          • fillStyle:填充顏色。
          • strokeStyle:邊框顏色。

          示例

          const canvas = document.getElementById("canvas");
          const ctx = canvas.getContext("2d");
          
          ctx.fillRect(10 viciss, 10 viciss, 10 viciss, 10 viciss);
          

          圖形操作

          • 線條:使用 beginPath()、moveTo() 和 lineTo() 方法繪制線條。
          • 圖形:使用 beginPath()、arc() 和 closePath() 方法繪制圖形。
          • 文本:使用 fillText() 方法繪制文本。

          動畫

          • 使用 requestAnimationFrame() 方法在動畫幀中更新圖形。
          • 使用 transform 屬性來改變圖形的坐標系。

          結論

          畫布 API 提供了在 JavaScript 中創建交互式圖形的強大工具。它適合各種目的,從簡單圖形到復雜的動畫。了解畫布 API 可以幫助您在網頁上創建令人驚嘆的視覺效果。

          么是Canvas

          <canvas> 是HTML中的一個元素,它可被用來通過 JavaScript(Canvas API 或 WebGL API)繪制圖形及圖形動畫。

          Canvas API 提供了一個通過 JavaScriptHTML<canvas> 元素來繪制圖形的方式。它可以用于動畫、游戲畫面、數據可視化、圖片編輯以及實時視頻處理等方面。

          <canvas>標簽本身沒有繪圖能力,它僅僅是圖形的容器。在HTML,一般通過Javascript語言來完成實際的操作。

          創建HTML頁面并添加繪圖容器

          本文通過Javascript操作Canvas制作一個簡單的顯示當前時間的動畫時鐘,了解和學習簡單的canvas用法,僅以拋磚引玉。

          首先創建一個HTML文件,為了方便管理,使用一個div標簽包裹兩個canvas標簽,并加上一些簡單的css樣式。

          <!doctype html>
          <html lang="zh-cn">
          <head><title>Canvas繪制動畫時鐘</title>
          <style>
          html,body{margin:0;padding:0}
          #clockWrap {
          	position: relative;
          }
          canvas {
          	position: absolute;
          }
          #clock-ui {
          	z-index: 2;
          }
          #clock-plate {
          	z-index: 1;
          }
          </style>
          </head>
          <body>
            <div id="clockWrap">
            <canvas id="clock-plate"></canvas>
            <canvas id="clock-ui"></canvas>
          </div>
          <script></script>
          </body></html>

          本示例中使用了兩個canvas標簽(為什么使用兩個,一個不是更簡單嗎?),一個用于繪制鐘面,一個根據當前時間實時顯示和更新時針、分針和秒針的動態指向。好了,話不多說,開干。

          繪制鐘面刻度

          一個簡單的時鐘,可以分為鐘面上的刻度和指針。其中刻度和12個數字是固定的,我們可以將它們繪制在當作背景的canvas上(示例中id為clock-plate的canvas)。

          (1)要使用canvas,首先必須通過容器獲取渲染上下文:

          var $=function(id){return document.querySelector(id);}//這個函數只是為了方便獲取dom元素
          const canvasbg=$("#clock-plate"),
                canvas=$("#clock-ui"),
                ctx = canvasbg.getContext("2d"),//背景容器上下文
                ctxUI = canvas.getContext("2d");//指針容器上下文,后面代碼要用
          //定義畫布寬度和高度,時鐘圓直徑,并設置畫布大小
          const oW=1000,oH=800,cW=400,r=cW/2,oX=oW/2,oY=oH/2;
          canvas.width=oW;
          canvas.height=oH;
          canvasbg.width=oW;
          canvasbg.height=oH;

          (2)畫鐘的邊框,為了好看,這里畫兩個圈:

           //畫出時鐘外圓框
            ctx.lineWidth = 12;
          	ctx.beginPath();
          	ctx.arc(oX, oY, r+14, 0, 2 * Math.PI);
          	ctx.stroke();
          	ctx.closePath();
          	ctx.lineWidth = 8;
          	//畫出時鐘內圓框(刻度圈)
          	ctx.beginPath();
          	ctx.arc(oX, oY, r, 0, 2 * Math.PI);
          	ctx.stroke();
          	ctx.closePath();
          	ctx.beginPath();

          邊框效果圖

          (3)繪制刻度線和數字,可以利用三角函數計算出每個刻度的坐標:

          利用三角函數計算刻度線的坐標位置

          鐘面上有12個大格,從正上方12開始,它們的度數分別是270,300,330,0,30,60,90,120,150,180,210,240。然后利用JS的Math.sin和Math.cos分別計算出各大格的坐標。注意:js中Math.sin()和Math.cos()的參數不是角度數弧度。可以使用Math.PI/180*角度來轉化,比如將30度轉換成弧度=Math.PI/180*30

          //繪制鐘表中心點
          	ctx.beginPath();
          	ctx.arc(oX, oY, 8, 0, 2 * Math.PI);//圓心
          	ctx.fill();
          	ctx.closePath();
          	//設置刻度線粗細度
          	ctx.lineWidth = 3;
          	//設置鐘面12個數字的字體、大小和對齊方式
          	ctx.font = "30px serif";
          	ctx.textAlign="center";
          	ctx.textBaseline="middle";
          	var kdx,kdy;
          	//繪制12個大刻度和12個數字
          	//為方便計算,先定義了0-11這12個刻度對應的度數,也可以直接定義對應的弧度。
          	const hd=Math.PI/180,degr=[270,300,330,0,30,60,90,120,150,180,210,240];
          	for(var i=0;i<12;i++){
          		kdx=oX+Math.cos(hd*degr[i])*(r-3);
          		kdy=oY+Math.sin(hd*degr[i])*(r-3);
          		ctx.beginPath();
          		ctx.arc(kdx, kdy, 6, 0, 2 * Math.PI);//畫圓形大刻度
          		ctx.fill();
              //繪制刻度對應的數字
          		ctx.strokeText(i==0? 12 : i,oX+Math.cos(hd*degr[i])*(r-24),oY+Math.sin(hd*degr[i])*(r-24));
          		ctx.closePath();
          	}
          	
          	//繪制小刻度
          	ctx.lineWidth = 2;
          	for(var i=0;i<60;i++){
          		if(i % 5 == 0) continue;//跳過與刻度重疊的刻度
          		x0=Math.cos(hd*i*6);
          		y0=Math.sin(hd*i*6);
          		ctx.beginPath();
          		ctx.moveTo(oX+x0*(r-10), oY+y0*(r-10)); 
          		ctx.lineTo(oX+x0*r, oY+y0*r); //畫短刻度線
          		ctx.stroke(); 
          		ctx.closePath();
          	}

          效果如圖:

          鐘面效果圖

          (4)根據當前時間繪制指針

          習慣上,時針粗短,分針略粗而長,秒針細長。為加大區別,示例中秒針細長并且繪制成紅色。

          function drawHp(i){//繪制時針
          	const x0=Math.cos(hd*i*30),y0=Math.sin(hd*i*30);
          	drawPointer(oX,oY,oX+x0*(r-90),oY+y0*(r-90),10,"#000000");
          }
          function drawMp(i){//繪制分針
          	const x0=Math.cos(hd*i*6),y0=Math.sin(hd*i*6);
          	drawPointer(oX,oY,oX+x0*(r-60),oY+y0*(r-60),5,"#000000");
          }
          function drawSp(i){//繪制秒針
          	const x0=Math.cos(hd*i*6),y0=Math.sin(hd*i*6);
          	drawPointer(oX,oY,oX+x0*(r-20),oY+y0*(r-20),2,"#FF0000");
          }
          //抽取出繪制三種指針時共同的部分,注意指針繪制在渲染上下文ctxUI中
          function drawPointer(ox,oy,tx,ty,width,color){
          	ctxUI.strokeStyle = color;
          	ctxUI.lineCap = "round";
          	ctxUI.lineWidth = width;
          	ctxUI.beginPath();
          	ctxUI.moveTo(ox, oy);
          	ctxUI.lineTo(tx,ty);
          	ctxUI.stroke();
          	ctxUI.closePath();
          }

          現在已經有了繪制三種指針的方法,參數是當前時間的時、分和秒,將根據它們的值確定指針的坐標。不過,因為使用的是默認的convas坐標體系,0值實際指向3的位置,需要小小的修正一下。

          window.requestAnimationFrame(function fn(){
          		var d = new Date();
          		ctxUI.clearRect(0,0,oW,oH);
          		//度數從0開始,而0在3刻度(15分/秒位置),修正為全值減15,如果小于0則修正回來
              var hour=d.getHours(),minute=d.getMinutes()-15,second=d.getSeconds()-15;
          		hour=hour>11? hour-15 : hour-3;
          		drawHp(hour>=0? hour : 12+hour);
          		drawMp(minute>=0? minute : 60+minute);
          		drawSp(second>=0? second : 60+second);
          		window.requestAnimationFrame(fn);
          });

          接下來,調用window.requestAnimationFrame,在其中繪制并更新指標的位置。看看效果如何:

          指針繪制情況與實際時間相符

          貌似效果有了,截圖時電腦上的時間是10時17分,指針繪制上,時針指向10時,分針指向17。嗯,感覺有點別扭?對了,時針和分針怎么是端端正正地指向它們的整時整分刻度上呢?實際鐘表上時針和分針是展示動態進度的,此時時針應該越過10時的位置才對。沒關系,我們在繪制時針和分針時別點東西,讓它的角度值加上分針和秒針的值試試。

          //修改后的繪制三種指針的方法
          function drawHp(i,f,m){//繪制時針,參數:時,分,秒
          	const x0=Math.cos(hd*(i+(f/60)+(m/600))*30),y0=Math.sin(hd*(i+(f/60)+(m/600))*30);
          	drawPointer(oX,oY,oX+x0*(r-90),oY+y0*(r-90),10,"#000000");
          }
          function drawMp(i,f){//繪制分針,參數,分,秒
          	const x0=Math.cos(hd*(i+(f/60))*6),y0=Math.sin(hd*(i+(f/60))*6);
          	drawPointer(oX,oY,oX+x0*(r-60),oY+y0*(r-60),5,"#000000");
          }
          function drawSp(i){//繪制秒針
          	const x0=Math.cos(hd*i*6),y0=Math.sin(hd*i*6);
          	drawPointer(oX,oY,oX+x0*(r-20),oY+y0*(r-20),2,"#FF0000");
          }

          再來看看效果,嗯,立竿見影呀:

          指針指向更合理了

          到此為止,canvas繪制一個簡易時鐘就完成了。下面繼續優化一下。剛才使用requestAnimationFrame方法即時更新繪制情況。這個方法與刷新率有關,看看mdn上面怎么說的:

          window.requestAnimationFrame() 方法會告訴瀏覽器你希望執行一個動畫。它要求瀏覽器在下一次重繪之前,調用用戶提供的回調函數。

          對回調函數的調用頻率通常與顯示器的刷新率相匹配。雖然 75hz、120hz 和 144hz 也被廣泛使用,但是最常見的刷新率還是 60hz(每秒 60 個周期/幀)。為了提高性能和電池壽命,大多數瀏覽器都會暫停在后臺選項卡或者隱藏的 <iframe> 中運行的 requestAnimationFrame()。

          本示例中,更新指針的位置并不需要很高的刷新頻率,可以通過節流進行一下優化:

          var fps = 5, fpsInterval = 1000 / fps,lastTime = new Date().getTime(); //記錄上次執行的時間
          function runStep() {
              requestAnimationFrame(runStep);
              var d=new Date(),now = d.getTime()
              var elapsed = now - lastTime;
              if (elapsed > fpsInterval) {
          				ctxUI.clearRect(0,0,oW,oH);
                  lastTime = now - (elapsed % fpsInterval); 
          			//度數從0開始,而0在3刻度(15分/秒位置),修正為全值-15,如果小于0則用60減回
                  var hour=d.getHours(),minute=d.getMinutes()-15,second=d.getSeconds()-15;//console.log(d.getSeconds(),second);
                  hour=hour>11? hour-15 : hour-3;
                  drawHp(hour>=0? hour : 12+hour,minute+15,second+15);
                  drawMp(minute>=0? minute : 60+minute,second+15);
                  drawSp(second>=0? second : 60+second);
              }
          }
          runStep();

          當然,實現時鐘的方法是很多,比如可以使用畫布的旋轉(rotate方法)來實現指針的動態轉動等等。

          完整HTML+JS源碼:


          主站蜘蛛池模板: 国产婷婷一区二区三区| 激情啪啪精品一区二区| 国产成人精品一区二区三在线观看| 色国产在线视频一区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 91福利国产在线观看一区二区 | 一区二区三区在线免费| 久久一区二区免费播放| 亚洲AV综合色区无码一区爱AV| 亚洲国产成人久久一区二区三区 | 午夜爽爽性刺激一区二区视频| 中文字幕一区在线| 日韩一区二区精品观看| 成人区精品一区二区不卡亚洲| 亚洲AV无码一区东京热久久| 暖暖免费高清日本一区二区三区| 亚洲av福利无码无一区二区 | 国模精品视频一区二区三区| 无码人妻品一区二区三区精99| 日韩在线一区视频| 国产亚洲一区二区在线观看 | 中文人妻无码一区二区三区| 日本一区二区三区在线观看视频 | 丰满爆乳一区二区三区| 国产成人一区二区精品非洲 | 亚洲AV综合色区无码一区爱AV | 91精品福利一区二区| 久久亚洲AV午夜福利精品一区| 激情综合丝袜美女一区二区| 亚洲午夜精品一区二区麻豆| 无码人妻精品一区二区三区在线| 亚洲色婷婷一区二区三区| 亚洲成av人片一区二区三区| 国产精品盗摄一区二区在线| 精品国产一区二区三区久久影院| 亚洲中文字幕一区精品自拍| 国产精品特级毛片一区二区三区| 真实国产乱子伦精品一区二区三区| 精品视频在线观看你懂的一区| 无码日韩人妻AV一区免费l | 无码人妻精品一区二区三18禁|