TOP > カテゴリ > HTML5・JavaScript >

canvasでドット絵用のキャンバスを作成する[1マス=1ドット]

HTML5のcanvasでドット絵用の四角いマスを配置してマウスダウンでマスを塗りつぶす事ができるキャンバスのサンプルです。

このサンプルプログラムでは1マスは1ドットとなります。

ドット絵のキャンバス体験

「10x10」のキャンバスの上でマウスをダウンすることによってマスを塗りつぶす事ができます。マウスをダウンしたまま移動する連続して塗りつぶせます。

現在座標はマウスがある位置の座標。マウスダウンはマウスダウンした座標。セル番号はキャンバスのセル番号です。Rは「Row = 行番号」、Cは「Col = 列番号」となります。

このドット絵のキャンバスはブラウザで動作する「アイコンエディタ」のプロトタイプとして作成しました。

サンプルプログラム

前章のキャンバス体験と同じコードとなります。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
var canvas; // キャンバス
var ctx;    // コンテキスト

var canvas_magnification = 25;    // 表示倍率  
var canvas_width  = 10;           // キャンバス横幅   
var canvas_height = 10;           // キャンバス縦幅 
var canvas_mousedown_flg = false; // マウスダウンフラグ

///// 内部関数

function init_canvas(){
  canvas_mousedown_flg = false;
  
  ctx.fillStyle = "rgb(255, 255, 255)";  
  ctx.fillRect(0,0,canvas.width,canvas.height);
                 
  drawRule();  
}
   
// 座標からブロック名を取得する   
function Point2BlockName(x,y){  
  var col = 'C' + (Math.floor(x / canvas_magnification)+1);
  var row = 'R' + (Math.floor(y / canvas_magnification)+1);
  
  document.getElementById('msg3').innerHTML = 'セル番号 ' +row + ' x ' + col;
}  

// キャンバスに罫線を描画する
function drawRule(){

  // 線の色
  ctx.strokeStyle = "#1e90ff";
 
  // 線の太さ
  ctx.lineWidth = 2;
  
  // 破線
  if (ctx.setLineDash){
    ctx.setLineDash([1, 2]);
  }
  
  ctx.beginPath();
  
  // 縦線
  for (var i = 0; i < canvas_width+1; i++) {
    ctx.moveTo((i*canvas_magnification),0);
    ctx.lineTo((i*canvas_magnification),canvas.height);
  }

  // 横線
  for (var i = 0; i < canvas_height+1; i++) {
    ctx.moveTo(0,(i*canvas_magnification));
    ctx.lineTo(canvas.height,(i*canvas_magnification));
  }

  ctx.stroke();  
}

///// イベント
    
window.onload = function (){
  // キャンバス
  canvas = document.getElementById("MyCanvas");
     
  canvas.width  = canvas_width * canvas_magnification;
  canvas.height = canvas_height * canvas_magnification;    
  
  ctx = canvas.getContext("2d");
  
  canvas.addEventListener('mousedown', OnMousedown);
  canvas.addEventListener('mousemove', OnMousemove);
  canvas.addEventListener('mouseup', OnMouseup);
  window.addEventListener('mouseup', OnMouseup);
  
  init_canvas();              
}

function OnMousedown(e) {
  var rect = e.target.getBoundingClientRect();
  mouseX = e.clientX - rect.left;
  mouseY = e.clientY - rect.top; 
        
  // 塗りつぶし
  var col = Math.floor(mouseX / canvas_magnification);
  var row = Math.floor(mouseY / canvas_magnification);
  
  ctx.fillStyle = "rgb(200, 0, 0)";  
  ctx.fillRect(col * canvas_magnification, row * canvas_magnification,
               canvas_magnification, canvas_magnification);
  
  // 罫線の描画
  drawRule();
  
  document.getElementById('msg2').innerHTML = 'マウスダウン X:' +mouseX + ' Y' +mouseY;
  
  canvas_mousedown_flg = true;
}

function OnMousemove(e) {
  var rect = e.target.getBoundingClientRect();
  mouseX = e.clientX - rect.left;
  mouseY = e.clientY - rect.top; 
        
  if (canvas_mousedown_flg){
      // 塗りつぶし
      var col = Math.floor(mouseX / canvas_magnification);
      var row = Math.floor(mouseY / canvas_magnification);
      
      ctx.fillStyle = "rgb(200, 0, 0)";  
      ctx.fillRect(col * canvas_magnification, row * canvas_magnification, 
                   canvas_magnification, canvas_magnification);
      
      drawRule();
  }  
 
  document.getElementById('msg1').innerHTML = '現在座標 X:' +mouseX + ' Y' +mouseY;
  Point2BlockName(mouseX,mouseY);
}

function OnMouseup(e) {
  canvas_mousedown_flg = false; 
}            
</script> 
</head>
<body>
<button onclick="init_canvas();">クリア</button>
<p></p>
<canvas id="MyCanvas" style="paddling:0;"></canvas>
<div id="msg1"></div>
<div id="msg2"></div>
<div id="msg3"></div> 
</body>
</html> 

ドット絵用のマスはdrawRule()関数でmoveTo/lineToメソッドを使用して罫線を描画します。

重要なコードはマウス系イベントで使用しているgetBoundingClientRectプロパティです。このプロパティは矩形のサイズ情報を返します。そこから、clientXとclientYを使用して現在のマウスカーソルの座標を取得しています。

※getBoundingClientRectプロパティはW3Cの仕様ではありません。ただし、IE11/Edge/Chrome/FireFoxでの動作確認はしております。IE9/IE10は未確認ですがあると思います。

関連リンク

塗りつぶしのアルゴリズム[ペイント系]

参考リンク

Web IconEditor





関連記事



公開日:2016年02月22日
記事NO:01788