「TAURI」で「丸アートお絵描き」アプリを作ろう
はじめに
今回は、前回で作ったプログラムにさらに肉付けしていき、丸シールでお絵描きするアート作品風に円をたくさん描画するだけでお絵描きできるアプリを開発します。そのためには、まず前回のプログラムをコーディングする必要があります。
図1のように色の付いた正円を好きな太さで何個も判子のように押していけば、例えばヒマワリの丸シールアートが描けます。よく見ていただければ分かるように、塗り絵のように線画の下絵を読み込んでから描いています。あまり上手な絵は描けませんが、これなら誰でも簡単に描けてヘタウマな感じがしませんか。
今回は「HTML5+JavaScript+CSS」だけコーディングし、「canvas」タグに円を描けるようにしたり、円の赤緑青の色をスライダーで変更させられるようにしたり、円のペン(筆)の太さを変更させられるようにしたり、canvasタグの幅高さの大きさを変更できるようにしたりします。「Rust」については前回のまま同じコードで、画像を読み込んだり保存したりするだけです。
タグを配置して円を描けるようにする
「index.html」「main.js」「styles.css」をコーディングすると、図2のように赤緑青の色を変更したりペンの太さを変更したりして円を描けるようになります。後はペンの色と太さに合わせてプレビューの筆を反映したり、canvasの幅と高さも反映したりすれば完成です。
HTMLファイルにタグを配置する
ここで「src」→「index.html」ファイルにタグを配置するだけで、ほとんどお絵描きアプリの完成図に近いものができます。ただしHTMLファイルでは見た目だけで、実際に円を描くにはJavaScriptでプログラミングしなければなりません。
ペンの円の色や太さを決める「input」タグの「type」属性が"range"のスライダーです。最小値を「min」属性で、最大値を「max」属性でセットします。canvas画面の幅高さをセットするinputタグのtype属性が"text"のテキストボックスで、テキストボックスの値が変更されるたびに「onBlur」属性で指定した「changeWidth」関数や「changeHeight」関数が呼ばれます。
・「src」→「index.html」のサンプルコード(前略) <body> <header> <h1>MaruArt</h1> <button onClick="newImage()">新規</button> <button onClick="openImage()">開く</button> <button onClick="saveImage()">保存</button> <button onClick="undoImage()">アンドゥ</button> </header> <div id="canvas"> <canvas></canvas> </div> <div id="ui"> <p> 赤 <input id="red" type="range" min="0" max="255" value="0" step="1"><br /> 緑 <input id="green" type="range" min="0" max="255" value="0" step="1"><br /> 青 <input id="blue" type="range" min="0" max="255" value="0" step="1"><br /> </p> <p> <div id="color"></div> </p> <p> 幅 <input onBlur="changeWidth(this)" type="text" id="width" name="width" required minlength="1" maxlength="4" size="11"><br /> 高さ <input onBlur="changeHeight(this)" type="text" id="height" name="height" required minlength="1" maxlength="4" size="11"><br /> </p> <p> 筆 <input id="pen" type="range" min="1" max="75" value="25" step="1"><br /> </p> </div> <script src="main.js"></script> </body> </html>
【サンプルコードの解説】
「アンドゥ」ボタンを押すと「undoImage」関数が呼ばれるようにbuttonタグを配置します。
「#ui」セレクタに「赤」と「緑」と「青」を0~255以下まで選べるスライダー(inputタグのrangeタイプ)を配置します。
「#color」セレクタに実際のペンの色と大きさの実物大をプレビューします。まだここでは変更が反映されません。
canvasの「幅」と「高さ」のサイズを変更できるテキストボックス(inputタグのtextタイプ)を配置します。まだここでは変更が反映されません。
「筆」(ペン)の太さを1~75以下まで選べるスライダー(inputタグのrangeタイプ)を配置します。
canvasタグにJavaScriptで円を描けるようにする
「src」→「main.js」ファイルでindex.htmlの各セレクタを制御します。canvasタグ上をクリックしたら、黒っぽい輪郭で囲まれた円を描きます。輪郭の円周の色は、円の色の赤緑青の値をそれぞれ2/3倍した値です。
「querySelector」メソッドでペンの色を「#red」セレクタなどから取得しますが、その値はそのインスタンスの「value」プロパティから取得します。色だけでなくペンの太さも「#pen」セレクタのvalueプロパティから取得します。
コンテキストの「strokeStyle」プロパティと「fillStyle」プロパティに渡す色は、例えば'rgb(64,128,255)'のような文字列で表したRGB値です。
・「src」→「main.js」のサンプルコードconst { invoke } = window.__TAURI__.tauri; const { open,save } = window.__TAURI__.dialog; let _canvas = document.querySelector('canvas'); let _context = _canvas.getContext('2d'); //赤色 let _red = document.querySelector('#red'); //緑色 let _green = document.querySelector('#green'); //青色 let _blue = document.querySelector('#blue'); //ペン let _pen = document.querySelector('#pen'); //HTMLの読み込みが終了しとき window.addEventListener("DOMContentLoaded", () => { //キャンバスでマウスクリックが離されたとき _canvas.addEventListener("mouseup", (e) => { maru(e); }); }); //キャンバスにおけるマウスの位置を取得 function getPos(event) { let clientRect = _canvas.getBoundingClientRect(); let x = event.clientX - clientRect.left; let y = event.clientY - clientRect.top; return [x,y]; } //円を描く function maru(event) { let pos = getPos(event); let color = 'rgb('+2*_red.value/3+','+2*_green.value/3+','+2*_blue.value/3+')'; _context.beginPath(); _context.lineWidth = 1; _context.strokeStyle = color; color = 'rgb('+_red.value+','+_green.value+','+_blue.value+')'; _context.fillStyle = color; _context.arc(pos[0],pos[1],_pen.value,0,Math.PI*2,true); _context.fill(); _context.stroke(); } (後略)
【サンプルコードの解説】
index.htmlの#redセレクタを「_red」変数に、#greenセレクタを「_green」変数に、#blueセレクタを「_blue」変数に、#penセレクタを「_pen」変数に代入します。
イベントリスナーでDOMが全て読み込まれたら(DOMContentLoaded)、canvasタグ上でマウスクリックが離されたとき(mouseup)、「maru」関数をイベントリスナーで呼ぶようにセットします。
「getPos」関数はcanvas上のマウス座標、つまりcanvasタグの一番左上が(X,Y)=(0,0)となるようにマウス座標を取得します。
canvas上でマウスクリックが離されたらmaru関数が呼ばれ、取得したマウス座標の位置に_penの太さで_redと_greenと_blueの色の円とその色を黒っぽくした円周の輪郭を描きます。
スタイルシートの装飾
「スタイルシートのCSSは後からデザインを微調整すれば良い」と言いましたが、今回は次の「src」→「styles.css」ファイルのように円のプレビューなどデフォルトの値を設定しておいた方が良いです。
ここまでコーディングしたら「$ cargo-tauri dev」でデバッグビルドして実行してみてください。canvasをクリックすれば円が描けますね。ペンの色や太さも変更して円を描いてみてください。余談ですが「開く」ボタンで画像ファイルを開けば、その画像サイズにcanvasタグの幅高さのサイズが変更できます。
・「src」→「styles.css」のサンプルコード(前略) #ui { float: left; color: #000; margin: 10px; } #color { background-color: #000; border: 1px solid #000; width: 50px; height: 50px; border-radius: 50%; }
【サンプルコードの解説】
#uiセレクタでペンの色と太さとcanvasの幅高さのUIはできるだけcanvasタグの右側に配置されるように「float: left;」で左側に浮動します。「できるだけ」と書いたのは、図3のように画面幅が狭いときに左側に浮動する配置が下に折り返されるからです。
#colorセレクタで、プレビューのペンをまずは真っ黒の半径25px(50pxの50%)で円を描画します。