canvasでいろんなマスクをかける


いろんな形のマスクをかけて画像をくりぬいてみる。

## 下準備

とりあえずマスクをかける画像を描画する。


```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Language" content="ja">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0,minimal-ui">
<title>mask</title>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script type="text/javascript" src="./script.js"></script>
</body>
</html>
```

```javascript:script.js
(function () {

    var canvas = document.getElementById('canvas');
    canvas.width = 960;
    canvas.height = 540;

    var context = canvas.getContext('2d');

    var bgImg = new Image();
    bgImg.onload = function () {
        context.globalCompositeOperation = 'source-over';
        context.drawImage(bgImg, 0, 0, canvas.width, canvas.height);
    };
    bgImg.src = './bg.jpg';

})();
```

ここまでで↓の画像が表示されるので準備完了。

![bg.jpg](https://qiita-image-store.s3.amazonaws.com/0/53664/55707f2b-569e-5b71-ca47-cb370c6ed2d9.jpeg "背景を描画した状態")


## マスクをかける

合成処理を決める`globalCompositeOperation`プロパティを変更して上書き描画することでマスクをかける。
`globalCompositeOperation`については[HTML5.JP - globalCompositeOperation プロパティ](http://www.html5.jp/canvas/ref/property/globalCompositeOperation.html)がわかりやすい。

現状、`globalCompositeOperation`の値は`source-over`(デフォルト値)で、既に`drawImage`で画像が描画されている。
これに対してマスクをかけるには、`globalCompositeOperation`を`destination-in`にしてから適当な形を描画すればよい。

```javascript:script.js
(function () {

    var canvas = document.getElementById('canvas');
    canvas.width = 960;
    canvas.height = 540;

	// 中央にマスクをかけるための値を変数にいれておく
    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;

    var context = canvas.getContext('2d');

    var bgImg = new Image();
    bgImg.onload = function () {
        context.globalCompositeOperation = 'source-over';
        context.drawImage(bgImg, 0, 0, canvas.width, canvas.height);
        drawMask();
    };
    bgImg.src = './bg.jpg';
    
    var drawMask = function () {
        // globalCompositeOperation に destination-in を設定
        context.globalCompositeOperation = 'destination-in';
        var size = 200;
        var half = size / 2;
        // 矩形を描画
        context.fillRect(centerX - half, centerY - half, size, size);
    };

})();
```

すると↓のように、あとから描画した部分のみ画像が表示される。

![Kobito.Hxzl3F.png](https://qiita-image-store.s3.amazonaws.com/0/53664/18023b69-4141-323c-d9c5-3e1e46ba3890.png "矩形のマスクがかかった状態")


### マスクの形を変える

`globalCompositeOperation`を変更したあとの描画内容次第でマスクの形が決まる。
arcや、pathを使ってマスクを自由な形にすることもできる。

#### ark

```javascript:script.js
    var drawMask = function () {
        context.globalCompositeOperation = 'destination-in';
        var size = 200;
        // 円を描画
        context.arc(centerX, centerY, size, 0, Math.PI * 2);
        context.fill();
    };
```

![Kobito.geU8c3.png](https://qiita-image-store.s3.amazonaws.com/0/53664/2b0c3ee5-9878-16df-2ea9-740915891d83.png "円形のマスクがかかった状態")



#### path

```javascript:script.js
    var drawMask = function () {
        context.globalCompositeOperation = 'destination-in';
        // pathで三角形を描画
        context.beginPath();
        context.moveTo(0, 0);
        context.lineTo(centerX, centerY);
        context.lineTo(canvas.width, 0);
        context.closePath();
        context.fill();
    };
```

![Kobito.mgEfHB.png](https://qiita-image-store.s3.amazonaws.com/0/53664/e0196036-4012-b246-18fb-3bcd61bcebef.png "pathで作った三角形のマスクがかかった状態")

## マスクに画像を使う

pathを使えばマスクをある程度自由な形にすることができるが、複雑なマスクをかけるのは大変。
複雑な形のマスクをかけたい場合は、透過画像を用いると簡単にできる。

用意するのは↓のような、マスクとなる部分以外が透過になっている画像。透過でない部分の色は意識しなくておｋ。

この画像をいままでと同じように描画する。

<img src="https://qiita-image-store.s3.amazonaws.com/0/53664/4814aaa4-49bc-2cb9-5e3c-55db2d4ad36c.png" width="100" alt="マスクに使う星型の透過画像">

```javascript:script.js
    var drawMask = function () {
        context.globalCompositeOperation = 'destination-in';
        // 星型の透過画像を描画
        var maskImg = new Image();
        maskImg.onload = function () {
            context.drawImage(maskImg, centerX - (maskImg.width / 2), centerY - (maskImg.height / 2), maskImg.width, maskImg.height);
        };
        maskImg.src = './star.png';
    };
```

すると星型のマスクがかかる。

![Kobito.YQNXkP.png](https://qiita-image-store.s3.amazonaws.com/0/53664/611c79f5-6a53-8aad-1410-e4ae00dea6ad.png "星型のマスクがかかった状態")

画像を変えれば、更に複雑なマスクをかけることも可能。

![Kobito.Yts25s.png](https://qiita-image-store.s3.amazonaws.com/0/53664/6e933aaf-c9f5-e552-a83d-697217d02583.png "ミッキーの形のマスクがかかった状態")

ﾊﾊｯ

[demo](http://keiskimu.com/Qiita/mask/)