みかづきブログ・カスタム

基本的にはちょちょいのほいです。

html2canvasでmix-blend-modeを使っているページのスクリーンショットを撮る 📸



ことの発端

以前、html2canvasを使ってページのスクリーンショットを撮る検証を行いました。

blog.kimizuka.org

この検証以降、DOMのレンダリング結果を画像化したいときは、積極的にhtml2canvasを使っていたのですが、最近、CSSのmix-blend-modeが反映されていないことに気づきました。

blog.kimizuka.org

改めて、ドキュメントを確認してみると、しっかりとUnsupported CSS propertiesにmix-blend-modeが記載されています。

github.com

どうにかして、mix-blend-modeのレンダリング結果も画像化できないかと、調査を始めたのがことの発端です。


調査(Issueを発見)

Issueは簡単に見つかりました。

github.com

CanvasにもglobalCompositeOperationという合成演算方法の指定ができるコンテキストのプロパティがあるので、html2canvasのソースをうまいこと編集すればいける!ということは共通認識のようです。

developer.mozilla.org


さらに調査(プルリクエストを発見)

Issueを辿ると、プルリクエストを見つけました。

github.com

  • Edgeでテストできていない
  • 透明な要素で機能しない

という注意事項はあれど、基本的な修正は完了しているようです。
早速、クローンして試してみます。


検証

https://develop.kimizuka.org/html2canvas-mix-blend-mode/


検証用に3つの要素を作ってみました。

左(ブレンドモードなし)

赤い要素の中に青い要素を入れています。
これが基準です。

HTML
<style>
.box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px; height: 200px;
}

.mini-box {
  width: 100px; height: 100px;
}

.red {
  background: red;
}

.blue {
  background: blue;
}
</style>
<div class="box red">
  <div class="mini-box blue"></div>
</div>



中央(ブレンドモードあり)

DOM構造は左の要素と同じです。
子要素にmix-blend-modeでscreenを指定しているので、青い要素がピンクの様に見えます。

HTML
<style>
.box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px; height: 200px;
}

.mini-box {
  width: 100px; height: 100px;
}

.red {
  background: red;
}

.blue {
  background: blue;
}

.screen {
  mix-blend-mode: screen;
}
</style>
<div class="box red">
  <div class="mini-box blue screen"></div>
</div>



右(ブレンドモードあり)

DOMの構造を若干変えています。
mix-blend-modeを設定している要素は無色で、その子要素に色をつけています。

HTML

<style>
.box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px; height: 200px;
}

.mini-box {
  width: 100px; height: 100px;
}

.red {
  background: red;
}

.blue {
  background: blue;
}

.screen {
  mix-blend-mode: screen;
}
</style>
<div class="box red">
  <div class="screen">
    <div class="mini-box blue"></div>
  </div>
</div>

この状態でhtml2canvasを使って画像化してみます。


画像化

画像化しました。

左(ブレンドモードなし)

ブレンドモードを使っていないので、問題なく画像化できています。


中央(ブレンドモードあり)

ブレンドモードを使っているものの、そのレンダリング結果がしっかりと画像化できています。
ちなみにEdgeでも試してみましたが、問題なく画像化できました。


右(ブレンドモードあり)

ブラウザで観覧した際とhtml2canvasで画像化した際で差異が出ています。
html2canvasで生成した画像にはブレンドモードが効いていません。


結論

このブランチのソースコードを使えば、mix-blend-modeに対応した状態で画像化することが可能。
ただし、入れ子にしたりすると評価されなくなるので、できるだけシンプルな構造にするのが望ましい。

github.com