Photo Timelineやモックアップ作成アプリ、Image Crop Studioを開発していて、一番苦労した部分があります。
各アプリはこちら
Photo Timeline
ビフォーアフターの画像やコラージュが作れるアプリ

モックアップ作成アプリ
ポートフォリオなどに使えるモックアップが作れるアプリ
Image Crop Studio
簡単にトリミングができるアプリ

苦労した点は、「画面で見えているプレビュー」と「保存された画像」が一致しないという問題です。
最初は「Canvasって画像を書くだけでしょ?」くらいに思っていました。
ですが実際に開発してみると、
- 保存すると位置がズレる
- サイズが違う
- 余白が増える
- 拡大率がおかしい
という問題が次々に発生しました。
今回は、私がCanvasを理解するまでに学んだことをまとめます。
Canvasとは?
Canvas(HTML5 Canvas)は、ブラウザ上で画像や図形、文字などを自由に描画できるHTMLの要素です。
通常のHTMLでは、画像や文字を配置して画面を作りますが、CanvasではJavaScriptを使って一つひとつ描画していきます。
例えば、
- 写真の編集
- モックアップ画像の生成
- SNS投稿画像の作成
- お絵描きアプリ
- グラフや図形の表示
- ゲーム
など、多くのWebアプリで利用されています。
Canvasには次のような特徴があります。
- JavaScriptで自由に描画できる
- PNGやJPEGとして画像を書き出せる
- 図形・画像・文字を組み合わせられる
- 描画速度が速く、リアルタイム編集にも向いている
今回私が開発したPhoto TimelineやImage Crop Studioでも、最終的な画像を生成するためにCanvasを利用しています。
ただ、Canvasは「画像を置く」だけの仕組みではありません。
「座標を指定して一枚のキャンバスにすべて描画する」という考え方になっているため、最初は少し戸惑いました。
実際に開発を進める中で、一番苦労したのがプレビュー画面と書き出した画像を一致させることでした。
次は、その原因について紹介します。
なぜプレビューと書き出しが違うの?
一番最初に勘違いしていたのは、
「画面に表示されているもの=保存される画像」
ではないということです。
実はCanvasには
- ブラウザ上で表示している見た目
- Canvas内部の描画領域
という2つの世界があります。
例えば
画面表示
1000 × 600
Canvas内部
2000 × 1200
という状態も普通に存在します。
HTMLでCSSだけを使ってCanvasを拡大縮小すると、見た目と実際の描画サイズが変わってしまいます。MDNでも、CanvasはCSSではなくwidth・height属性で描画領域を指定することが推奨されています。
そのため
「画面ではちょうどいい」
と思っていても、
保存すると全然違う位置になることがあります。
Canvasは座標ですべて管理している
CanvasはPhotoshopのようなレイヤーではありません。
基本的には
画像A
x = 100
y = 200
画像B
x = 350
y = 120
というように、
すべて座標で管理しています。
つまり
- 画像
- テキスト
- 図形
全部
drawImage(...)
fillText(...)
fillRect(...)
で描画しているだけです。
「見た目を動かす」のではなく、
座標を書き換えている
という感覚になります。
CSSで位置を動かしても保存画像には反映されない
これもかなりハマりました。
例えば
transform: scale(0.8);
や
translate(...)
で見た目を調整しても、
Canvasへ保存するときには関係ありません。
保存画像では
Canvasが持っている
x
y
width
height
だけが使われます。
つまり
画面だけCSSで動かすと
プレビューと保存画像がズレます。
私が一番苦労したのは倍率
Photo TimelineやImage Crop Studioでは
プレビュー画面は小さく表示しています。
例えば
保存サイズ
1200px
でも
画面では
400px
くらいで表示しています。
このとき
ドラッグした座標は
画面
の座標になります。
しかし保存時は
1200px
基準になります。
つまり
保存座標
=
画面座標 × 倍率
という計算を毎回行わないといけません。
プレビュー専用の座標と保存用の座標を分けた
最初は
座標は1つ
で管理していました。
しかし途中で限界が来ました。
最終的には
元データ
↓
倍率計算
↓
プレビュー表示
↓
倍率計算
↓
保存
という流れに変更しました。
これによって
- ドラッグ位置
- 拡大率
- 書き出し
が一致するようになります。
Canvasは「描き直す」世界
HTMLでは
<div>
を動かしているイメージですが、
Canvasは違います。
Canvasでは
背景
↓
画像
↓
文字
↓
装飾
を
毎回全部描き直しています。
そのため
画像を書き出す処理では
もう一度
drawImage()
drawImage()
fillText()
を最初から実行しています。
この考え方を理解すると
Canvasがかなり分かりやすくなりました。
Canvasは怖くない!
正直、Canvasは最初かなり難しかったし嫌厭していました。
「画面の表示」と「Canvas内部の座標」は別物という考え方が大切です。
一度仕組みが分かると画像編集アプリやモックアップ作成ツールなど、Webだけでは実現できない表現を作れるようになります。
私自身もまだ勉強中ですが、今ではWebアプリ開発に欠かせない技術の一つになっています。
各アプリはこちら
Photo Timeline
ビフォーアフターの画像やコラージュが作れるアプリ

モックアップ作成アプリ
ポートフォリオなどに使えるモックアップが作れるアプリ
Image Crop Studio
簡単にトリミングができるアプリ
