# Canvas 關於橡皮擦
### HTML DOM classList 屬性
:::info
classList 屬性返回元素的類名,作為 DOMTokenList 對象。
該屬性用於在元素中添加,移除及切換 CSS 類。
classList 屬性是只讀的,但你可以使用 add() 和 remove() 方法修改它。
:::
* add ->在元素中添加一個或多個類名。如果指定的類名已存在,則不會添加
* remove ->移除元素中一個或多個類名。注意: 移除不存在的類名,不會報錯。
* [更多方法在此](https://www.runoob.com/jsref/prop-element-classlist.html)
* [更多方法在此](https://ithelp.ithome.com.tw/articles/10241358)
```javascript=
// 觸發橡皮擦
toolbar.addEventListener("click", (e) => {
if (e.target.id === "eraser") {
eraserEnabled = true
// 透過 active 進行切換橡皮擦跟畫筆,使用橡皮擦->開,畫筆->關
eraser.classList.add("active")
brush.classList.remove("active")
ctx.globalCompositeOperation = "destination-out"
}
if (e.target.id === "brush") {
eraserEnabled = false
eraser.classList.remove("active")
brush.classList.add("active")
ctx.globalCompositeOperation = "source-over"
}
})
```
### globalCompositeOperation -> [合成效果](https://developer.mozilla.org/zh-TW/docs/Web/API/Canvas_API/Tutorial/Compositing)
:::info
新繪製的圖形總會覆蓋在之前的圖形上,對大多數情況來說這相當正常,不過它也限制了圖形繪製的順序。其實我們可以透過 globalCompositeOperation 屬性來改變這項預設行為。
:::
利用 globalCompositeOperation,
我們可以將新圖形繪製在舊圖形之下、
遮蓋部分區域、清除畫布部分區域 (不同於 clearRect() 函式只能清除矩形區域)。
**globalCompositeOperation 屬性**
將一個源(新的)圖像繪製到目標(已有的)的圖像上。
:::info
源圖像 = 打算放置到畫布上的繪圖。
目標圖像 = 已經放置在畫布上的繪圖。
:::
```javascript=
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="blue";
ctx.fillRect(20,20,75,50);
ctx.fillStyle="red";
ctx.globalCompositeOperation="source-over";
ctx.fillRect(50,50,75,50);
```
先執行藍色區域,再增添紅色矩形 -> globalCompositeOperation="source-over"
超越舊的代表 -> 舊的落後在後面

**globalCompositeOperation = type**
[type 可指定為以下多種合成設定之一](https://www.w3big.com/zh-TW/tags/canvas-globalcompositeoperation.html#gsc.tab=0)
每一種合成設定均將套用到新繪製的圖形上。
```javascript=
var gco=new Array();
gco.push("source-atop");在目標圖像頂部顯示源圖像。源圖像位於目標圖像之外的部分是不可見的。
gco.push("source-in");在目標圖像中顯示源圖像。只有目標圖像之內的源圖像部分會顯示,目標圖像是透明的。
gco.push("source-out");在目標圖像之外顯示源圖像。只有目標圖像之外的源圖像部分會顯示,目標圖像是透明的。
gco.push("source-over");默認。在目標圖像上顯示源圖像。
gco.push("destination-atop");在源圖像頂部顯示目標圖像。目標圖像位於源圖像之外的部分是不可見的。
gco.push("destination-in");在源圖像中顯示目標圖像。只有源圖像之內的目標圖像部分會被顯示, 源圖像是透明的。
gco.push("destination-out");在源圖像之外顯示目標圖像。只有源圖像之外的目標圖像部分會被顯示,源圖像是透明的。
gco.push("destination-over");在源圖像上顯示目標圖像。
gco.push("lighter");顯示源圖像 + 目標圖像。
gco.push("copy");顯示源圖像。忽略目標圖像。
gco.push("xor");使用異或操作對源圖像與目標圖像進行組合。
......
ctx.fillStyle="blue";
ctx.fillRect(10,10,50,50);
ctx.globalCompositeOperation=gco[n];
ctx.beginPath();
ctx.fillStyle="red";
ctx.arc(50,50,30,0,2*Math.PI);
ctx.fill();
......先有藍方->目標圖像(舊的) 才有紅圈 -> 源圖像(新)
```
