Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲夂夂婷婷色拍ww47,好男人www社区资源在线观看,精品视频中文字幕

          整合營銷服務商

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

          免費咨詢熱線:

          HTML5(六)-Canvas 高級操作

          一篇文章《HTML5(五)——Canvas API》介紹 canvas 繪制基本圖形,這節開始介紹canvas的高級操作。

          一、canvas 轉換

          canvas 轉換常用的幾種方法介紹,如下:

          方法

          描述

          scale()

          縮放當前繪圖至更大或更小。

          rotate()

          旋轉當前繪圖。

          translate()

          重新映射畫布上的 (0,0) 位置。

          transform()

          替換繪圖的當前轉換矩陣。

          setTransform()

          將當前轉換重置為單位矩陣。然后運行 transform()。

          1.1 、scale - 縮放

          使用語法:scale(x,y)

          x:表示水平方向的縮放倍數

          y:表示垂直方向的縮放倍數

          eg:canvas 繪制的矩形框放大兩倍,代碼如下:

          var canvas = document.getElementById("canvas")
          var ctx = canvas.getContext("2d")
          ctx.scale(2,2)
          ctx.fillStyle="red"
          ctx.fillRect(0,0,200,200)

          1.2、translate - 畫布平移

          使用語法:translate(x,y)

          x:添加到水平坐標上的位置

          y:添加到垂直坐標上的位置

          設置之后開始繪制的圖片位置從(x,y)算起。

          eg:繪制兩個一樣的矩形,一個在平移前繪制,一個在平移后繪制,代碼如下:

          var canvas = document.getElementById("canvas")
          var ctx = canvas.getContext("2d")
          ctx.fillStyle="red"
                  
          ctx.fillRect(0,0,200,200)
          //平移
          ctx.translate(200,200)
          ctx.fillRect(0,0,200,200)

          運行結果如圖:

          1.3 、rotate - 旋轉

          使用語法:rotate(angle)

          angle 旋轉弧度,如果想使用角度,可以把角度轉成弧度,公式為:deg * Path.PI/180。

          eg:將一個矩形旋轉45度,代碼如下:

          var canvas = document.getElementById("canvas")
          var ctx = canvas.getContext("2d")
          //旋轉45度
          ctx.rotate(45*Math.PI/180)
          ctx.fillStyle="red"
          ctx.fillRect(0,0,200,200)

          運行結果如圖:

          根據上述結果我們發現旋轉的時候,默認原點是畫布的起始點,我們想要的旋轉是在矩形框中心為原點的旋轉,此時我們需要借助上translate平移,重置一下原點,修改上述代碼為:

          <canvas width="400" height="400" id="canvas"></canvas>
          
          var canvas = document.getElementById("canvas")
          var ctx = canvas.getContext("2d")
          
          ctx.translate(200,200)
          ctx.rotate(45*Math.PI/180)
          ctx.translate(-200,-200)
          
          ctx.fillStyle="red"
          ctx.fillRect(100,100,200,200)

          運行結果如圖:

          1.4、transform - 矩陣變換

          使用語法:transform(a,b,c,d,e,f)

          • a:水平縮放
          • b:水平傾斜
          • c:垂直傾斜
          • d:垂直縮放
          • e:水平移動
          • f:垂直移動

          transform可以替代前邊平移、縮放、旋轉三者,如下:

          // 平移
          translate(x,y) <=> transform(1,0,0,1,x,y) <=> transform(0,1,1,0,x,y)
          // 縮放
          sacle(x,y) <=> transform(x,0,0,y,0,0) 
          // 旋轉
          rotate(angle) <=> transform(Math.cos(angle*Math.PI/180), Math.sin(angel*Math.PI/180), -Math.sin(angle*Math.PI/180), Math.cos(angle*Math.PI/180))

          1.5、setTransform - 矩陣變換

          setTransform()方法將變換的矩陣進行重置,它把當前的變換矩陣重置為單位矩陣
          使用語法:transform(a,b,c,d,e,f)
          各參數說明:水平旋轉、水平傾斜、垂直傾斜、垂直縮放、水平移動、垂直移動

          setTransform() 方法把當前的變換矩陣重置為單位矩陣,然后以相同的參數運行 transform()

          二、canvas 操作圖片

          drawImage() 在畫布上繪制圖像、畫布或視頻。也能夠繪制圖片的一部分,增加或減少圖像的尺寸。以下是三種常見使用語法:

          • 語法1:drawImage( img , x , y )
          • 語法2:drawImage( img , x , y , width , height )
          • 語法3:drawImage( img , sx , sy , swidth, sheight , x , y , width , height )

          上述參數表示的意義如下:

          參數

          描述

          img

          規定要使用的圖像、畫布或視頻。

          sx

          可選。開始剪切的 x 坐標位置。

          sy

          可選。開始剪切的 y 坐標位置。

          swidth

          可選。被剪切圖像的寬度。

          sheight

          可選。被剪切圖像的高度。

          x

          在畫布上放置圖像的 x 坐標位置。

          y

          在畫布上放置圖像的 y 坐標位置。

          width

          可選。要使用的圖像的寬度。(伸展或縮小圖像)

          height

          可選。要使用的圖像的高度。(伸展或縮小圖像)

          eg:利用語法3,進行繪制圖片的部分內容,實現如下效果:

          給上述兔子順便加一個點擊屏幕暫停開始功能,完整代碼如下:

          <canvas width="400" height="400" id="canvas"></canvas>
          <script>
           var canvas = document.getElementById("canvas")
           var ctx = canvas.getContext("2d")
           var img = new Image()
           let pause = false,frameCounter = 0,i=0;
           img.src = "./rotate.png"
           img.onload = function(){
            requestAnimationFrame(next)
           }
          function next(){
           ctx.clearRect(0,0,canvas.width,canvas.height)
           if(frameCounter%5 == 0){ //frameCounter 控制動畫速度
            i++
            if(i==11)i=0
           }
           ctx.drawImage(img,
            0,i*240,240,240,
            0,0,240,240) // 每張圖片寬高都是240,具體參數根據圖片而定
            frameCounter ++
            if(!pause)requestAnimationFrame(next)
           }
          window.onclick = function(){
           pause = !pause
           next()
          }
          </script>

          eg:使用 canvas 畫布處理視頻,使用定時器繪制視頻的當前幀,連續起來就是一個視頻,需要注意的是必須處理暫停和開始播放兩種操作,具體代碼如下:

          var v=document.getElementById("video1");
          var c=document.getElementById("myCanvas");
          ctx=c.getContext('2d');
          v.addEventListener('play',function() {var i=window.setInterval(function() 
          {ctx.drawImage(v,0,0,270,135)},20);},false);
          v.addEventListener('pause',function() {window.clearInterval(i);},false);
          v.addEventListener('ended',function() {clearInterval(i);},false);

          三、像素級操作

          常見的像素級的操作有三種:

          • getImageData() - 獲取畫布像素數據
          • createImageData() - 創建新的、空白像素
          • putImageData() - 圖像像素數據放回畫布

          3.1、getImageData

          使用語法:getImageData( x , y , width , height )

          • x:要被提取的圖像數據矩形區域的左上角 x 坐標。
          • y:要被提取的圖像數據矩形區域的左上角 y 坐標。
          • width:被提取的圖像數據矩形區域的寬度
          • height:被提取的圖像數據矩形區域的高度

          返回一個 imageData 對象,用來描述 canvas 區域隱含的像素數據,這個區域通過像素表示,起點是( x , y ),寬高為 widht 和 height 。

          imageData 對象包含三個屬性:

          • imageData.height - 像素描述的矩形實際高度。
          • imageData.width - 像素描述的矩形實際寬度。
          • imageData.data - 包含 rgba 順序數據的一個數組,數據使用0-255直接整數表示。

          3.2、createImageData

          使用語法:

          createImageData( width , height )

          創建一個空白的 imageData 對象,新對象的默認像素值 transparent black。對于imageData對象中的每個像素值,都存在 rgba 這四方面的信息,即:

          • r - 紅色(0-255)
          • g - 綠色(0-255)
          • b - 藍色(0-255)
          • a - alpha(0-255,0是透明,255是完全可見)

          新對象默認像素值為(0,0,0,0)。

          eg:如果我們想把 imageData 中一個像素變為紅色時,可以改變第一和第四位信息,代碼如下:

          var imageData = ctx.createImageData(100,100)
          imageData.data[0] = 255
          imageData.data[1] = 0
          imageData.data[2] = 0
          imageData.data[3] = 255

          3.1、putImageData

          使用語法:

          putImageData( imgData , x , y , dirtyX , dirtyY , dirtyWidth ,dirtyHeight );

          參數及意義:

          參數

          描述

          imgData

          規定要放回畫布的 ImageData 對象。

          x

          ImageData 對象左上角的 x 坐標,以像素計。

          y

          ImageData 對象左上角的 y 坐標,以像素計。

          dirtyX

          可選。水平值(x),以像素計,在畫布上放置圖像的位置。

          dirtyY

          可選。水平值(y),以像素計,在畫布上放置圖像的位置。

          dirtyWidth

          可選。在畫布上繪制圖像所使用的寬度。

          dirtyHeight

          可選。在畫布上繪制圖像所使用的高度。

          通過 getImageData 復制的指定矩形像素數據,編輯之后,通過 putImageData 方法將圖像數據放回畫布上。

          eg:添加濾鏡效果:上述兔子是白色的變換成紅色兔子,這時需要把綠色和藍色都設置成0即可,代碼如下:

          TML5 Canvas是HTML5新增的一個元素,它提供了一個可執行JavaScript腳本繪制圖形的區域。Canvas元素通過使用JavaScript API,可以在瀏覽器上繪制圖形、渲染動畫和實現交互效果等。

          使用原理:
          HTML5 Canvas通過使用JavaScript API在瀏覽器中創建一塊畫布(Canvas),然后可以使用腳本語言(通常是JavaScript)在畫布上繪制各種形狀、線條、圖像和文本等。Canvas使用像素渲染,可以直接操作像素數據,因此在性能方面相比其他圖形技術(如SVG)更具優勢。

          場景:
          HTML5 Canvas可以應用于各種需要圖形繪制、動畫渲染和交互效果的場景,例如:

          1. 游戲開發:Canvas可以用來開發2D或3D游戲,通過繪制游戲場景、角色和動畫等實現游戲效果。
          2. 數據可視化:Canvas可以用來繪制各種圖表和圖形,實現數據可視化效果。
          3. 圖像處理:Canvas可以對圖像進行像素級別的操作,實現圖像處理功能,例如濾鏡、裁剪和合成等。
          4. 實時視頻處理:Canvas可以結合WebRTC等技術實現實時視頻處理,例如在視頻通話中添加特效和濾鏡等。

          代碼示例:
          以下是一個簡單的HTML5 Canvas代碼示例,用于在畫布上繪制一個矩形和一個圓形:

          <!DOCTYPE html>  
          <html>  
              <head>  
               			<title>HTML5 Canvas示例</title>  
              </head>  
                <body>  
                     <canvas id="myCanvas" width="400" height="400"></canvas>  
                       <script>  
                           // 獲取Canvas元素和繪圖上下文  
                           var canvas = document.getElementById("myCanvas");  
                           var ctx = canvas.getContext("2d");  
                           // 繪制矩形  
                           ctx.fillStyle = "blue";  
                           ctx.fillRect(50, 50, 100, 100);  
                           // 繪制圓形  
                           ctx.beginPath();  
                           ctx.arc(200, 200, 50, 0, Math.PI * 2);  
                           ctx.fillStyle = "red";  
                           ctx.fill();  
                       </script>  
                </body>  
          </html>

          在上述代碼中,我們首先獲取了Canvas元素和繪圖上下文(Context),然后使用fillRect()方法繪制了一個藍色的矩形,使用arc()方法繪制了一個紅色的圓形。最后,我們使用fill()方法填充了圓形的顏色。

          、什么是Canvas?

          HTML5 提供Canvas API,其本質上是一個DOM元素,可以看成是瀏覽器提供一塊畫布供我們在上面渲染2D或者3D圖形。由于3D繪制上下文(webgl)目前在很多瀏覽器上兼容性較差,所以我們一般用于繪制2D圖形。

          <canvas id="canvas"></canvas>


          2、為什么使用Canvas?


          Canvas是HTML5引入的標簽,在此之前我們通常會使用SVG來繪制一些圖形,那么兩者之間有什么區別呢?SVG可縮放矢量圖形(Scalable Vector Graphics)是基于可擴展標記語言XML描述的2D圖形的語言,兩者部分區別:


          • SVG 圖像是使用各種元素創建的,這些元素分別應用于矢量圖像的結構、繪制與布局;而Canvas本身并不描述圖像,而是通過Javascript完成繪制;
          • 如上所述,SVG本身是DOM元素,每一個描述元素也是DOM元素,瀏覽器在進行渲染時需要進行大量計算以處理每一個元素;而在渲染Canvas的過程中,瀏覽器只需要渲染一張畫布,其余的是通過Javascript引擎執行邏輯來繪制;
          • SVG(矢量圖)不依賴分辨率,放大不會失真;而Canvas(位圖)依賴分辨率,放大會失真;



          由于Canvas是通過Javascript來完成繪制的,所以可控性很強,我們可以比較精確的控制圖形渲染的每一幀;從另一方面來說,如果在高頻率渲染中要處理過多的DOM元素就意味著性能一定不會太好,渲染速度會下降很多。Canvas的高性能能夠保障復雜場景中圖形的渲染效率,所以目前很多領域都會使用Canvas,例如動畫、游戲圖形、數據可視化、照片處理和實時視頻處理等。



          3、Canvas的基本使用

          要使用Canvas,我們需要先獲取Canvas元素的引用繼而通過getContext()方法獲取圖形的繪制上下文。

          const canvas = document.getElementById('canvas')
          const ctx = canvas.getContext('2d')


          獲取到圖形繪制上下文后,我們就能使用CanvasRenderingContext2D接口上的繪圖API了,接下來我們可以了解一些比較常規的使用。


          3.1、畫布屬性:


          • width、height:畫布的寬度以及高度,默認大小為300x150;
          • fillStyle:填充圖形的樣式,值可以是color string、CanvasGradient對象;
          • strokeStyle:輪廓圖形的樣式,值可以是color string、CanvasGradient對象;
          • lineWidth:繪制線條的寬度;
          • globalAlpha:畫布的透明度,0-1的偏移值;
          • globalCompositeOperation:畫布中新老圖形重疊時的渲染方式,默認為source-over,新圖形覆蓋老圖形;
          • ......
          ctx.width = 300
          ctx.height = 300
          ctx.fillStyle = '#fff'
          ctx.strokeStyle = 'blue'
          ctx.lineWidth = 5
          ctx.globalAlpha = 0.3
          ctx.globalCompositeOperation = 'destination-out' // 新老圖形重疊部分變透明
          ......

          3.2、繪制圖形:


          • .fillRect(x,y,width,height):繪制一個填充的矩形,矩形左上角的坐標為(x,y),高寬分別為width、height;
          • .strokeRect(x,y,width,height):繪制一個矩形邊框,矩形左上角的坐標為(x,y),高寬分別為width、height;
          • .clearRect(x,y,width,height):清除指定矩形區域,讓清除部分完全透明;
          ctx.fillStyle = 'red' 
          ctx.fillRect(100,100,100,100)
          
          
          ctx.strokeStyle = 'blue'  
          ctx.strokeRect(200,200,100,100)
          
          
          ctx.clearRect(125,125,50,50)
          ctx.strokeRect(130,130,40,40)




          3.3、繪制路徑:


          • .beginPath():開始一段路徑的繪制
          • .closePath():從起始點到當前點,結束路徑的繪制,非必需
          • .fill():根據路徑生成填充圖形;
          • .stroke():通過路徑生成輪廓圖形;
          • .moveTo(x,y):聲明一段路徑的起始點;
          • .lineTo(x,y):繪制一條從當前坐標到(x,y)的線;
          ctx.beginPath()
          ctx.moveTo(50,50)
          ctx.lineTo(100,100)
          ctx.lineTo(100,0)
          ctx.fill()
          
          
          ctx.beginPath()
          ctx.moveTo(110,100)
          ctx.lineTo(150,100)
          ctx.lineTo(150,200)
          ctx.lineTo(110,200)
          ctx.closePath() // 輪廓圖形不會根據從當前坐標到起始坐標生成輪廓,所以需要閉合路徑
          ctx.stroke()


          3.4、繪制圓弧:


          • .arc(x,y,radius,startAngle,endAngle,anticlockwise):畫一個以(x,y)為圓心的以 radius 為半徑的圓弧(圓),從 startAngle 開始到 endAngle 結束,按照 anticlockwise 給定的方向(默認為順時針,false)來生成;
          • arcTo(x1,y1,x2,y2,radius):根據給定的兩條切線中的一組切點坐標生成半徑為radius的圓弧;



          注意:arc函數中的角度的單位是弧度而不是度,弧度=(Math.PI/180)*度

          // 圓左上部分
          ctx.beginPath()
          ctx.arc(100,100,50,Math.PI,Math.PI*3/2,false)
          ctx.strokeStyle = '#ff6700'
          ctx.stroke()
          
          
          // 圓右上部分
          ctx.beginPath()
          ctx.arc(100,100,50,Math.PI*3/2,0,false)
          ctx.strokeStyle = '#6700ff'
          ctx.stroke()
          
          
          // 圓右下部分
          ctx.beginPath()
          ctx.arc(100,100,50,0,Math.PI/2,false)
          ctx.strokeStyle = '#00FFFF'
          ctx.stroke()
          
          
          // 圓左下部分
          ctx.beginPath()
          ctx.arc(100,100,50,Math.PI/2,Math.PI,false)
          ctx.strokeStyle = '#8B008B'
          ctx.stroke()
          
          
          // 兩條切線的交點坐標為(0,0)
          ctx.beginPath()
          ctx.moveTo(100,0)
          ctx.arcTo(0,0,0,100,100)
          ctx.fillStyle = 'blue'
          ctx.fill()



          3.5、漸變對象:


          • .createLinearGradient(x1, y1, x2, y2):創建一個沿參數坐標指定的直線的漸變,開始坐標為(x1,y1),結束坐標為(x2,y2);
          • .createRadialGradient(x1, y1, r1, x2, y2, r2):創建根據參數確定兩個圓的坐標的放射性漸變,開始圓形圓心為(x1,y1),半徑為r1;結束圓形圓心為(x2,y2),半徑為r2;

          創建好漸變對象之后,可以通過漸變對象上的.addColorStop(offset,color)為每一個漸變階段填充顏色,offset為0-1的偏移值。

          const gradient = ctx.createLinearGradient(50, 50, 250, 50)
          gradient.addColorStop(0, 'blue')
          gradient.addColorStop(0.5, 'green')
          gradient.addColorStop(1, 'red')
          ctx.fillStyle = gradient
          ctx.fillRect(0, 0, 300, 90)
          
          
          const radialGradient = ctx.createRadialGradient(200,200,100,200,200,50);
          radialGradient.addColorStop(0,"yellow");
          radialGradient.addColorStop(1,"green");
          ctx.fillStyle = radialGradient;
          ctx.fillRect(100,100,200,200);




          3.6、像素操作:


          • .drawImage(image,x,y,width,height):image可以是image對象、canvas元素、video元素;
          • .getImageData(x,y,width,height):獲取坐標為(x,y)一定區域內圖像的像素數據;
          const div = document.querySelector('div')
          let mousedown = false;
          
          
          function getRandom() {
            return Math.round(255 * Math.random());
          }
          
          
          function getColor() {
            return `rgb(${getRandom()},${getRandom()},${getRandom()})`;
          }
          
          
          const gradient = ctx.createLinearGradient(0, 0, 300, 300);
          gradient.addColorStop(0, getColor());
          gradient.addColorStop(0.6, getColor());
          gradient.addColorStop(1, getColor());
          
          
          function clear() {
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
          }
          
          
          ctx.beginPath();
          ctx.fillStyle = gradient;
          ctx.fillRect(0, 0, 300, 300);
          
          
          function selector(x = 150, y = 150) {
            clear();
            ctx.beginPath();
            ctx.arc(x, y, 5, 0, Math.PI * 2);
            ctx.strokeStyle = "#fff";
            ctx.stroke();
            const { data } = ctx.getImageData(x, y, 1, 1); // 獲取(x,y)點對應的imageData
            const color = `rgba(${data[0]},${data[1]},${data[2]},${data[3] / 255})`
            div.innerText = `color: ${color}`;
            div.style.backgroundColor = color
          }
          
          
          function handleSelector(e) {
            const x = e.offsetX;
            const y = e.offsetY;
            selector(x, y);
          }
          
          
          canvas.addEventListener("mousedown", (e) => {
            mousedown = true;
            handleSelector(e)
          });
          
          
          canvas.addEventListener("mouseup", () => {
            mousedown = false;
          });
          
          
          canvas.addEventListener("mousemove", (e) => {
            if (mousedown) {
              handleSelector(e)
            }
          });
          
          
          selector();




          3.7、畫布狀態:


          • .save():將當前畫布的狀態推入到棧中,例如fillStyle、2D轉換等;
          • .restore():將棧頂元素彈出,恢復上一次推入棧中畫布的狀態;

          當我們需要通過空間轉換來繪制圖形時,保存與恢復畫布的狀態是很關鍵的,因為我們是在同一塊畫布上繪制圖形,而變換都是基于畫布的,這與我們平時使用到的CSS 2D轉換截然不同,所以我們在下一步繪制時要確認此時畫布的狀態是否是我們的理想狀態。

          ctx.save() // 保存畫布初始狀態
          ctx.translate(100,100) // 將畫布原點轉移至(100,100)
          ctx.fillStyle = 'red'
          ctx.fillRect(0,0,50,50)
          
          
          ctx.restore() // 恢復畫布狀態,此時畫布原點為(0,0)
          ctx.fillStyle = 'blue'
          ctx.fillRect(0,0,50,50)


          3.8、幾何變化:


          • .translate(x,y):畫布默認的原點是(0,0),此方法可以切換原點到(x,y)而不需要手動更改繪制圖形的坐標;
          • .rotate(angle):將畫布旋轉一定的角度,angle單位為弧度;
          • .scale(sx,sy):sx為水平方向的縮放比例,sy為豎直方向的縮放比例;
          • .transform(a,b,c,d,e,f):依次為水平縮放、垂直傾斜、水平傾斜、垂直縮放、水平移動、垂直移動;


          const colors = ['red','orange','yellow','green','blue','purple'];
          ctx.translate(150,150)
              
          for(let i = 0; i < 6; i++) {
            ctx.beginPath()
            ctx.fillStyle = colors[i]
            ctx.moveTo(0,0)
            ctx.lineTo(100,0)
            ctx.lineTo(100,50)
            ctx.rotate(Math.PI/3)
            ctx.fill()
          }


          4、綜合實戰


          const p = Math.PI;
          
          
          function clock() {
            const date = new Date();
            const hour = date.getHours()
            const s = date.getSeconds();
            const m = date.getMinutes();
            const h = !!(hour % 12) ? hour % 12 : 12;
            ctx.clearRect(0, 0, canvas.width, canvas.height);
          
          
            ctx.save(); // 保存畫布初始狀態
          
          
            ctx.translate(150, 150);
            ctx.rotate(-p / 2);
          
          
            // 輪廓
            ctx.beginPath();
            ctx.lineWidth = 5;
            ctx.strokeStyle = "#76b2ff";
            ctx.arc(0, 0, 80, 0, p * 2);
            ctx.stroke();
          
          
            // 圓心
            ctx.beginPath();
            ctx.arc(0, 0, 2, 0, p * 2);
            ctx.fill();
          
          
            // 分針、秒針刻度
            for (let i = 0; i < 60; i++) {
              ctx.beginPath();
              ctx.rotate(p / 30);
              ctx.moveTo(75, 0);
              ctx.lineWidth = 4;
              ctx.strokeStyle = "#89f086";
              ctx.lineTo(80, 0);
              ctx.stroke();
            }
          
          
            // 時針刻度
            for (let i = 0; i < 12; i++) {
              ctx.beginPath()
              ctx.rotate(p / 6)
              ctx.moveTo(70, 0)
              ctx.lineTo(80, 0)
              ctx.stroke()
            }
          
          
            ctx.save(); // 保存畫布變換之后的狀態
          
          
            // 秒針
            ctx.beginPath();
            ctx.rotate(s * (p / 30));
            ctx.lineWidth = 2
            ctx.strokeStyle = '#ff6700'
            ctx.moveTo(0, 0);
            ctx.lineTo(80, 0);
            ctx.stroke();
          
          
            // 恢復之前的狀態再保存,時針、分針、秒針都是基于原點以及畫布方向變換后繪制
            ctx.restore();
            ctx.save();
          
          
            // 分針
            ctx.beginPath();
            ctx.rotate(m * (p / 30));
            ctx.lineWidth = 3;
            ctx.strokeStyle = '#6700ff'
            ctx.moveTo(0, 0);
            ctx.lineTo(70, 0);
            ctx.stroke();
          
          
            ctx.restore();
          
          
            // 時針
            ctx.beginPath();
            ctx.rotate(h * (p / 6));
            ctx.lineWidth = 4;
            ctx.moveTo(0, 0);
            ctx.lineTo(60, 0);
            ctx.stroke();
          
          
            ctx.restore(); // 恢復畫布最初狀態
          
          
            document.querySelector('div').innerText = `Now:${h} : ${m} : ${s}  ${hour > 12 ? 'pm' : 'am'}`
          
          
            window.requestAnimationFrame(clock);
          }
          clock();




          5、小結


          隨著互聯網的高速發展,用戶對頁面的視覺和交互有著越來越高的要求,傳統的web開發無法得到滿足,利用Canvas強大的繪圖能力,可以讓網頁顯示的內容更加的豐富多彩,也能給用戶帶來更好的視覺體驗。

          作者:LLS-FE團隊

          來源:微信公眾號:流利說技術團隊

          出處:https://mp.weixin.qq.com/s/bvkx3wOeMvIUU64cktX6iA


          主站蜘蛛池模板: 日韩精品一区二区三区国语自制| 中文乱码精品一区二区三区| 亚洲AV日韩精品一区二区三区| 2014AV天堂无码一区| 人妻av综合天堂一区| 文中字幕一区二区三区视频播放 | 成人一区二区免费视频| 亚洲欧美日韩一区二区三区在线 | 在线日产精品一区| 亚洲AV成人一区二区三区AV| 色一乱一伦一区一直爽| 亚洲AV无码一区二区乱子仑| 日韩人妻一区二区三区蜜桃视频| 清纯唯美经典一区二区| 视频在线观看一区| 国产精品一区二区久久沈樵| 久久人妻无码一区二区| 亚洲中文字幕久久久一区| 天堂va在线高清一区| 国产99视频精品一区| 99久久无码一区人妻a黑| 精品无码一区二区三区爱欲| 人妻体内射精一区二区三四| 午夜福利一区二区三区高清视频 | 久久精品一区二区免费看| 国产AV一区二区三区传媒| 亚洲综合一区二区国产精品| 天堂资源中文最新版在线一区| 亚洲天堂一区二区三区四区| 国产精品一区二区久久精品涩爱| 91成人爽a毛片一区二区| 国产精品视频一区二区三区经| 91在线一区二区| 国产精品无码一区二区在线观 | 中文字幕日韩一区二区三区不卡| 久久无码人妻一区二区三区午夜 | 一区二区3区免费视频| 久久亚洲中文字幕精品一区四| 亚洲线精品一区二区三区影音先锋| 亚洲永久无码3D动漫一区| 99久久综合狠狠综合久久一区|