canvas - 可点击、可触摸的矩形动画和播放声音

canvas - clickable, touchable rectangles that animate and play sounds

I made this with DOM events and CSS transitions 我真的很难弄清楚如何用 canvas 制作这样的东西。我希望能够有触摸事件并最终播放声音。

我正在查看 phaser.js,它看起来很有希望,但是在形状上创建事件处理程序不是内置的。

这个想法似乎是绘制一堆矩形,监听整个 canvas 上的触摸和单击事件,然后找出要为哪个相应的矩形设置动画...但我迷路了考虑一下。

DOM 这么简单,canvas 这么难?非常感谢所有帮助。

当您知道 canvas 是一个包含多个绘图的单个元素时,这并不难。只有 canvas 元素本身会触发事件。 canvas 上的多个绘图中的每一个都不会触发单独的事件。

因此,要对 canvas 产生效果,您必须手动处理这些任务:

  • 保存每个条形音箱的定义:它的 x、y 位置及其宽度和高度

  • 监听鼠标事件

  • 通过对每个已保存的条形音箱进行鼠标点击测试,手动测试鼠标事件是否发生在其中一个条形音箱内

  • 如果鼠标在特定条形音箱内,播放该条形音箱的声音并用颜色突出显示该条形。

下面是带注释的示例代码和演示:

// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;

// create an array of objects representing each sound to be played
var sounds=[];
for(var i=0;i<15;i++){
  sounds.push({
    element:document.createElement('audio'),
    src:'https://dl.dropboxusercontent.com/u/139992952/multple/Ticking_Clock-KevanGC-1934595011.mp3',
    isPlaying:false
  });
  document.body.appendChild(sounds[i].element);
  sounds[i].element.src=sounds[i].src;
}

// create an array of objects representing the hit area of each "sound-bar"
var hits=[];
for(var i=0;i<15;i++){
  hits.push({x:213,y:i*43+88,w:750,h:40,fill:randomColor()});
}

// load the sound board
var img=new Image();img.onload=start;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/soundboard.png";
function start(){
  // resize the canvas to image size
  canvas.width=img.width;
  canvas.height=img.height;
  // draw the sound board image
  ctx.drawImage(img,0,0);
  // listen for mousedown events
  $("#canvas").mousedown(function(e){handleMouseDown(e);});
}

// handle mousedown events
function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  // get mouse X&Y
  mx=parseInt(e.clientX-offsetX);
  my=parseInt(e.clientY-offsetY);

  // hit test each sound-bar
  for(var i=0;i<hits.length;i++){
    var h=hits[i];
    // define this sound-bar by drawing it (no stroke/fill)
    ctx.beginPath();
    ctx.rect(h.x,h.y,h.w,h.h);
    // is the mouse in this particular sound-bar
    if(ctx.isPointInPath(mx,my)){
      var s=sounds[i];
      // if this bar is playing sound, pause
      // and redraw the un-highlighted sound board
      if(s.isPlaying){
        s.element.pause();
        ctx.clearRect(0,0,cw,ch);
        ctx.drawImage(img,0,0);
        // if this bar is silent, start playing
        // and fill this bar with a highlight color
      }else{
        s.element.play();
        ctx.fillStyle=hits[i].fill;
        ctx.fill();
      }
      s.isPlaying=!s.isPlaying;
    }
  }
}

// adjust for window scrolling
window.onscroll=function(e){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;
}

// utility: get a random color
function randomColor(){ 
  return('#'+Math.floor(Math.random()*16777215).toString(16));
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Click on a sound-bar to play it's sound<br>Click again to pause its sound</h4>
<canvas id="canvas" width=300 height=300></canvas>