Основной элемент canvas в HTML5 и JavaScript тестирование


Я написал этот кусок JavaScript, чтобы просто узнать основы рисования на/взаимодействие с HTML5-элемента canvas.

Просто хочу убедиться, что я делаю все "правильно" в случае, если у меня есть какие-то явные гаффы код или есть более эффективный способ.

function start() {
  canvas = document.getElementById("area");

  // initiate ball
  ball.init({
    context: canvas.getContext('2d'),
    color: "#F33",
    radius: 30,
  });
}

var ball = (function() {
  var ball;

  var mouseMoveEvent;
  var prevMouseMoveEvent;

  // set default options
  var default_options = {
    context: "", // required
    radius: 20,
    color: "#F33",
    startX: window.innerWidth / 2,
    startY: window.innerHeight / 2
  };

  return {
    draw: function() {
      // prep canvas
      ball.o.context.canvas.width = window.innerWidth;
      ball.o.context.canvas.height = window.innerHeight;

      //capture current position values
      var cur_x = ball.posX;
      var cur_y = ball.posY;

      //capture current context dimensions
      var ctx_width = ball.o.context.canvas.width;
      var ctx_height = ball.o.context.canvas.height;


      if (ball.isGrabbed) {
        //-------------- track ball with mouse when grabbed
        mouseOffsetX = mouseMoveEvent.x - prevMouseMoveEvent.x;
        mouseOffsetY = mouseMoveEvent.y - prevMouseMoveEvent.y;

        ball.posX += mouseOffsetX;
        ball.posY += mouseOffsetY;

        // save previous mouse move state
        prevMouseMoveEvent = mouseMoveEvent;
      } else {
        //-------------- bounding
        var x_reach = Math.abs(ball.iterX) + ball.o.radius;
        var y_reach = Math.abs(ball.iterY) + ball.o.radius;

        if ((cur_x + x_reach) > ctx_width || (cur_x - x_reach) < 0)
          ball.iterX = -(.70 * ball.iterX);

        if ((cur_y + y_reach) > ctx_height || (cur_y - y_reach) < 0)
          ball.iterY = -(.70 * ball.iterY);

        ball.iterX *= .999;
        ball.iterY *= .999;
        ball.posX += ball.iterX;
        ball.posY += ball.iterY;
      }

      //-------------- protect browser borders
      // North
      if (ball.posY - ball.o.radius < 0)
        ball.posY = ball.o.radius;
      // South
      else if (ball.posY + ball.o.radius > ctx_height)
        ball.posY = ctx_height - ball.o.radius;
      // East
      else if (ball.posX + ball.o.radius > ctx_width)
        ball.posX = ctx_width - ball.o.radius;
      // West
      else if (ball.posX - ball.o.radius < 0)
        ball.posX = ball.o.radius;

      //-------------- draw
      ball.o.context.beginPath();
      ball.o.context.fillStyle = ball.o.color;
      ball.o.context.arc(ball.posX, ball.posY, ball.o.radius, 0, Math.PI * 2, true);
      ball.o.context.closePath();
      ball.o.context.fill();
    },
    mouseDown: function(e) {
      // grab ball
      if (ball.o.context.isPointInPath(e.x, e.y)) {
        prevMouseMoveEvent = e;
        ball.isGrabbed = true;
      }
    },
    mouseUp: function(e) {
      // release
      if (ball.isGrabbed) {
        // set iter speed based on mouse speed on release
        ball.iterX = mouseMoveEvent.x - prevMouseMoveEvent.x;
        ball.iterY = mouseMoveEvent.y - prevMouseMoveEvent.y;

        ball.isGrabbed = false;
      }
    },
    mouseMove: function(e) {
      if (ball.o.context.isPointInPath(e.x, e.y)) {
        document.body.style.cursor = "move";
      } else {
        document.body.style.cursor = "default";
      }
      mouseMoveEvent = e;
    },
    init: function(options) {
      ball = this;

      //load up defaults
      ball.o = default_options;

      // merge in user options that exist
      for (var attr in options) {
        ball.o[attr] = options[attr];
      };

      // set starting values
      ball.posX = ball.o.startX;
      ball.posY = ball.o.startY;
      ball.iterX = 0;
      ball.iterY = 0;
      ball.isGrabbed = false;

      // attach events
      window.onmousedown = ball.mouseDown;
      window.onmouseup = ball.mouseUp;
      window.onmousemove = ball.mouseMove;

      // start
      setInterval(ball.draw, 1);
    },
  };

})();
body {
  margin: 0px;
}

#area {
  width: 100%;
  height: 100%;
  margin: 0px;
  background: #FF7
}
<body onLoad="start();">
  <canvas id="area"></canvas>
</body>



322
1
задан 23 августа 2011 в 08:08 Источник Поделиться
Комментарии
1 ответ

Это выглядит довольно хорошо. В начало функции, холст переменная должна быть объявлена с Вар; неявные глобальные переменные являются одним из худших частей.

function start()
{
var canvas = document.getElementById("area");

// ...
}

Во-вторых, оператор VAR можно объявить несколько переменных одновременно, так как

var cur_x = ball.posX;
var cur_y = ball.posY;

должно быть

var cur_x = ball.posX, cur_y = ball.posY;

В-третьих, эта линия

for (var attr in options) { ball.o[attr] = options[attr]; };


  1. лишняя точка с запятой в конце и, что более важно

  2. не сделать проверку метода hasOwnProperty.

Подавляющее большинство времени, при переборе свойств объекта, вы должны проверить, чтобы убедиться, что свойства существуют на самом деле на объекте, а не в цепочке прототипов. Более подробную информацию читайте эту статью Дугласа Крокфорда. Так это должно выглядеть:

for (var attr in options) {
if (options.hasOwnProperty(attr))
ball.o[attr] = options[attr];
}

1
ответ дан 24 августа 2011 в 04:08 Источник Поделиться