1
| <canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas>
|
基本用法
綁定 canvas
1 2 3 4 5
| const cvs=document.querySelector('#cvs') // 宣告 Canvas Content Object getContext() 2d webgl // 2D 畫面 3D 畫面 const ctx= cvs.getContext('2d')
|
Fill 填滿
1 2 3 4 5 6
| // 填滿顏色 ctx.fillStyle="red" // 透明度 1 為不透明 0 為完全透明 ctx.globalAlpha=0.5 // fillRect(X,Y,weight,height) ctx.fillRect(50,50,100,100)
|
Stroke 描邊
1 2 3 4
| // 描邊顏色 ctx.strokeStyle='blue' // strokeRect(X,Y,weight,height) ctx.strokeRect(100,100,100,100)
|
Path 路徑
1 2 3 4 5 6 7 8 9 10
| // 開啟路徑 ctx.beginPath() // 移動到當前所在位置 moveTo(X,Y) ctx.moveTo(300,300) // 與設定座標畫一直線 lineTo(X,Y) ctx.lineTo(400,500) // 關閉路徑 ctx.closePath() // 選擇顯現方式 stoke() fill() ctx.stroke()
|
繪製多邊形
1 2 3 4 5 6
| ctx.beginPath() ctx.moveTo(300,300) ctx.lineTo(100,500) ctx.lineTo(500,500) ctx.closePath() ctx.fill()
|
影像處理、濾鏡
影像處理
1 2 3 4 5 6
| let img=new Image() img.src='../head.png' img.onload=function () { // 註冊 load 事件,圖片載入完成後,入完成後,才做繪製 // drawImage(img,X,Y,width,height) ctx.drawImage(img,0,0,cvs.width,cvs.height) }
|
濾鏡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // Html <button onclick="invertColor()">影像反轉</button> <canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas> // JavaScript function invertColor(){ let pixels=ctx.getImageData(0,0,cvs.width,cvs.height) //一個像素佔據 4 個資料 (bytes) 。 r,g,b,a(範圍 0 ~ 255) let pixelsData=pixels.data for (let i = 0; i < pixelsData.length; i+=4) { pixelsData[i]=255-pixelsData[i] pixelsData[i+1]=255-pixelsData[i+1] pixelsData[i+2]=255-pixelsData[i+2] } ctx.putImageData(pixels,0,0) }
|
檔案輸入、輸出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| // Html
<input type="file" onchange="loadFile(this)"> <button onclick="saveFile()">儲存檔案</button> <a href="" id="download"></a> <canvas id="cvs" width="800" height="600" style="border: 1px solid #000000;"></canvas>
// JavaScript
function loadFile(input){ // 抓取 input files let files=input.files[0] // 把 files 轉成網址 let url=URL.createObjectURL(files) let img=new Image() img.src=url img.onload=function () { ctx.drawImage(img,0,0,cvs.width,cvs.height) } }
function saveFile() { const link=document.querySelector('#download') // a 連結下載格式 link.download='image.jpg' // canvas 輸出格式 link.href=cvs.toDataURL('image/jpeg') link.click() }
|
畫線
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| let painting=false // 按下滑鼠代表開始畫畫 cvs.addEventListener('mousedown',startPosition) // 放下滑鼠代表完成畫畫 cvs.addEventListener('mouseup',finishedPosition) // 滑鼠移動代表正在畫畫 cvs.addEventListener('mousemove',draw)
function startPosition() { painting=true } function finishedPosition(e) { painting=false ctx.beginPath() } function draw(e) { // 如果正在畫畫就 return if(!painting)return if(stroke && !eraser){ ctx.lineWidth=size ctx.strokeStyle=color ctx.lineCap='round' ctx.lineTo(e.clientX,e.clientY) ctx.stroke() ctx.beginPath() ctx.moveTo(e.clientX,e.clientY) }else if(!stroke && eraser){ ctx.lineWidth=size ctx.strokeStyle='#E8E8E8' ctx.lineCap='round' ctx.lineTo(e.clientX,e.clientY) ctx.stroke() ctx.beginPath() ctx.moveTo(e.clientX,e.clientY) } }
|
Undo、Redo
創建一個物件,每次畫完就擷取圖片存在物件裡,物件[步驟]讀取畫面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| let restore_array=[] let step=-1
function finishedPosition(e) { painting=false ctx.beginPath() console.log(e.type) if(e.type!='mousedown'){ restore_array.push(ctx.getImageData(0,0,cvs.width,cvs.height)) step++ } if(restore_array.length>0){ console.log(1) domUndo.classList.add('btn-active') }else{ domUndo.classList.remove('btn-active') } }
function undo(e) { e.preventDefault() if(step<=0){ allClear() domUndo.classList.remove('btn-active') }else{ console.log(restore_array) domUndo.classList.add('btn-active') step-- ctx.putImageData(restore_array[step],0,0) } if(step<restore_array.length&&step>=0){ domRedo.classList.add('btn-active') }else{ domRedo.classList.remove('btn-active') } } function redo(e) { e.preventDefault() console.log(step) if(step==restore_array.length||step<0){ return }else if(step<restore_array.length){ step++ ctx.putImageData(restore_array[step],0,0) } }
|