简体   繁体   中英

Draw a square in javascript using canvas

I am using the following code to draw a square. I am new to javascript. Can anyone please tell me what's wrong with the following code? It doesn't draw an exact/correct square. The side/length of the square must be the one that is longer between x & y. I think there are some dimension issues. Please help!

construct: function(pos,parent) {
      obj=Object.create(parent);
      obj.minx=obj.maxx=pos.x;
      obj.miny=obj.maxy=pos.y;
      if (fillColor!="inherit")
        obj.fillStyle=fillColor;
      if (strokeColor!="inherit")
        obj.strokeStyle=strokeColor;
      if (strokeThickness!="inherit")
        obj.lineWidth=strokeThickness;
      },
    draw: function(selected) {
      ctx.beginPath();
      ctx.fillStyle=this.fillStyle;
      ctx.strokeStyle=(selected) ?
                      "gray" : this.strokeStyle;
      ctx.lineWidth=this.lineWidth;

    ctx.rect(this.minx,this.miny,this.maxx,this.maxy);

      ctx.fill();
      if (selected) {
        ctx.moveTo(this.minx,this.miny);
        ctx.lineTo(this.maxx,this.maxy);
        ctx.moveTo(this.minx,this.maxy);
        ctx.lineTo(this.maxx,this.miny);
        }
      ctx.stroke();
      },
    mousedown: function(event) {
      downPos=event;
      square.construct(downPos,drawObject[containingBox4point(downPos)]);
      inDrag=true;
      },
    mousemove: function(event) {
      if (!inDrag)
      {
        drawPrevious();
        drawCursor(event,containingBox4point(event));
        return;
      }
      upPos=event;
      if (upPos.x>downPos.x) {
        obj.minx=downPos.x;
        obj.maxx=upPos.x +  Math.abs(obj.maxy - obj.miny);
        }
      else {
        obj.minx=upPos.x;
        obj.maxx=downPos.x +  Math.abs(obj.maxy - obj.miny);
        }
      if (upPos.y>downPos.y) {
        obj.miny=downPos.y;
        obj.maxy=upPos.y + Math.abs(obj.maxx - obj.minx);
        }
      else {
        obj.miny=upPos.y;
        obj.maxy=downPos.y + Math.abs(obj.maxx - obj.minx);
        }
      drawPrevious();
      obj.draw(containingBox(obj)==(-1));
      drawCursor(event,containingBox4point(upPos));
      }

Drawing a rectangle or square on canvas based on radio button mode

在此输入图像描述在此输入图像描述

I offer this explanation as I respectfully believe your code has gone off course a bit :)

A brief tutorial

This code uses jQuery which smooths out the differences between different web browsers.

<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

First, get a reference to the canvas element

// get a reference to the canvas element

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

Create a canvas context for drawing (called ctx):

// create a canvas context to draw stuff with

var ctx=canvas.getContext("2d");

Set some styles on the context

// set the context's fill and stroke styles
ctx.fillStyle="skyblue";
ctx.strokeStyle="lightgray";
ctx.lineWidth=3;

Save the canvas position on the web page.

This will be used later in calculating mouse position.

// get the canvas's position on the page

var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;

Since we'll be dragging, set up variables to hold the starting XY of the drag

// set up variables to hold the mouse starting X/Y
// when the user drags the mouse
var startX;
var startY;

Create a variable to indicate if we're in the middle of dragging.

// indicate whether the user is dragging the mouse

var isDragging=false;

Create a variable to indicate if we should be drawing a square or a rectangle:

// set up a variable to determine whether to  draw a square or a rectangle

var modeName="square";

This code sets the modeName variable when the user clicks either the “square” or “rectangle” radio button

If the user clicks the "rectangle" radio button, then modeName will be set to "rectangle"

If the user clicks the "square" radio button, then modeName will be set to "square"

// use jQuery to set the modeName variable

$('input[name=mode]').click(function() {
    modeName=$('input[name=mode]:checked').val();
});

Listen for mouse events

Use jQuery to listen for when the user presses/releases mousebutton and moves the mouse.

  • handleMouseDown will be called when the user presses the mouse button down,
  • handleMouseUp will be called when the user releases the mouse button,
  • handleMouseMove will repeatedly be called when the user moves the mouse

Listen for mouse events:

// listen for mousedown, call handleMouseDown when it’s pressed

$("#canvas").mousedown(function(e){handleMouseDown(e);});

// listen for mouseup, call handleMouseUp when it’s released

$("#canvas").mouseup(function(e){handleMouseUp(e);});

// listen for mouse movements, call handleMouseMove when the mouse moves

$("#canvas").mousemove(function(e){handleMouseMove(e);});

Handle when the user presses, releases and moves the mouse—dragging!

When the user presses the mouse down, the handleMouseDown function is called:

  • Store the starting mouse position in startX and startY.
  • Set the isDragging flag to true.

handleMouseDown:

// called when user presses the mouse button down
// This is the start of a drag

function handleMouseDown(e){

  // calculate the mouse position relative to the canvas

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // store the starting mouse position

  startX=mouseX;
  startY=mouseY;

  // set isDragging to indicate we’re starting a drag.

  isDragging=true;
}

When the user releases the mouse button, the handleMouseUp function is called

  • Clear the isDragging flag (drag is over)

handleMouseUp:

// called when the user releases the mouse button,  

function handleMouseUp(e){

  // the drag is over, clear the isDragging flag

  isDragging=false;

}

