初回キャンバスと座標
本ツールにおける描画の中核は,HTML5が提供する<canvas>要素と2Dレンダリングコンテキスト(CanvasRenderingContext2D)を利用したピクセル操作です.ツールの初回読み込み時,ブラウザ上には内部解像度が幅1000ピクセル,高さ600ピクセルに設定されたキャンバス領域が生成されます.
このアスペクト比(5:3)は固定されており,利用者の画面サイズやウィンドウ幅に応じて表示上のサイズが縮小・拡大された場合でも,キャンバス内部の座標系は常に1000x600を維持する仕様となっています.
描画開始の基点となる初期状態では,背景全体を白色(#ffffff)の矩形(fillRect)で塗りつぶす処理が実行されます.これにより,透過情報の無い白無地のキャンバスが準備され,最初の履歴としてブラウザのメモリ上に記録されます.
また,ユーザーがマウスやタッチパネルでキャンバスに触れた際の座標取得には,getBoundingClientRectメソッドを用いて画面上の要素の表示位置や実寸を取得し,内部解像度との比率を計算する処理を挟んでいます.この計算式により,ブラウザのズーム機能やレスポンシブ配置によって見た目のサイズが変化していても,マウスポインタや指のタッチ位置とキャンバス内部のピクセル座標のズレを補正し,意図した位置から正確に線を引き始めることが可能となっています.
このような座標計算処理は全てブラウザ内で行われています.
ペンの太さと透明度
描画における筆致の調整機能として,本ツールではペンの太さ(ブラシサイズ)と不透明度の2つのパラメータをスライダー操作で変更できるUIを提供しています.ペンの太さは1ピクセルから最大80ピクセルまでの範囲で1ピクセル単位で指定可能です.ユーザーがスライダーを動かすとReactのステートが更新され,次に線を描き始めるときのCanvasのlineWidthに反映されます.
不透明度は1%から100%までの値を指定でき,描画時に適用されるglobalAlphaプロパティを通じてキャンバス上のピクセルの濃淡を制御します.不透明度を下げた状態で線を重ねると,水彩画のように色が重なり合う表現が可能となります.さらに描画線の先端および線同士の結合部分は,それぞれlineCap属性およびlineJoin属性に「round(丸型)」を指定することで,急な曲線を引いた際でも角張った不自然な描画を防ぎ,滑らかなストロークを実現しています.
描画色については,あらかじめ用意された10種類のカラープリセット(黒,赤,オレンジ,黄,緑,シアン,青,紫,ピンク,白)から選択できるほか,HTMLの<input type="color">を利用したカラーピッカーにより,16進数カラーコードによる任意のカスタムカラー(#RRGGBB)を指定することも可能です.
これらの太さ,透明度,色の各種設定は描画イベントが発生する直前に2Dコンテキストに対して適用され,設定変更ごとにプレビュー領域で現在のブラシ状態を視覚的に確認できるよう実装されています.
消しゴムとUndo
本ツールには描画の修正を補助するため,消しゴム機能および操作の取り消し・やり直し機能(Undo/Redo)が実装されています.消しゴム機能は,一般的なペイントツールのように「白色を上塗りする」のではなく,合成モード(globalCompositeOperation)を「destination-out」に変更することで実現されています.
このモードが有効な状態でキャンバス上をドラッグすると,既存のピクセルデータのアルファチャンネル(透明度)が削り取られ,透明または半透明なピクセルへと変わります.初期の白背景とは異なります.消しゴムの太さもペンの太さスライダーと連動しており,最大80ピクセルの範囲で広範囲の消去が可能です.
一方,Undo(元に戻す)およびRedo(やり直す)機能は,キャンバスの描画状態を画像データとして配列(履歴スタック)に保存する手法を用いています.ユーザーがマウスのボタンを離す,またはタッチ操作を終了する(mouseup, mouseleave, touchend)たびに,現在のキャンバス全体がtoDataURLメソッドによってData URI形式の文字列に変換され,履歴配列の末尾に追加されます.
Undoボタンをクリックすると,現在のインデックスを1つ戻し,保存されていた過去の画像文字列からImageオブジェクトを生成してキャンバス全体に再描画(drawImage)します.これにより,レイヤーやベクターデータのような複雑な構造を持たせることなく,メモリ上で連続したビットマップ画像の差し替えによる履歴管理を行っています.
全消去と履歴の境界
キャンバス全体を初期状態に戻す機能として,「キャンバス消去」ボタンを配置しています.この機能が実行されると,単に履歴を最初からやり直すのではなく,現在の描画コンテキストの状態(合成モードや透明度)を一時的に退避(save)させた上で,キャンバスの幅と高さ(1000x600ピクセル)全体に白色(#ffffff)の矩形を描画する処理が行われます.
全消去が完了すると退避していたコンテキストの状態が復元(restore)され,消去直前のブラシ設定を維持したまま直ちに次の描画へ移行できるよう設計されています.
履歴管理における境界として,この全消去操作も「1つの描画アクション」として扱われます.つまり,全消去を実行した直後にキャンバスの状態が文字列化されて履歴スタックに積まれるため,誤って全消去ボタンを押してしまった場合でも,Undoボタンを使って消去直前の状態へ戻ることが可能です.
ただし,本システムにおける履歴データの保存は,あくまでブラウザのメモリ内でのみ行われます.ベクター形式としてのパス情報(座標の軌跡)や,各ストロークを独立して管理するレイヤー機能は実装されておらず,すべての描画は確定した瞬間に1枚のラスター画像として平坦化(フラット化)されます.
そのため,過去に描画した特定の線だけを選択して移動させたり,特定のレイヤーのみを非表示にしたりするといった編集機能は提供されていません.
PNGと白背景JPEG
描画したイラストの保存(エクスポート)形式として,本ツールは「PNG形式」と「JPEG形式」の2種類をサポートしています.ドロップダウンメニューから出力形式を選択し,「イラストを保存」ボタンを押すことで,ブラウザ内部での画像生成処理が開始されます.
PNG形式が選択された場合,キャンバスの現在の状態がそのまま透過情報を持ったPNG画像のData URI文字列(image/png)へと変換されます.前述の通り,消しゴム機能を使用した部分は透明なピクセルとなっているため,PNG形式で保存すれば,他の画像編集ソフト等で開いた際にも消しゴムの跡が背景透過として正しく認識されます.
一方,JPEG形式が選択された場合の処理は異なります.JPEGは仕様上アルファチャンネル(透過情報)をサポートしていないため,消しゴムで透明化した部分が真っ黒に変換されてしまう現象を防ぐ必要があります.そのため出力処理時には,一時的に目に見えない出力用キャンバス(1000x600px)をメモリ上に動的生成し,その全面を白色で塗りつぶします.
その上から現在の描画済みキャンバスを合成(drawImage)し,すべての透明部分を白色で埋めた状態を作り出します.その後,この合成済みキャンバスに対して品質パラメータを内部固定値の「0.95」に設定した上でJPEG変換(image/jpeg)を実行し,ダウンロードリンクを生成しています.
保存前確認と再読込の注意
本ツールでの入力座標に基づくパスの描画,消しゴムによるピクセルの透過,履歴データの文字列変換およびメモリ保持,最終的なPNGやJPEG形式へのエンコード処理は,すべて利用者のブラウザ内で実行される実装となっています.
ここで最も注意すべき点は,本ツールが作成した画像データや履歴をブラウザのLocalStorageやIndexedDBといった永続的な保存領域へ書き込む実装を持たないという点です.したがって,編集中にブラウザの「再読み込み(リロード)」ボタンを押す,誤ってタブを閉じる,または別ページへ遷移すると,ブラウザのメモリ上に保持されていたキャンバスの画像データおよびUndo用の履歴配列は直ちに全て破棄され,初期状態の真っ白なキャンバスへリセットされます.
自動保存機能や,次回アクセス時に前回の続きから再開する復元機能は備わっていません.
長時間の作業を行う場合や,重要な手書きメモを作成した場合は,不意の操作によるデータ消失を防ぐため,こまめに「イラストを保存」ボタンを利用して,端末のローカルフォルダ(ダウンロードフォルダ等)へ画像を都度エクスポートすることを推奨します.ファイル名は保存実行時のシステムタイムスタンプ(ミリ秒)を用いて「sketch_1700000000000.png」のような名称が付けられます.
同名ファイルの扱いや保存先はブラウザの設定に依存するため,保存後に確認してください.