HTML5画布的多点触控

3
我正在使用HTML5 canvas创建一个音乐乐器,并且在将多点触控功能集成到我的代码时遇到了问题。我希望能够让用户同时播放多个键。我对整个HTML5概念还很陌生,所以需要沿途任何帮助。
我发现了一些JS文件可以帮助我,例如hammer.js和magictouch.js。然而,我不知道如何将它们用于我的代码中。
在这种情况下,我正在尝试将多点触控实现到由画布上的函数绘制的钢琴上。我该如何开始进行多点触控?我如何与画布一起使用它?
        var button = document.getElementById("Draw");
        button.onclick = function(){
            drawOnCanvas();
        }
        function drawOnCanvas(){        
        var canvas = document.getElementById("main");

        if (canvas.getContext){
            var cxt = canvas.getContext("2d");
            <!-- alert("2D context supported"); -->

                cxt.beginPath();
                cxt.moveTo(20, 20);
                cxt.lineTo(60, 20);
                cxt.moveTo(60, 20);
                cxt.lineTo(60, 160);
                cxt.moveTo(60, 160);
                cxt.lineTo(75, 160);
                cxt.moveTo(75, 160);
                cxt.lineTo(75, 230);
                cxt.moveTo(75, 230);
                cxt.lineTo(20, 230);
                cxt.moveTo(20, 20);
                cxt.lineTo(20, 230);
                cxt.stroke();

                <!-- Key note C -->

                cxt.rect(60, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.shadowColor = '#999';
                cxt.shadowBlur = 20;
                cxt.shadowOffsetX = 15;
                cxt.shadowOffsetY = 15;
                cxt.fill();
                cxt.stroke();

                <!-- Key note C# -->

                cxt.beginPath();
                cxt.moveTo(90, 20);
                cxt.lineTo(120, 20);
                cxt.moveTo(90, 20);
                cxt.lineTo(90, 160);
                cxt.moveTo(90, 160);
                cxt.lineTo(75, 160);
                cxt.moveTo(75, 160);
                cxt.lineTo(75, 230);
                cxt.moveTo(60, 230);
                cxt.lineTo(60, 230);
                cxt.moveTo(75, 230);
                cxt.lineTo(135, 230);
                cxt.moveTo(135, 230);
                cxt.lineTo(135, 160);
                cxt.moveTo(135, 160);
                cxt.lineTo(120, 160);
                cxt.moveTo(120, 160);
                cxt.lineTo(120, 20);
                cxt.stroke();

                <!-- Key note D -->

                cxt.beginPath();
                cxt.rect(120, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note D# -->

                cxt.beginPath();
                cxt.moveTo(150, 20);
                cxt.lineTo(190, 20);
                cxt.moveTo(150, 20);
                cxt.lineTo(150, 160);
                cxt.moveTo(150, 160);
                cxt.lineTo(135, 160);
                cxt.moveTo(135, 160);
                cxt.lineTo(135, 230);
                cxt.moveTo(135, 230);
                cxt.lineTo(190, 230);
                cxt.moveTo(190, 230);
                cxt.lineTo(190, 20);
                cxt.moveTo(125, 230);
                cxt.stroke(); 

                <!-- Key note E -->

                cxt.beginPath();
                cxt.moveTo(190, 20);
                cxt.lineTo(230, 20);
                cxt.moveTo(190, 20);
                cxt.lineTo(190, 230);
                cxt.moveTo(230, 20);
                cxt.lineTo(230, 160);
                cxt.moveTo(230, 160);
                cxt.lineTo(245, 160);
                cxt.moveTo(245, 160);
                cxt.lineTo(245, 230);
                cxt.moveTo(245, 230);
                cxt.lineTo(190, 230);
                cxt.stroke();

                <!-- Key note F -->

                cxt.beginPath();
                cxt.rect(230, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note F# --> 

                cxt.beginPath();
                cxt.moveTo(260, 20);
                cxt.lineTo(290, 20);
                cxt.moveTo(290, 20);
                cxt.lineTo(290, 160);
                cxt.moveTo(290, 160);
                cxt.lineTo(305, 160);
                cxt.moveTo(305, 160);
                cxt.lineTo(305, 230);
                cxt.moveTo(305, 230);
                cxt.lineTo(245, 230);
                cxt.moveTo(245, 230);
                cxt.lineTo(245, 160);
                cxt.moveTo(245, 160);
                cxt.lineTo(260, 160);
                cxt.moveTo(260, 160);
                cxt.lineTo(260, 20);
                cxt.stroke();

                <!-- Key note G -->

                cxt.beginPath();
                cxt.rect(290, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note G# -->

                cxt.beginPath();
                cxt.moveTo(320, 20);
                cxt.lineTo(350, 20);
                cxt.moveTo(350, 20);
                cxt.lineTo(350, 160);
                cxt.moveTo(350, 160);
                cxt.lineTo(365, 160);
                cxt.moveTo(365, 160);
                cxt.lineTo(365, 230);
                cxt.moveTo(365, 230);
                cxt.lineTo(305, 230);
                cxt.moveTo(305, 230);
                cxt.lineTo(305, 160);
                cxt.moveTo(305, 160);
                cxt.lineTo(320, 160);
                cxt.moveTo(320, 160);
                cxt.lineTo(320, 20);
                cxt.stroke();

                <!-- Key note A -->

                cxt.beginPath();
                cxt.rect(350, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note A# -->

                cxt.beginPath();
                cxt.moveTo(380, 20);
                cxt.lineTo(420, 20);
                cxt.moveTo(420, 20);
                cxt.lineTo(420, 160);
                cxt.moveTo(420, 160);
                cxt.lineTo(420, 160);
                cxt.moveTo(420, 160);
                cxt.lineTo(420, 230);
                cxt.moveTo(420, 230);
                cxt.lineTo(365, 230);
                cxt.moveTo(365, 230);
                cxt.lineTo(365, 160);
                cxt.moveTo(365, 160);
                cxt.lineTo(380, 160);
                cxt.moveTo(380, 160);
                cxt.lineTo(380, 20);
                cxt.stroke();

                <!-- Key note B --> 

                cxt.beginPath();
                cxt.moveTo(420, 20);
                cxt.lineTo(460, 20);
                cxt.moveTo(460, 20);
                cxt.lineTo(460, 160);
                cxt.moveTo(460, 160);
                cxt.lineTo(475, 160);
                cxt.moveTo(475, 160);
                cxt.lineTo(475, 230);
                cxt.moveTo(475, 230);
                cxt.lineTo(420, 230);
                cxt.moveTo(420, 230);
                cxt.lineTo(420, 20);
                cxt.stroke();

                <!-- Key note C' -->

                cxt.beginPath();
                cxt.rect(460, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note C#' -->

                cxt.beginPath();
                cxt.moveTo(490, 20);
                cxt.lineTo(520, 20);
                cxt.moveTo(520, 20);
                cxt.lineTo(520, 160);
                cxt.moveTo(520, 160);
                cxt.lineTo(535, 160);
                cxt.moveTo(535, 160);
                cxt.lineTo(535, 230);
                cxt.moveTo(535, 230);
                cxt.lineTo(475, 230);
                cxt.moveTo(475, 230);
                cxt.lineTo(475, 160);
                cxt.moveTo(475, 160);
                cxt.lineTo(490, 160);
                cxt.moveTo(490, 160);
                cxt.lineTo(490, 20);
                cxt.stroke();

                <!-- Key note D' -->

                cxt.beginPath();
                cxt.rect(520, 20, 30, 140);
                cxt.fillStyle = 'black';
                cxt.fill();
                cxt.stroke();

                <!-- Key note D#' -->

                cxt.beginPath();
                cxt.moveTo(550, 20);
                cxt.lineTo(595, 20);
                cxt.moveTo(595, 20);
                cxt.lineTo(595, 160);
                cxt.moveTo(595, 160);
                cxt.lineTo(595, 160);
                cxt.moveTo(595, 160);
                cxt.lineTo(595, 230);
                cxt.moveTo(595, 230);
                cxt.lineTo(535, 230);
                cxt.moveTo(535, 230);
                cxt.lineTo(535, 160);
                cxt.moveTo(535, 160);
                cxt.lineTo(550, 160);
                cxt.moveTo(550, 160);
                cxt.lineTo(550, 20);
                cxt.stroke();
            }

        canvas.addEventListener("mousedown", function(evt) {
                    var mousePos = getMousePos(canvas, evt);
                    var message = "Mouse Position :  " + mousePos.x + ", " + mousePos.y;
                    writeMessage(canvas, message);
                    playSong(mousePos.x, mousePos.y);
                }, false); 

        function playSong(xpos, ypos) {

            if ((xpos > '40' && xpos < '79' && ypos > '40' && ypos < '180') || (xpos > '40' && xpos < '97' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("c_note").play();
                }
                else if (xpos > '80' && xpos < '110' && ypos > '40' && ypos < '180') 
                {
                document.getElementById("csharp_note").play();
                }
                else if ((xpos > '111' && xpos < '140' && ypos > '40' && ypos < '180') || (xpos > '97' && xpos < '155' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("d_note").play();           
                }
                else if (xpos > '141' && xpos < '171' && ypos > '40' && ypos < '180') 
                {
                document.getElementById("dsharp_note").play();
                }
                else if ((xpos > '172' && xpos < '210' && ypos > '40' && ypos < '180') || (xpos > '156' && xpos < '210' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("e_note").play();           
                }
                else if ((xpos > '211' && xpos < '250' && ypos > '40' && ypos < '180') || (xpos > '210' && xpos < '265' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("f_note").play();           
                }
                else if (xpos > '251' && xpos < '281' && ypos > '40' && ypos < '180') 
                {
                document.getElementById("fsharp_note").play();
                }
                else if ((xpos > '282' && xpos < '310' && ypos > '40' && ypos < '180') || (xpos > '266' && xpos < '325' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("g_note").play();           
                }
                else if (xpos > '311' && xpos < '341' && ypos > '40' && ypos < '180')
                {
                document.getElementById("gsharp_note").play();          
                }
                else if ((xpos > '342' && xpos < '370' && ypos > '40' && ypos < '180') || (xpos > '326' && xpos < '385' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("a_note").play();           
                }
                else if (xpos > '371' && xpos < '399' && ypos > '40' && ypos < '180')
                {
                document.getElementById("asharp_note").play();          
                }
                else if ((xpos > '400' && xpos < '440' && ypos > '40' && ypos < '180') || (xpos > '385' && xpos < '440' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("b_note").play();           
                }
                else if ((xpos > '441' && xpos < '480' && ypos > '40' && ypos < '180') || (xpos > '441' && xpos < '495' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("c2_note").play();          
                }
                else if (xpos > '481' && xpos < '510' && ypos > '40' && ypos < '180')
                {
                document.getElementById("csharp2_note").play();         
                }
                else if ((xpos > '511' && xpos < '540' && ypos > '40' && ypos < '180') || (xpos > '496' && xpos < '555' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("d2_note").play();          
                }
                else if (xpos > '541' && xpos < '571' && ypos > '40' && ypos < '180')
                {
                document.getElementById("dsharp2_note").play();         
                }
                else if ((xpos > '572' && xpos < '615' && ypos > '40' && ypos < '180') || (xpos > '556' && xpos < '615' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("e2_note").play();          
                }
                else if ((xpos > '616' && xpos < '654' && ypos > '40' && ypos < '180') || (xpos > '616' && xpos < '675' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("f2_note").play();          
                }
                else if (xpos > '656' && xpos < '686' && ypos > '40' && ypos < '180')
                {
                document.getElementById("fsharp2_note").play();         
                }
                else if ((xpos > '687' && xpos < '714' && ypos > '40' && ypos < '180') || (xpos > '676' && xpos < '730' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("g2_note").play();          
                }
                else if (xpos > '715' && xpos < '745' && ypos > '40' && ypos < '180')
                {
                document.getElementById("gsharp2_note").play();         
                }
                else if ((xpos > '746' && xpos < '775' && ypos > '40' && ypos < '180') || (xpos > '731' && xpos < '790' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("a2_note").play();          
                }
                else if (xpos > '776' && xpos < '805' && ypos > '40' && ypos < '180')
                {
                document.getElementById("asharp2_note").play();         
                }
                else if ((xpos > '806' && xpos < '845' && ypos > '40' && ypos < '180') || (xpos > '791' && xpos < '845' && ypos > '180' && ypos < '250'))
                {
                document.getElementById("b2_note").play();          
                }

                }

        function writeMessage(canvas, message) {
                cxt.font = "18pt Calibri";
                cxt.fillStyle = "black";
                cxt.clearRect(0, 0, 300, 50);
                cxt.fillText(message, 10, 20);
            }

        function getMousePos(canvas, evt) {
                var rect = canvas.getBoundingClientRect();
                return {x: (evt.pageX + rect.left), y: (evt.pageY + rect.top)};
            }               
    }  

你忘记了提出实际问题。除非你有一个具体的问题需要解决,否则我们无法帮助你。我们不会为你编写代码,我们在这里是为了帮助指导你走向正确的方向。 - jered
1个回答

2
为了支持某种多点触控功能,您需要处理触摸事件touchstart touchmove touchend touchcancel(如果要支持IE,则还需要处理指针事件)。触摸事件具有changedTouches属性。从该属性中读取添加或删除的触摸,并存储该信息。
function touchStart(evt) {
  var changedTouches = evt.changedTouches;   
  for (var i = 0; i < changedTouches.length; i++) {
    // remember new touches and its key
    var key = changedTouches[i].target;
    touches.push({ id : changedTouches[i].identifier, key: key });
  }
  updateKeys();
}

function touchEnd(evt) {
  var changedTouches = evt.changedTouches;
  for (var i = 0; i < changedTouches.length; i++) {
    // Remove this touch
    var index = getTouchIndex(changedTouches[i].identifier);
    if (index >= 0) {
        touches.splice(index, 1);
    }  
  }
  updateKeys();
}

有一个棘手的事件是touchmove,因为事件目标仍然是相应touchstart事件的目标。在您的情况下,当手指从一个键移动到另一个键时,您需要计算下一个钢琴键。

function touchMove(evt) {
  var changedTouches = evt.changedTouches;
  for (var i = 0; i < changedTouches.length; i++) {
    var touch = changedTouches[i];
    var index = getTouchIndex(touch.identifier);
    if (index >= 0) {
      // Update stored key to the new key
      var key = document.elementFromPoint(touch.pageX, touch.pageY);
      if (isKey(key))
        touches[index].key = key;
    }      
  }
  updateKeys();
}

钢琴例子:

var keys = [].slice.call(document.querySelectorAll('.key'), 0);
var keyboard = document.getElementById('keyboard');
var touches = [];

keyboard.addEventListener("touchstart", touchStart, false);
keyboard.addEventListener("touchmove", touchMove, false);
keyboard.addEventListener("touchend", touchEnd, false);

function isKey(key) {
 return keys.indexOf(key) >= 0;
}

function updateKeys() {
 keys.forEach(function(key) {
   key.classList.remove("down");
  });
 touches.forEach(function(touch) {
   if (isKey(touch.key))
     touch.key.classList.add("down");
  });
}

function touchStart(evt) {
  evt.preventDefault();
  var changedTouches = evt.changedTouches;   
  for (var i = 0; i < changedTouches.length; i++) {
    var key = changedTouches[i].target;
    touches.push({ id : changedTouches[i].identifier, key: key });
  }
 updateKeys();
}

function touchEnd(evt) {
  evt.preventDefault();
  var changedTouches = evt.changedTouches;
  for (var i = 0; i < changedTouches.length; i++) {
    var index = getTouchIndex(changedTouches[i].identifier);
    if (index >= 0) {
     touches.splice(index, 1);
    }  
  }
  updateKeys();
}

function touchMove(evt) {
  evt.preventDefault();
  var changedTouches = evt.changedTouches;
  for (var i = 0; i < changedTouches.length; i++) {
  var touch = changedTouches[i];
    var index = getTouchIndex(touch.identifier);
    if (index >= 0) {
     var key = document.elementFromPoint(touch.pageX, touch.pageY);
      if (isKey(key))
      touches[index].key = key;
    }      
  }
  updateKeys();
}

function getTouchIndex(id) {
  for (var i = 0; i < touches.length; i++) {
    if (touches[i].id === id) {
      return i;
    }
  }
  return -1;
}
#keyboard {
  background:#333;
  padding:10px;
}
.key {
  height:150px;
  width:35px;
  display:inline-block;
  background: #aee;
}
.key.down {
  background: #aae;
}
<div id="keyboard">
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接