Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
the below code draw 1 polygon on canvas.i dont know why it does not draw more then 1 polygon. i know it has something to do with car points being null or isstarted being false
but even after doing some changes it was of no use
can anyone help me with it like convert this code into a function or something or correct it so i can draw more then 1 polygon?



HTML
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div id="board">
<canvas id="canvas" width="300" height="300" style="border: 1px solid black;"></canvas>
		<br /><br />
		<input type="button" value="Save" onclick="save();" />&nbsp;
		<input type="button" value="reset" onclick="reset(); " />&nbsp;
		
</p>
</div><!-- END board -->
</body>
</html>

<style>
body {
        margin: 0;      
}
 
#board {
        margin: 0 auto;
        width: 500px;   
}
 
#myCanvas {
        border: 3px dotted #000;        
}
</style>

<script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js?ver=1.4.2"></script>
<script type="text/javascript">
var END_CLICK_RADIUS = 5;
			var MAX_POINTS = 8;
			var mouseX = 0;
			var mouseY = 0;
			var isStarted = false;
			var points = null;
			var canvas = null;
			var ctx = null;
			window.onload = function() {
			
				canvas = document.getElementById("canvas");
				ctx = canvas.getContext("2d");
				
				//changeColor("red");
				canvas.addEventListener("click", function(e) {
					var x = e.clientX-canvas.offsetLeft;
					var y = e.clientY-canvas.offsetTop;
					if(isStarted) {
						//drawing the next line, and closing the polygon if needed
						if(Math.abs(x - points[0].x) < END_CLICK_RADIUS && Math.abs(y - points[0].y) < END_CLICK_RADIUS) {
							isStarted = false;
						
						} else {
							points[points.length] = new Point(x, y);
							if(points.length >= MAX_POINTS) {
								isStarted = false;
								
							}
						}
					}
					else
					if(points == null) {
						//opening the polygon
						points = new Array();
						points[0] = new Point(x, y);
						isStarted = true;
					}
				}, false);
				
				//we just save the location of the mouse
				canvas.addEventListener("mousemove", function(e) {
					mouseX = e.clientX - canvas.offsetLeft;
					mouseY = e.clientY - canvas.offsetTop;
				}, false);
				
				//refresh time
				setInterval("draw();", 100);
			}
			
			
			//object representing a point
			function Point(x, y) {
				this.x = x;
				this.y = y;
			}
			
			
			//draws the current chape
			function draw() {
				ctx.clearRect(0, 0, canvas.width, canvas.height);
			
				ctx.beginPath();

				if(points != null && points.length > 0) {
					ctx.moveTo(points[0].x, points[0].y);
					
					for(i = 1 ; i < points.length ; i++) {
						ctx.lineTo(points[i].x, points[i].y);
					}
					
					if(isStarted) {
						ctx.lineTo(mouseX, mouseY);
					} else {
						ctx.lineTo(points[0].x, points[0].y);
					}
				}
				
				ctx.stroke();
				
			}
</script>
Posted
Updated 6-Dec-13 4:37am
v2

1 solution

Well, first of all - would you prefer to be called "stacy m alina" or "mugjees ilyas"?
I've already seen your question on stack overflow..

Anyway there's a number of things you need to consider, listed in the order that I reccall them.

1. You begin a path 10 times a second, yet you never close it. Not exactly recommended.

2. You mark every option of the select box as 'selected' - just do it for one of them. Also, probably a good idea to initialize the current colour from the value held here. That way your html controls the javascript and you don't have to maintain both. - I.e you set the colour to red in the javascript, yet the select box shows yellow in Chrome on windows.

3. You've been overly verbose in the change handler for the select box. You only need to write this.value

4. You've only got a single array of points. Not quite sure how you expect to draw more than 1 polygon without having more that 1 place to store points. It's not like you can assume the number of points in a polygon - it could be 3 or it could be 8..

5. You don't save the colour of the polygon anywhere. I guess that would mean you end up drawing them all the same colour. Perhaps not what you had in mind.

6. You're not using a thing from jQuery, no need to waste bandwidth by including it. The page loads much quicker with its omission, too.