When the user is dragging, the handleMouseMove function is repeatedly called:

  • If the isDragging flag is not set, just exit.
  • Clear the canvas in preparation for a newly positioned rectangle/square.
  • If the user wants a rectangle, call a function to draw a rectangle.
  • If the user wants a square, call a function to draw a square.

handleMouseMove:

// called repeatedly when the user drags the mouse

function handleMouseMove(e){

  // calculate the mouse position relative to the canvas

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // if the user isn’t dragging, just exit

  if( !isDragging ){ return; }

  // clear the canvas in preparation for drawing a modified square/rectangle

  ctx.clearRect(0,0,canvas.width,canvas.height);

  // this switch decided if the user selected a rectangle or square for drawing

  switch(modeName){

      // the user clicked the rectangle radio button and modeName == “rectangle”

      case "rectangle":

          // call a function that draws a rectangle 

          drawRectangle(mouseX,mouseY);

          break;

      // the user clicked the rectangle radio button and modeName == “square”

      case "square":

          // call a function that draws a square

          drawSquare(mouseX,mouseY);

          break;

      default:
          break;
  }

}

This function draws a rectangle from the startX/startY to the current mouseX/mouseY

function drawRectangle(mouseX,mouseY){
    var width=mouseX-startX;
    var height=mouseY-startY;
    ctx.beginPath();
    ctx.rect(startX,startY,width,height);
    ctx.fill();
    ctx.stroke();
}

This function draws a square from the startX/startY towards the current mouseX/mouseY

All 4 sides of the square will be determined by: mouseX – startX

Since the square must enforce 4 equal sides, when dragging a square, it may appear to “jump”

function drawSquare(mouseX,mouseY){
    var width=Math.abs(mouseX-startX)*(mouseX<startX?-1:1);
    var height=Math.abs(width)*(mouseY<startY?-1:1);
    ctx.beginPath();
    ctx.rect(startX,startY,width,height);
    ctx.fill();
    ctx.stroke();
}

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/myHDW/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:20px;}
    #canvas{border:1px solid red;}
    input{width:15px;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    var startX;
    var startY;
    var isDown=false;

    ctx.fillStyle="skyblue";
    ctx.strokeStyle="lightgray";
    ctx.lineWidth=3;

    var modeName="square";

    $('input[name=mode]').click(function() {
        modeName=$('input[name=mode]:checked').val();
        console.log(modeName);
    });


    function handleMouseDown(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousedown stuff here
      startX=mouseX;
      startY=mouseY;
      isDown=true;
    }

    function handleMouseUp(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#uplog").html("Up: "+ mouseX + " / " + mouseY);

      // Put your mouseup stuff here
      isDown=false;
    }

    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here
      if(!isDown){return;}

      ctx.clearRect(0,0,canvas.width,canvas.height);

      switch(modeName){
          case "rectangle":
              drawRectangle(mouseX,mouseY);
              break;
          case "square":
              drawSquare(mouseX,mouseY);
              break;
          default:
              break;
      }

    }

    function drawRectangle(mouseX,mouseY){
        var width=mouseX-startX;
        var height=mouseY-startY;
        ctx.beginPath();
        ctx.rect(startX,startY,width,height);
        ctx.fill();
        ctx.stroke();
    }

    function drawSquare(mouseX,mouseY){
        var width=Math.abs(mouseX-startX)*(mouseX<startX?-1:1);
        var height=Math.abs(width)*(mouseY<startY?-1:1);
        ctx.beginPath();
        ctx.rect(startX,startY,width,height);
        ctx.fill();
        ctx.stroke();
    }

    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});


}); // end $(function(){});
</script>

</head>

<body>
    <p>Note: the square's side length is determined</p>
    <p>by mouseX minus startingX.</p>
    <p>As a result, the square may "jump" as you</p>
    <p>move left or above the starting point.</p>
    <canvas id="canvas" width=300 height=300></canvas><br>

    <input type="radio" id="rect" name="mode" value="rectangle" />
    <label for="rect">Rectangle</label>
    <input type="radio" id="sqr" name="mode" value="square" checked="checked" /> 
    <label for="sqr">Square</label>

</body>
</html>

[addition: have square be longer of Math.abs(mouseX-startX) and Math.abs(mouseY-startY)]

This alternative drawSquare() will calculate the longer of x-drag and y-drag and use that calculation as the length of the 4 sides of the square:

    function drawSquare(mouseX,mouseY){
        var lengthX=Math.abs(mouseX-startX);
        var lengthY=Math.abs(mouseY-startY);
        if(lengthX>lengthY){
            var width=lengthX*(mouseX<startX?-1:1);
            var height=lengthX*(mouseY<startY?-1:1);
        }else{
            var width=lengthY*(mouseX<startX?-1:1);
            var height=lengthY*(mouseY<startY?-1:1);
        }
        ctx.beginPath();
        ctx.rect(startX,startY,width,height);
        ctx.fill();
        ctx.stroke();
    }

Since I can't add comments, I'd like to add extra info for mathemtical part of drawing square from "markE" algorythm.

If you use:

var lengthX=Math.abs(mouseX-startX);
var lengthY=Math.abs(mouseY-startY);
if(lengthX<lengthY){ //changed this part
    var width=lengthX*(mouseX<startX?-1:1);
    var height=lengthX*(mouseY<startY?-1:1);
}
else{
    var width=lengthY*(mouseX<startX?-1:1);
    var height=lengthY*(mouseY<startY?-1:1);
}

You can remove this square jumping and get more MS Paintlike action.

Thsis the simple Javascript that make Square

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.rect(20, 20, 150, 100);
ctx.stroke();

</script> 

</body>
</html>

For more design click here : How to Create a Centered Square Crop

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM