iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
0

變形效果

在使用變形效果以前,通常會先儲存畫布,以下為畫布的儲存和復原方法:

畫布狀態儲存與復原

方法 描述
save() 儲存現階段畫布狀態
restore() 復原最近一次儲存的畫布狀態

每一次呼叫save(),畫布狀態就會存進一個stack中,畫布的狀態包含:

  • strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 屬性的屬性值
  • 套用過的變形效果
  • 目前截圖路徑

而每一次呼叫restore(),最近一次儲存的畫布便會從堆疊中被取出,然後還原到此畫布狀態。

變形方法

可以想像成是移動、旋轉、縮放畫布上的座標軸

方法 描述
translate(x, y) 移動網格上的畫布,將畫布原點(0,0)移到(x,y),其中x代表水平距離、y代表垂直距離
rotate(x) 以畫布原點為中心,順時針旋轉畫布x弧度(弧度 = Math.PI * 角度 / 180)
scale(x, y) x代表縮放畫布水平網格單位x倍,y代表縮放畫布垂直網格單位y倍,輸入1.0不會造成縮放。如果輸入負值會造成座標軸鏡射。
transform(a, b, c, d, e, f) 上面三個變形效果都是設定在這個變形矩陣,呼叫Transform會拿目前的變形矩陣,a代表水平縮放圖像,b代表水平偏移圖像,c代表垂直偏移圖像,d代表垂直縮放圖像,e代表水平移動圖像,f代表垂直移動圖像
setTransform(a, b, c, d, e, f) 將目前矩陣當作恆等矩陣,也就是設成預設矩陣

最好在做變形效果前儲存畫布狀態,如果要恢復先前狀態,只要呼叫restore()就能恢復畫布狀態,如忘記儲存和恢復畫布狀態,繪圖區域很容易超出邊界,發生圖案不見的狀況。

因為怕自己以後忘記transform的矩陣是怎麼來的,在此紀錄一下:
https://ithelp.ithome.com.tw/upload/images/20200917/20111500CYC0RQq1pg.png

  • a代表水平縮放圖像,影響在縮放或旋轉影像時沿X軸的像素定位
  • b代表水平偏移圖像,影響在旋轉或傾斜影像時沿Y軸的像素定位
  • c代表垂直偏移圖像,影響在旋轉或傾斜影像時沿X軸的像素定位
  • d代表垂直縮放圖像,影響在縮放或旋轉影像時沿Y軸的像素定位
  • e代表水平移動圖像,沿X軸移動
  • f代表垂直移動圖像,沿Y軸移動

小小範例

codepen範例連結

ctx.translate(150,150) //移動畫布原點至(150,150)
 for(let i=1; i<12; i++){ //畫12圈
 ctx.save() //儲存畫布狀態
 ctx.fillStyle='rgb('+(25*i)+',255,'+ (255-25*i)+')' //決定每一圈填滿顏色
 for(let j=0;j<i*6;j++){ //決定每一圈畫幾個矩形
  ctx.rotate(Math.PI*2/(i*6)) //旋轉畫布
  ctx.beginPath()
  ctx.rect(0,i*12.5,6,6) //畫每一圈矩形
  ctx.fill()
}
  ctx.restore() //恢復一開始畫布還沒旋轉狀態,讓下一圈的也從頭畫
}

最後成果:
https://ithelp.ithome.com.tw/upload/images/20200917/20111500AMQinnkNvz.png

~如有疑問或是錯誤,歡迎不吝指教~

參考來源
[1]https://developer.mozilla.org/zh-TW/docs/Web/API/Canvas_API/Tutorial/Transformations
[2]https://www.w3school.com.cn/tags/html_ref_canvas.asp
[3]https://www.runoob.com/w3cnote/html5-canvas-intro.html
[4]https://www.twle.cn/l/yufei/canvas/canvas-basic-geometric-transform.html


上一篇
【Day07】Canvas-繪製影像
下一篇
【Day09】Canvas-合成效果&裁剪路徑
系列文
菜雞用Canvas/Pixi動動動動動起來30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言