7. You've got the idea for points - make an object to hold the x,y coords. How about you do the same thing for the storage of polygons? All you need to store is the array of points that define it, along with its colour. You can then maintain an array of the polygons that have been drawn too.

8. You're updating 10 times a second, whether the user has taken action that would update the screen or not. No real problem with a small number of polygons on a mains-powered device, but a bit power-hungry for battery powered devices. Also rather inneficient. I haven't bothered, but you may consider making a second canvas with a higher z-index, positioned at the same place as the current one. Then, you could draw completed polygons on the lower canvas, since you never need to clear it. You could then redraw the in-progress polygon on the higher z-index canvas whenever the mouse was moved or the colour changed. A better approach again may be to respond to mouse-movement rather than a timer. You could get the time when you draw the polygon and only draw it if mroe than 100ms has elapsed since last time. This would cap the maximum number of redraws to 10 per second, yet do absolutely nothing if nothing had changed.

I've addressed all points except #8 - I'll leave that for you to consider.

EDIT: updated code - adds ability to draw either single line segments or poylgons.
HTML
<!DOCTYPE html>
<head>
<script>
var END_CLICK_RADIUS = 5;
//the max number of points of your poygon
var MAX_POINTS = 8;

var mouseX = 0;
var mouseY = 0;
var isStarted = false;

var points = null;
var polygons = null;
var lines = null;

var canvas = null;
var ctx = null;


window.addEventListener('load', onPageLoaded, false);

function byId(e){return document.getElementById(e);}

//object representing a point
function Point(x, y)
{
	this.x = x;
	this.y = y;
}

// object representing a polygon
function Polygon(points, color)
{
	this.points = points;
	this.color = color;
}

// object representing a single line segment
function LineSegment(point1, point2, color)
{
	this.p1 = point1;
	this.p2 = point2;
	this.color = color;
}

function onPageLoaded() 
{
	canvas = document.getElementById("canvas");
	ctx = canvas.getContext("2d");
	setColor( byId('color').value );
	
	canvas.addEventListener("click", onCanvasClick, false);
	canvas.addEventListener("mousemove", onCanvasMouseMove, false);

	polygons = new Array();
	lines = new Array();
	
	//refresh time
	setInterval(updateScreen, 100);
}

function onCanvasMouseMove(e)
{
	mouseX = e.clientX - canvas.offsetLeft;
	mouseY = e.clientY - canvas.offsetTop;
}

function addPolygon()
{
	polygons[polygons.length] = new Polygon(points, byId('color').value);
	alert(polygons.length + " polygons completed");
}

function addLine()
{
	lines[lines.length] = new LineSegment(points[0], points[1], byId('color').value);
}

function onCanvasClick(e) 
{
	var x = e.clientX-canvas.offsetLeft;
	var y = e.clientY-canvas.offsetTop;
	
	switch (byId('shapeType').value)
	{
		case 'poly': polyClick(x,y);
					 break;
		case 'line': lineClick(x,y);
					 break;
	}
}


function lineClick(x,y)
{
	if (isStarted)
	{
		points[points.length] = new Point(x,y);
		addLine();
		reset();
		isStarted = false;
	//	points = new Array();
	}
	else
	{
		isStarted = true;
		points = new Array();
		points[points.length] = new Point(x,y);
	}
}

function polyClick(x, y)
{
	if(isStarted) 
	{
		//drawing the next line, and closing the polygon if needed
		if(Math.abs(x - points[0].x) < END_CLICK_RADIUS && Math.abs(y - points[0].y) < END_CLICK_RADIUS) 
		{
			isStarted = false;
			addPolygon();
			reset();
		} 
		else 
		{
			points[points.length] = new Point(x, y);
			if(points.length >= MAX_POINTS) 
			{
				addPolygon();
				reset();
			}
		}
	} 
	
	else if(points == null) 
	{
		//opening the polygon
		points = new Array();
		points[0] = new Point(x, y);
		isStarted = true;
	}
}


//changes the color of the draw
function setColor(color)
{
	ctx.strokeStyle = color;
}

//resets the application
function reset() 
{
	isStarted = false;
	points = null;
}

// called whenever the screen needs updating
function updateScreen()
{
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	
	switch (byId('shapeType').value)
	{
		case 'poly':	
			drawIncompletePolygon();
			break;
		case 'line':	
			drawIncompleteLine();
			break;
	}
	

	var i, n;
	n = polygons.length;
	for (i=0; i<n; i++)
		drawPolygon(polygons[i]);
		
	n = lines.length;
	for (i=0; i<n; i++)
		drawLineSegment(lines[i]);
	
}

// draws an arbitrary polygon. Takes a Polygon object as the input
function drawPolygon(polyToDraw)
{
	setColor(polyToDraw.color);
	var i, n = polyToDraw.points.length;
	ctx.beginPath();
	
	ctx.moveTo(polyToDraw.points[0].x, polyToDraw.points[0].y);
	for (i=1; i<n; i++)
		ctx.lineTo(polyToDraw.points[i].x, polyToDraw.points[i].y);

	ctx.lineTo(polyToDraw.points[0].x, polyToDraw.points[0].y);
	
	ctx.closePath();
	ctx.stroke();
}

function drawLineSegment(lineSegToDraw)
{
	setColor(lineSegToDraw.color);
	ctx.beginPath();
	ctx.moveTo(lineSegToDraw.p1.x, lineSegToDraw.p1.y);
	ctx.lineTo(lineSegToDraw.p2.x, lineSegToDraw.p2.y);
	ctx.closePath();
	ctx.stroke();
}

function drawIncompleteLine()
{
	if (isStarted)
	{
		setColor(byId('color').value);
		ctx.beginPath();
		ctx.moveTo(points[0].x, points[0].y);
		ctx.lineTo(mouseX, mouseY);
		ctx.closePath();
		ctx.stroke();
	}
}


//draws the current **in-progress** shape
function drawIncompletePolygon() 
{
	setColor(byId('color').value);
	
	ctx.beginPath();

	if(points != null && points.length > 0) 
	{
		ctx.moveTo(points[0].x, points[0].y);

		for(i = 1 ; i < points.length ; i++) 
		{
			ctx.lineTo(points[i].x, points[i].y);
		}

		if(isStarted) 
		{
			ctx.lineTo(mouseX, mouseY);
		} 
		else 
		{
			ctx.lineTo(points[0].x, points[0].y);
		}
	}
	ctx.stroke();
	ctx.closePath();
}
</script>

<style>
body
{
	margin: 0;      
}

#board
{
	margin: 0 auto;
	width: 500px;   
}

#myCanvas
{
	border: 3px dotted #000;        
}
</style>
</head>
<body>
<div id="board">
<canvas id="canvas" width="300" height="300" style="border: 1px solid black;"></canvas>
<br />
<select id='shapeType'>
	<option value="poly" selected>Polygon</option>
	<option value="line">Line</option>
</select>
Couleur : <select id="color" onchange="setColor(this.value);">
	<option value="red" selected="selected">Red</option>
	<option value="blue">Blue</option>
	<option value="green">green</option>
	<option value="black">black</option>
	<option value="yellow">yellow</option>
</select>
</div>
</body>
</html>
 
Share this answer
 
v2
Comments
Thomas Daniels 6-Dec-13 12:09pm    
+5 for a great and complete answer (especially the first sentence)!
enhzflep 6-Dec-13 12:15pm    
Thanks mate. (:smirk: I couldn't resist)
mughees ilyas 6-Dec-13 12:32pm    
WOW just WOW
and call me mughees :) stacy m alina is a friend whose computer i was using earlier.
and that was some serious help u did there with the code :)
you the best
enhzflep 6-Dec-13 12:43pm    
:SMILES:

Cool mughees. I figured you've shown clear effort, seem to have grasped the overwhelming majority of the concepts involved and stated where you thought the problem was.
Finally, you asked for help and didn't demand it or say that it was urgent.

If you keep up that kind of an approach, people will usually be more than happy to help.
mughees ilyas 6-Dec-13 12:40pm    
and can u guide me how to delete a shape too once it is drawn ?
i know how to make an eraser tool but is it possible to click and delete the entire shape with one click ?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900