HTML Canvas の描画設定を保存し、後で描画設定を復帰させる

HTML Canvas の描画設定を保存し、後で描画設定を復帰させるコードを紹介します。

概要

HTML Canvas のコンテキストではアクティブなペンのカラーやペンの幅、塗りつぶしのカラーなどの描画設定は1つしか保持できず、描画のたびに切り替える必要があります。 HTML Canvasでは描画設定を一時的に保存し、後で描画設定を復帰させることができます。この記事では、HTML Canvasの描画設定の保存と復帰のコードを紹介します。

書式

描画設定の保存

描画設定の保存をする場合はsaveメソッドを利用します。
(HTML Canvasのコンテキスト).save();

描画設定の復帰

描画設定の復帰をする場合はrestoreメソッドを利用します。
(HTML Canvasのコンテキスト).restore();

実施例

コード

下記のHTMLファイルを作成します。
SimpleRestore.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>

  <script type="text/javascript">
    function draw() {
      var canvas = document.getElementById('SimpleCanvas');

      if (!canvas || !canvas.getContext) {
        return false;
      }
     
      var sx = 20;
      var sy = 20;

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

      context.fillStyle = '#fffeb4';
      context.strokeStyle = '#f18e00';
      context.lineWidth = 2;
      context.save();

      for (i = 0; i < 3; i++) {
        context.beginPath();
        context.rect(sx, sy, 160, 80);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10, sy + 20, 40, 40);
        context.fillStyle = '#b7f2ff';
        context.fill();
        context.lineWidth = 1;
        context.setLineDash([4, 4, 8, 4]);
        context.strokeStyle = '#007790';
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 50, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 100, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        sx += 170;
        sy += 90;
        context.restore();
      }
    }
  </script>
</head>
<body onload="draw()" style="background-color:#D0D0D0;">
  <canvas id="SimpleCanvas" width="640" height="360" style="background-color:#FFFFFF;"></canvas>
  <div>Canvas Demo</div>
</body>
</html>

解説

HTML Canvasのコンテキスト取得についての処理はこちらの記事を参照してください。

コンテキストに塗りつぶしのカラーや線幅、線のカラーを設定します。
設定後にsave()メソッドを呼び出し、設定を保存します。
      context.fillStyle = '#fffeb4';
      context.strokeStyle = '#f18e00';
      context.lineWidth = 2;
      context.save();

ループで3回処理を実行します。
for (i = 0; i < 3; i++) {
  /* 中略 */
}

ループ外で設定された描画設定(黄色)で 160×80 の矩形を描画します。
    context.beginPath();
    context.rect(sx, sy, 160, 80);
    context.fill();
    context.stroke();

水色の塗りつぶし、青線の破線に切り替えて 40×40 の正方形を3つ描画します。
    context.beginPath();
    context.rect(sx + 10, sy + 20, 40, 40);
    context.fillStyle = '#b7f2ff';
    context.fill();
    context.lineWidth = 1;
    context.setLineDash([4, 4, 8, 4]);
    context.strokeStyle = '#007790';
    context.stroke();

    context.beginPath();
    context.rect(sx + 10 + 50, sy + 20, 40, 40);
    context.fill();
    context.stroke();

    context.beginPath();
    context.rect(sx + 10 + 100, sy + 20, 40, 40);
    context.fill();
    context.stroke();

描画位置のオフセットを変更し、restore() メソッドを呼び出し保存していた描画設定を復帰します。
    sx += 170;
    sy += 90;
    context.restore();

実行結果

上記のHTMLファイルをWebブラウザで表示します。下図のページが表示されます。
3つ目の長方形は水色の点線で描画されていることがわかります。save()メソッドで保存された設定はresotre()メソッドで復帰されると保存状態が無くなってしまい、 2度目のresotre()メソッドの呼び出しではsaveされた内容を復帰できず、現在の設定のまま次の描画処理が実行されてしまうことが確認できます。

3つとも同じ描画にする場合

方法1

先のコードではsave()1回の処理で1回分のrestore()の復元しかできないため、3つ目の長方形のカラーが黄色にならないことがわかりました。 3つの長方形を同じスタイルで描画する場合は、黄色の長方形を描画した直後に毎回save()メソッドを呼び出すことで、毎回のresotre()で元の描画設定に復帰できるようにします。
    function draw() {
      var canvas = document.getElementById('SimpleCanvas');

      if (!canvas || !canvas.getContext) {
        return false;
      }
     
      var sx = 20;
      var sy = 20;

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

      context.fillStyle = '#fffeb4';
      context.strokeStyle = '#f18e00';
      context.lineWidth = 2;
      context.save();

      for (i = 0; i < 3; i++) {
        context.beginPath();
        context.rect(sx, sy, 160, 80);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10, sy + 20, 40, 40);
        context.fillStyle = '#b7f2ff';
        context.fill();
        context.lineWidth = 1;
        context.setLineDash([4, 4, 8, 4]);
        context.strokeStyle = '#007790';
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 50, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 100, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        sx += 170;
        sy += 90;
        context.restore();
      }
    }

上記のHTMLファイルをWebブラウザで表示すると下図のページが表示されます。3つとも同じスタイルで描画できています。

方法2

事前にrestoreで復帰する回数分 saveメソッドを呼び出しておくことで複数回のrestoreができるようにする方法です。
下記のコードでは2回save()メソッドを呼び出しているため、2回分restoreメソッドで復帰できます。
    function draw() {
      var canvas = document.getElementById('SimpleCanvas');

      if (!canvas || !canvas.getContext) {
        return false;
      }
     
      var sx = 20;
      var sy = 20;

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

      context.fillStyle = '#fffeb4';
      context.strokeStyle = '#f18e00';
      context.lineWidth = 2;
      context.save();
      context.save();

      for (i = 0; i < 3; i++) {
        context.beginPath();
        context.rect(sx, sy, 160, 80);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10, sy + 20, 40, 40);
        context.fillStyle = '#b7f2ff';
        context.fill();
        context.lineWidth = 1;
        context.setLineDash([4, 4, 8, 4]);
        context.strokeStyle = '#007790';
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 50, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        context.beginPath();
        context.rect(sx + 10 + 100, sy + 20, 40, 40);
        context.fill();
        context.stroke();

        sx += 170;
        sy += 90;
        context.restore();
      }
    }

下図の表示結果となります。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2020-10-25
作成日: 2020-10-25
iPentec all rights reserverd.