2013-06-21 3 views
1

Я пытаюсь создать простую программу холста, где пользователь может последовательно создавать новые фигуры. Это всего лишь основной создатель прямоугольника (я надеюсь расширить его больше на круги, линии и, возможно, даже на другие вещи). Прямо сейчас, хотя я создал что-то, что работает действительно странно.Рисование прямоугольника на Canvas

<html> 
    <head> 
    <meta chartset="utf-8"> 
    <title>Dragging a square</title> 
    <script type="text/javascript"> 
     var canvas, context, startX, endX, startY, endY; 
     var mouseIsDown = 0; 

     function init() { 
      canvas = document.getElementById("canvas"); 
      context = canvas.getContext("2d"); 

      canvas.addEventListener("mousedown", mouseDown, false); 
      canvas.addEventListener("mousemove", mouseXY, false); 

      document.body.addEventListener("mouseup", mouseUp, false); 
     } 

     function mouseUp() { 
      mouseIsDown = 0; 
      //mouseXY(); 
     } 

     function mouseDown() { 
      mouseIsDown = 1; 
      startX = event.clientX; 
      startY = event.clientY; 
      mouseXY(); 
     } 

     function mouseXY(eve) { 
      if (!eve) { 
       var eve = event; 
      } 
      endX = event.pageX - canvas.offsetLeft; 
      endY = event.pageY - canvas.offsetTop; 

      drawSquare(); 
     } 

     function drawSquare() { 
      // creating a square 
      var width = Math.abs(startX - endX); 
      var height = Math.abs(startY - endY); 

      context.beginPath(); 
      context.rect(startX, startY, width, height); 
      context.fillStyle = "yellow"; 
      context.fill(); 
      context.lineWidth = 7; 
      context.strokeStyle = 'black'; 
      context.stroke(); 

     } 
    </script> 
</head> 
<body onload="init()"> 
    <canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas> 
</body> 
    </html> 

Извините за немного странное форматирование, когда я копирую и вставляю свой код. Я думаю, что проблема заключается в моей функции mouseXY. Я хочу, чтобы пользователь щелкнул где-то на холсте, перетащив мышь, чтобы создать прямоугольник, когда пользователь отпустит это, и это конец этой операции, и они могут сразу создать целый новый прямоугольник. На данный момент тип программы просто позволяет мне щелкнуть и создать новый прямоугольник, но если я отпущу кнопку мыши, это не остановится, на самом деле мне нужно щелкнуть еще раз, чтобы остановить его, а затем создаст новый прямоугольник. Я все еще очень новичок в этом, и у меня много проблем с этим, я продолжу работать над этим, и, если я это выясню, я расскажу об этом на сайте. Спасибо Вам и хорошего дня!


Ну, я получил это, чтобы работать (спасибо @Ken), но теперь я пытаюсь решить новую проблему. Я хочу, чтобы можно было разместить несколько прямоугольников на холсте. Я создал функцию, которая представляет Rectangle, а затем создала функцию draw в прямоугольной функции для выделения прямоугольника. Я создал новую функцию под названием addShape(), которая идеально создает объект прямоугольника и вставляет в массив с именем square и drawShapes(), который должен стирать все на холсте и перерисовывать все. Вот что у меня есть до сих пор:

<html> 
    <head> 
    <meta chartset="utf-8"> 
    <title>Dragging a square</title> 
    <script type="text/javascript"> 
     function Rectangle(canvas, x, y, width, height,color) { 
      //this.context = canvas.getContext("2d"); 

      this.x = x; 
      this.y = y; 
      this.width = width; 
      this.height = height; 
      this.color = color; 

      this.draw = function() { 

       this.context.globalAlpha = 0.85; 
       this.context.beginPath(); 
       this.context.rect(this.x, this.y, this.width, this.height); 
       this.context.fillStyle = this.color; 
       this.context.strokeStyle = "black"; 
       this.context.lineWidth = 1; 

       this.context.fill(); 
       this.context.stroke(); 
      }; 

     }; 

     // hold the canvas and context variable, as well as the 
     // starting point of X and Y and the end ones 
     var canvas, context, startX, endX, startY, endY; 
     var mouseIsDown = 0; 

     // An array that holds all the squares 
     var squares = []; 

     window.onload = function() { 
      canvas = document.getElementById("canvas"); 
      context = canvas.getContext("2d"); 

      canvas.addEventListener("mousedown", mouseDown, false); 
      canvas.addEventListener("mousemove", mouseXY, false); 
      canvas.addEventListener("mouseup", mouseUp, false); 
     } 

     function mouseUp(eve) { 
      if (mouseIsDown !== 0) { 
       mouseIsDown = 0; 
       var pos = getMousePos(canvas, eve); 
       endX = pos.x; 
       endY = pos.y; 

       //Square(); //update on mouse-up 
       addShape(); // Update on mouse-up 
      } 
     } 

     function mouseDown(eve) { 
      mouseIsDown = 1; 
      var pos = getMousePos(canvas, eve); 
      startX = endX = pos.x; 
      startY = endY = pos.y; 
      // Square(); //update 
      addShape(); 
     } 

     function mouseXY(eve) { 

      if (mouseIsDown !== 0) { 
       var pos = getMousePos(canvas, eve); 
       endX = pos.x; 
       endY = pos.y; 

       //Square(); 
       addShape(); 
      } 
     } 

     function getMousePos(canvas, evt) { 
      var rect = canvas.getBoundingClientRect(); 
      return { 
       x: evt.clientX - rect.left, 
       y: evt.clientY - rect.top 
      }; 
     } 

     function addShape() { 
      var w = endX - startX; 
      var h = endY - startY; 
      var offsetX = (w < 0) ? w : 0; 
      var offsetY = (h < 0) ? h : 0; 
      var width = Math.abs(w); 
      var height = Math.abs(h); 

      var s = new Rectangle(startX + offsetX, startY + offsetY, width, height, "yellow"); 

      squares.push(s); 

      // Update the display 
      drawShapes(); 
     } 

     function drawShapes() { 
      context.clearRect(0,0,canvas.width,canvas.height); 

      for (var i = 0; i < squares.length; i++) { 
       var shape = squares[i]; 
       shape.draw(); 
      }; 
     } 

     function clearCanvas() { 
      squares = []; 

      drawShapes(); 
     } 

    </script> 
