アットウィキロゴ

Touch Paint サンプル

0.環境確認

 このサンプルは「色の入力欄」、「レンジ入力欄」を使用しています。
 ご利用の環境では動作しない場合がありますので以下のページより確認してください。


 以下のとおり「input type=range」、「input type=color」ともに「Yes」であればOK。

1.index.htmlを準備する。

1−1.canvasとlog出力領域を実装する。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  <title>TouchPaint</title>
</head>
<body>
  <canvas id="canvas">
    This browser is not supported
  </canvas>
  <p id="log"></p>
  <script>
  </script>
</body>
</html>

2.canvasにイベントを登録し動作を確認する。

2−1.定義

    var canvas = document.getElementById("canvas");
    var log = document.getElementById ("log");

2−2.canvasのサイズを指定する

    canvas.width = document.width;
    canvas.height = document.height - 200;

2−3.イベントを登録する。

    canvas.addEventListener("touchstart", touchStartHandler, false);
    canvas.addEventListener("touchmove", touchMoveHandler, false);
    canvas.addEventListener("touchend", touchEndHandler, false);
    
    function touchStartHandler(e) {
      log.innerHTML += "<p>Touch Event: touchstart</p>";
    }
    function touchMoveHandler(e) {
      log.innerHTML += "<p>Touch Event: touchmove</p>";
    }
    function touchEndHandler(e) {
      log.innerHTML += "<p>Touch Event: touchend</p>";
    }

2−3.実行結果


3.canvasにマークしてみる

3−1.定義

    var context = canvas.getContext("2d");
    var touches;

3−2.touchMoveHandlerを書き換える

    function touchMoveHandler(e) {
      touches = e.touches.item(0);
      context.fillRect(touches.pageX - this.offsetLeft, touches.pageY - this.offsetTop, 5, 5);
    }

3−3.実行結果



4.点を線で結んでみる

4−1.定義

    var drawPath = new Array;
    var isMoved = false;

4−2.touchStartHandlerを書き換える

    function touchStartHandler(e) {
      touches = e.changedTouches;
      drawPath.push(touches[0]);
    }

4−3.touchMoveHandlerを書き換える

    function touchMoveHandler(e) {
      touches = e.changedTouches;
      context.beginPath();
      context.moveTo(drawPath[0].pageX - this.offsetLeft, drawPath[0].pageY - this.offsetTop);
      context.lineTo(touches[0].pageX - this.offsetLeft, touches[0].pageY - this.offsetTop);
      context.closePath();
      context.stroke();
      drawPath.splice(0, 1, touches[0]); 
      e.preventDefault();
    }

4−4.touchEndHandlerを書き換える

    function touchEndHandler(e) {
      if (!isMoved) {
        context.beginPath();
        context.closePath();
        context.fill();
      }
      isMoved=false;
      drawPath.length = 0;
    }

4−5.実行結果



5.線の色や太さを変えてみる

5−1.タグを追加

  <div class="desc">
    <label>Color: <input type="color" class="strokeColor" id="strokeColor"></label>
    <label>Line width: 
      <input type="range" min="5" max="20" step="5" value="5" class="strokeWidth" id="strokeWidth">
    </label>
  </div>
  <button class="clearBtn" id="clearBtn">Clear!</button>

5−2.定義

    var strokeColor;
    var strokeWidth = 5;
    var strokeColorSel = document.getElementById("strokeColor");
    var strokeWidthSel = document.getElementById("strokeWidth");
    var clearBtn = document.getElementById("clearBtn");

5−3.イベント登録

    strokeColorSel.addEventListener("change", changeStrokeColor, false);
    strokeWidthSel.addEventListener("change", changeStrokeWidth, false);
    clearBtn.addEventListener("click", clearCanvas, false);
    function changeStrokeColor() {
      strokeColor = this.value;
    }
    function changeStrokeWidth() {
      strokeWidth = this.value;
    }
    function clearCanvas() {
      context.clearRect (0, 0, canvas.width, canvas.height);
    }

5−4.functionを追加

    function drawPathSetting(idx) {
      for (var i = 0; i < drawPath.length; i++) {
        var _idx = drawPath[i].identifier;
        if (_idx === idx) {
          return i;
        }
      }
      return -1;
    }

5−5.touchMoveHandlerを書き換える

    function touchMoveHandler(e) {
      touches = e.changedTouches;
      context.lineWidth = strokeWidth;
      context.strokeStyle = strokeColor;
      context.lineJoin = "round";
      for (var i = 0; i < touches.length; i++) {
        var idx = drawPathSetting(touches[i].identifier);
        context.beginPath();
        context.moveTo(drawPath[idx].pageX - this.offsetLeft, drawPath[idx].pageY - this.offsetTop);
        context.lineTo(touches[i].pageX - this.offsetLeft, touches[i].pageY - this.offsetTop);
        context.closePath();
        context.stroke();
        drawPath.splice(idx, 1, touches[i])
      }
      e.preventDefault();
    }

5−6.touchEndHandlerを書き換える

    function touchEndHandler(e) {
      if (!isMoved) {
        var startPoint = (Math.PI/180)*0;
        var endPoint = (Math.PI/180)*360;
        context.fillStyle = strokeColor;
        context.beginPath();
        context.arc(touches[0].pageX - this.offsetLeft, touches[0].pageY - this.offsetTop, strokeWidth/2, startPoint, endPoint, true);
        context.closePath();
        context.fill();
      }
      isMoved=false;
      drawPath.length = 0;
    }

