无法在html5画布上绘制超过1个形状 [英] unable to draw more then 1 shape on html5 canvas

查看:73
本文介绍了无法在html5画布上绘制超过1个形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码在canvas上绘制1个多边形。我不知道它为什么不绘制多于1个多边形。我知道它与汽车积分为空或启动是假的有关

但即使做了一些改变之后也没用了

任何人都可以帮助我将此代码转换为函数或其他内容或更正它以便我可以绘制多于1个多边形?







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?



<!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>

推荐答案

好首先 - 你更愿意被称为stacy m alina或mugjees ilyas吗?

我已经看到你关于堆栈溢出的问题..



无论如何,你需要考虑很多事情,按照我重新打电话的顺序列出。



1。你开始每秒10次的路径,但你永远不会关闭它。不完全推荐。



2。您将选择框的每个选项标记为已选择 - 只为其中一个选项执行。此外,从这里保存的值初始化当前颜色可能是个好主意。这样你的HTML控制javascript,你不必维护这两者。 - 即你在javascript中将颜色设置为红色,但是选择框在Chrome窗口中显示黄色。



3。你'在选择框的更改处理程序中过于冗长。你只需要写 this.value



4。你只需要得到了一个点阵。不太确定你如何期望绘制多于1个多边形,而没有更多的1个位置来存储点。这不像你可以假设多边形中的点数 - 它可能是3或它可能是8 ..



5。您不能将多边形的颜色保存在任何位置。我猜这意味着你最终会把它们全部绘制成相同的颜色。也许不是你的想法。



6。你没有使用jQuery的东西,不需要浪费带宽包括它。页面加载速度也快得多。



7。你已经有了积分的想法 - 让一个对象保持住x,y坐标。你为多边形的存储做同样的事情怎么样?您需要存储的只是定义它的点数组及其颜色。然后你可以维护一个已绘制的多边形数组。



8。你每秒更新10次,无论是用户已采取可更新屏幕的操作。主电源设备上的少量多边形没有真正的问题,但电池供电的设备有点耗电。也相当不合理。我没有打扰过,但你可以考虑制作一个z-index较高的第二个画布,与当前画布位于同一个地方。然后,您可以在下部画布上绘制完整的多边形,因为您永远不需要清除它。然后,只要移动鼠标或更改颜色,就可以在较高的z-index画布上重绘正在进行的多边形。更好的方法可能是响应鼠标移动而不是计时器。您可以获得绘制多边形的时间,并且只有在自上次以来经过了超过100毫秒的时间后才绘制它。这会将最大重绘次数限制为每秒10次,但如果没有任何改变,则绝对不会做任何事情。



除了#8,我已经解决了所有问题 - 我请留下让你考虑。



编辑:更新的代码 - 增加绘制单行段或poylgons的能力。

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.

updated code - adds ability to draw either single line segments or poylgons.
<!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>


这篇关于无法在html5画布上绘制超过1个形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