Reputation: 33
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));
}
Upvotes: 3
Views: 14610
Reputation: 1
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
Upvotes: -1
Reputation: 41
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.
Upvotes: 2
Reputation: 105015
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.
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:
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
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:
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();
}
Upvotes: 15