5−7.実行結果


6.スタイルシートで見栄えを整えてみる。

6−1.スタイルシートを準備する。

style.css

* {
  margin:0;padding:0;
}
html, body {
  width:100%;height:100%;background:#ddd;
}
h2 {
  padding:10px 15px;color:#6587ac;
}
.canvas { width:100%;background:#fff;}
.desc { display:table;width:100%;padding:5px 10px;text-align:right; }
.desc label { display:table-cell;width:50%;white-space:nowrap; }
.desc label:first-child { text-align:left; }
.strokeWidth { width:85px; }
button {
  float:right;margin-right:15px;
}
input, button {
  vertical-align:middle;
}
@media screen and (max-device-height : 800px) {
  .addHeight {height:360px;}
}
@media screen and (min-device-height : 801px) {
  .addHeight {height:480px;}
}

6−2.htmlのヘッダー部に追加する

index.html

  <link rel="stylesheet" type="text/css" href="css/style.css"/>

6−3.実行結果


7.完成

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
  <title>TouchPaint</title>
  <link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
  <canvas id="canvas">
    This browser is not supported
  </canvas>
  <div class="desc">
    <label>Color: <input type="color" class="strokeColor" id="strokeColor"></label>
    <label>Line width: 
      <input type="range" min="5" max="20" step="5" value="5" class="strokeWidth" id="strokeWidth">
    </label>
  </div>
  <button class="clearBtn" id="clearBtn">Clear!</button>
  <script>
    var canvas = document.getElementById("canvas");
    var log = document.getElementById ("log");
    var context = canvas.getContext("2d");
    
    var strokeColor;
    var strokeWidth = 5;
    
    var strokeColorSel = document.getElementById("strokeColor");
    var strokeWidthSel = document.getElementById("strokeWidth");
    var clearBtn = document.getElementById("clearBtn");
    
    canvas.width = document.width;
    canvas.height = document.height - 200;
    
    canvas.addEventListener("touchstart", touchStartHandler, false);
    canvas.addEventListener("touchmove", touchMoveHandler, false);
    canvas.addEventListener("touchend", touchEndHandler, false);
    strokeColorSel.addEventListener("change", changeStrokeColor, false);
    strokeWidthSel.addEventListener("change", changeStrokeWidth, false);
    clearBtn.addEventListener("click", clearCanvas, false);
    
    var drawPath = new Array;
    var isMoved = false;
    function touchStartHandler(e) {
      touches = e.changedTouches;
      drawPath.push(touches[0]);
    }
    
    var touches;
    function touchMoveHandler(e) {
      touches = e.changedTouches;
      
      context.lineWidth = strokeWidth;
      context.strokeStyle = strokeColor;
      context.lineJoin = "round";
      
      for (var i = 0; i < touches.length; i++) {
        
        var idx = drawPathSetting(touches[i].identifier);
        
        context.beginPath();
        context.moveTo(drawPath[idx].pageX - this.offsetLeft, drawPath[idx].pageY - this.offsetTop);
        context.lineTo(touches[i].pageX - this.offsetLeft, touches[i].pageY - this.offsetTop);
        context.closePath();
        context.stroke();
        
        drawPath.splice(idx, 1, touches[i])
      }
      e.preventDefault();
    }
    
    function touchEndHandler(e) {
      if (!isMoved) {
        var startPoint = (Math.PI/180)*0;
        var endPoint = (Math.PI/180)*360;
        context.fillStyle = strokeColor;
        context.beginPath();
        context.arc(touches[0].pageX - this.offsetLeft, touches[0].pageY - this.offsetTop, strokeWidth/2, startPoint, endPoint, true);
        context.closePath();
        context.fill();
      }
      isMoved=false;
      drawPath.length = 0;
    }
    function changeStrokeColor() {
      strokeColor = this.value;
    }
    function changeStrokeWidth() {
      strokeWidth = this.value;
    }
    function clearCanvas() {
      context.clearRect (0, 0, canvas.width, canvas.height);
    }
    function drawPathSetting(idx) {
      for (var i = 0; i < drawPath.length; i++) {
        var _idx = drawPath[i].identifier;
        if (_idx === idx) {
          return i;
        }
      }
      return -1;
    }
  </script>
</body>
</html>

style.css

* {
  margin:0;padding:0;
}
html, body {
  width:100%;height:100%;background:#ddd;
}
h2 {
  padding:10px 15px;color:#6587ac;
}
.canvas { width:100%;background:#fff;}
.desc { display:table;width:100%;padding:5px 10px;text-align:right; }
.desc label { display:table-cell;width:50%;white-space:nowrap; }
.desc label:first-child { text-align:left; }
.strokeWidth { width:85px; }
button {
  float:right;margin-right:15px;
}
input, button {
  vertical-align:middle;
}
@media screen and (max-device-height : 800px) {
  .addHeight {height:360px;}
}
@media screen and (min-device-height : 801px) {
  .addHeight {height:480px;}
}
最終更新:2013年07月30日 01:03