</head> 
<body onload="addShape()"> 
    <canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas><br> 
    <button onclick="clearCanvas()">Clear Canvas</button> 
</body> 
    </html> 

Я уверен, что нарушил оригинальный код ... спасибо за любую помощь!

+1

Что произойдет, если изменить слушатель событий MouseUp на холст, как два других? –

+2

Проблема в том, что вы не используете информацию, собранную 'mouseIsDown' – jeremy

+0

Вы имеете в виду, что я неправильно использую ее как флаг? Должен ли я использовать его в качестве условия для перемещения, возможно ... хорошо, я собираюсь что-то попробовать. – InsigMath

ответ

8

Вы должны изменить пару вещей в коде: (изменить: есть много проблем с этим кодом. Я прошел через некоторые из них встроенные здесь, но не проверял. Если вы положите его на скрипку, это легче для нас, чтобы проверить) ..

Fiddle

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

function mouseDown(eve) { 
    mouseIsDown = 1; 
    var pos = getMousePos(canvas, eve); 
    startX = endX = pos.x; 
    startY = endY = pos.y; 
    drawSquare(); //update 
} 

На левой кнопке мыши, только зарегистрироваться, если isMouseDown верно, иначе эта функция будет обрабатывать все входящие вверх-событий (как вы attatched его документ , что правильно - окно могло быть использовано также):

function mouseUp(eve) { 
    if (mouseIsDown !== 0) { 
     mouseIsDown = 0; 
     var pos = getMousePos(canvas, eve); 
     endX = pos.x; 
     endY = pos.y; 
     drawSquare(); //update on mouse-up 
    } 
} 

только рисовать, если mouseisdown верно:

function mouseXY(eve) { 

    if (mouseIsDown !== 0) { 
     var pos = getMousePos(canvas, eve); 
     endX = pos.x; 
     endY = pos.y; 

     drawSquare(); 
    } 
} 

Кроме того, вы должны очистить предыдущую область т он прямоугольник перед рисованием нового, иначе он не будет отображаться, когда вы нарисуете большой прямоугольник, а затем переместите мышь назад, чтобы нарисовать меньшую.

Для простоты вы можете сделать:

function drawSquare() { 
    // creating a square 
    var width = Math.abs(startX - endX); 
    var height = Math.abs(startY - endY); 

    context.clearRect(0, 0, context.width, context.height); 
    //or use fillRect if you use a bg color 

    context.beginPath(); 
    context.rect(startX, startY, width, height); 
    context.fillStyle = "yellow"; 
    context.fill(); 
    context.lineWidth = 7; 
    context.strokeStyle = 'black'; 
    context.stroke(); 
} 

Используйте это для позиции мыши:

function getMousePos(canvas, evt) { 
    var rect = canvas.getBoundingClientRect(); 
    return { 
     x: evt.clientX - rect.left, 
     y: evt.clientY - rect.top 
    }; 
} 
+0

Спасибо @Ken Я попробую прямо сейчас! – InsigMath

+0

Умм это действительно не исправляет это. Попробуйте перетащить квадрат определенного размера, а затем перетащить его назад, чтобы сделать его меньше, он продолжает таскать, оставляя уродливое пятно. Я хочу иметь возможность изменять его размер, не оставляя этого. – InsigMath

+0

Вот сценарий страницы http://jsfiddle.net/nt3Ny/ – InsigMath