一筆書きアプリのおさらい
「index.html」ファイルをWebブラウザで実行すると、以下の図のように、4つのサンプルコードが1つのセットとなり、お絵描きをすることができます。この4つが今回の連載のテンプレートとなります。
詳しくは、前回の連載で似たものを作ったので参考にしてください。今回はブラウザの幅に合わせてパソコン版が「pc.css」のスタイルシートを、モバイル版が「pc.css」と「mobile.css」のスタイルシートを適用します。

「.html」ファイルは、タグを配置するHTML5文書です。タイトルの<h1>タグ、メニューの<nav>タグ、絵を描ける<canvas>タグ、作者情報の<footer>タグを配置します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>一筆書きBBS</title> <link href="css/pc.css" rel="stylesheet" type="text/css" /> <link href="css/mobile.css" rel="stylesheet" type="text/css" media="only screen and (max-width:1023px)" /> <script type="text/javascript" src="js/main.js"></script> </head> <body> <div id="left"> <header> <h1>一筆書きBBS</h1> <nav> <a href="?page=home">HOME</a> <a href="?page=draw">DRAW</a> <a href="?page=about">ABOUT</a> </nav> </header> </div> <div id="right"> <canvas width="760" height="500"></canvas> <footer> <h3>このサイトは2025年から<a href="http://vexil.jp" target="_blank">VexilJp</a>がテストしています。</h3> </footer> </div> </body> </html>
「.css」ファイルが装飾のスタイルシートです。パソコン版では、左側にタイトルとメニューが配置されており、右上に絵を描くことができます。右下には、このサイトの作者についてを書けるようになっています。
html, body { font-family:Meiryo,"Hiragino Kaku Gothic Pro"; min-height: 100%; height: 100%; margin: 0; padding: 0; position: relative; background-color: #999; } header { overflow:hidden; width: 100%; margin: 0; padding: 0; } h1 { float: left; padding: 0; margin: 10px 0 0 0; } h2 { clear: both; } h3 { margin: 0 0 0 20px; padding: 20px 0; } nav { float: right; text-align: center; } footer { float: left; margin: 0; padding: 0; } input, textarea { width: calc(100% - 20px); padding: 0; margin: 5px 10px; } button { width: 200px; padding: 0; margin: 5px 10px; } input[type="submit"] { width: 200px; } select { margin: 10px 0 0 0; } #select { margin: 20px; } #select_num { color: #fff; background-color: #000; } canvas { background-color: #fff; z-index: 0; } ul { clear: both; } li { width: 100%; padding: 5px 0; } #left { float: left; margin: 0; padding: 0 10px; width: 380px; min-height: 100%; background-color: #ccc; } #right { float: right; width: calc(100% - 400px); min-height: 100%; background-color: #999; } a { color: #000; text-decoration: underline; } a:hover { color: #fff; background-color: #000; text-decoration: none; } nav a { float: left; margin: 0; padding: 25px 5px 20px 5px; font-size: 12px; text-decoration: none; font-weight: bold; }
モバイル版のスタイルシートは、上にタイトルとメニューを配置し、上下の真ん中に絵を描くことができるようになっています。下には、このサイトの作者について書けるように配置されています。
h1 { font-size: 50px; } h2 { font-size: 40px; } h3 { font-size: 35px; } li { font-size: 30px; } #left { clear: both; margin: 0; padding: 0 10px; width: 100%; min-height: 50%; background-color: #ccc; } #right { clear: both; width: 100%; min-height: 50%; background-color: #999; } a { font-size: 36px; } nav a { float: left; margin: 0; padding: 30px 10px; font-size: 30px; text-decoration: none; font-weight: bold; }
「.js」ファイルがHTML5やCSSを制御するプログラミング言語です。<canvas>タグに2D画像をお絵描きして描画します。マウスホイールで絵を描いた過程をアンドゥ・リドゥできます。
// 変数 let _canvas; let _context; let _click = false; let _pos = []; let _current = 0; // 全てのDOMが読み込み完了したら window.addEventListener("DOMContentLoaded", () => { _canvas = document.querySelector('canvas'); if (_canvas == null) return; _context = _canvas.getContext('2d'); window.addEventListener("resize", resize, false); resize(); // マウスがクリックされたら頂点描画 _canvas.addEventListener("mousedown", (e) => { _click = true; _pos.length = _current*4; let pos = getPos(e); _pos.push(pos[0],pos[1],pos[0],pos[1]); _current++; line(); }); // マウスが離されたら window.addEventListener("mouseup", (e) => { _click = false; }); // マウスがドラッグされたら window.addEventListener("mousemove", (e) => { if ( _click ) { let pos = getPos(e); _pos[_pos.length-4] = pos[0]; _pos[_pos.length-3] = pos[1]; line(); } }); // マウスホイールでアンドゥとリドゥ _canvas.addEventListener('wheel', (e) => { if (e.deltaY > 0) { if (_current > 0) _current--; } else if (e.deltaY < 0) { if (_current < _pos.length/4) _current++; } line(); }); }); // 画面サイズが変更されたら function resize() { if ( document.body.clientWidth <= 1023 ) { _canvas.width = window.innerWidth; } else { _canvas.width = document.body.clientWidth - 400; } _canvas.height = document.body.clientHeight - 80; line(); } // 図形の描画 function line() { _context.clearRect(0,0,_canvas.width,_canvas.height); let color = 'rgb(0,0,0)'; _context.strokeStyle = color; _context.lineWidth = 1; // 1クリックした頂点 for ( let i = 0; i < _current; i++ ) _context.strokeRect(_pos[i*4+2],_pos[i*4+3],1,1); // ベジェ曲線を引いていく _context.lineWidth = 3; _context.beginPath(); for ( let i = 1; i < _current; i++ ) { _context.moveTo(_pos[i*4-2],_pos[i*4-1]); _context.quadraticCurveTo(_pos[i*4],_pos[i*4+1],_pos[i*4+2],_pos[i*4+3]); } _context.stroke(); } // 正確なcanvasのマウス座標 function getPos(event) { // 要素の位置を取得 let clientRect = _canvas.getBoundingClientRect(); let positionX = event.clientX - clientRect.left; let positionY = event.clientY - clientRect.top; return [positionX,positionY]; }