HTML Canvas& JavaScript - 在选择上重新定义对象

时间:2017-05-12 12:29:03

标签: javascript html html5 canvas html5-canvas

下面的脚本在屏幕左侧绘制图像,在右侧绘制一个选择框。然后,它会尝试通过使imageID依赖于选择来重新定义右侧选择框中每个新选择上左侧绘制的图像。但是,正如您在下面看到的那样,无论您在右侧选择哪个数字,图像都保持不变(1),因为虽然可能会重新绘制,但在选择时不会重新定义。我想要发生的是,在右侧框中的选择中,图像中的数字随选择框而变化,使得它始终与选择相关联。换句话说,当您单击2时,图像将更改为images中的第二个图像。我找到了两种方法,但它们都存在缺陷:

1:img的{​​{1}}函数中定义paint。这可以工作,但它使一切运行非常缓慢,并且图像上的悬停动画停止按预期工作。

2:render函数中定义img。这也有效,但如果这样做,悬停动画将完全停止工作。

我为长代码道歉但我无法再浓缩它。为了简洁起见,我只包括1和1之间数字的图像。任何帮助都将不胜感激。

makeSelectionInfo
var c=document.getElementById('game'),
		canvasX=c.offsetLeft,
		canvasY=c.offsetTop,
		ctx=c.getContext('2d');

images=['https://i.stack.imgur.com/KfN4z.jpg',
        'https://i.stack.imgur.com/MyQS1.png',
        'https://i.stack.imgur.com/3Vlfj.jpg',
        'https://i.stack.imgur.com/u3NLH.jpg',
        'https://i.stack.imgur.com/XnLwl.png'];

var curvedRect = function(text, x, y, w, h) {
this.text = text;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.hovered = false;
this.clicked = false;
}

curvedRect.prototype.makeCurvedRect = function() {
var delta=0, theta=0, yRotation=this.y;
if (this.hovered) {
	delta = 3;
	shadowColor = '#000000';
	shadowBlur = 20;
	shadowOffsetX = 5;
	shadowOffsetY = 5;
	theta = -0.01;
} else {
	delta = 0;
	theta = 0;
	shadowColor = '#9F3A9B';
	shadowBlur = 0;
	shadowOffsetX = 0;
	shadowOffsetY = 0;
}
var x = this.x-delta;
var y = yRotation-delta;
var w = this.w+(2*delta);
var h = this.h+(2*delta);
var img=new Image();
img.src=images[this.text];
ctx.rotate(theta);
ctx.beginPath();
ctx.lineWidth='8';
ctx.strokeStyle='white';
ctx.moveTo(x+10, y);
ctx.lineTo(x+w-10, y);
ctx.quadraticCurveTo(x+w, y, x+w, y+10);
ctx.lineTo(x+w, y+h-10);
ctx.quadraticCurveTo(x+w, y+h, x+w-10, y+h);
ctx.lineTo(x+10, y+h);
ctx.quadraticCurveTo(x, y+h, x, y+h-10);
ctx.lineTo(x, y+10);
ctx.quadraticCurveTo(x, y, x+10, y);
ctx.shadowColor = shadowColor;
ctx.shadowBlur = shadowBlur;
ctx.shadowOffsetX = shadowOffsetX;
ctx.shadowOffsetY = shadowOffsetY;
ctx.stroke();
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.drawImage(img, x+2.5, y+2.5, w-5, h-5);
ctx.rotate(-theta);
}

curvedRect.prototype.hitTest = function(x, y) {
return (x >= this.x) && (x <= (this.w+this.x)) && (y >= this.y) && (y <= (this.h+this.y));
}

var selectionForMenu = function(id, text, y) {
	this.id = id;
	this.text = text;
	this.y = y;
	this.hovered = false;
	this.clicked = false;
	this.lastClicked = false;
}
function makeTextForSelected(text, y) {
    ctx.font='bold 12px Noto Sans';
    ctx.fillStyle='white';
    ctx.textAlign='center';
    ctx.fillText(text, 200, y);
}

function makeSelectionInfo(text) {
    makeTextForSelected(text, 375);
}

selectionForMenu.prototype.makeSelection = function() {
	var fillColor='#A84FA5';
	if (this.hovered) {
		if (this.clicked) {
			if (this.lastClicked) {
				fillColor='#E4C7E2';
			} else {
				fillColor='#D5A9D3';
			}
		} else if (this.lastClicked) {
			fillColor='#D3A4D0';
			makeSelectionInfo(this.text);
		} else {
			fillColor='#BA74B7';
		}
	} else if (this.lastClicked) {
		fillColor='#C78DC5';
		makeSelectionInfo(this.text);
	} else {
		fillColor='#A84FA5';
	}
	ctx.beginPath();
	ctx.fillStyle=fillColor;
	ctx.fillRect(400, this.y, 350, 30)
	ctx.stroke();

	ctx.font='10px Noto Sans';
	ctx.fillStyle='white';
	ctx.textAlign='left';
	ctx.fillText(this.text, 410, this.y+19);
}

selectionForMenu.prototype.hitTest = function(x, y) {
	return (x >= 400) && (x <= (750)) && (y >= this.y) && (y <= (this.y+30)) && !((x >= 400) && (y > 450));
}

var Paint = function(element) {
	this.element = element;
	this.shapes = [];
}

Paint.prototype.addShape = function(shape) {
	this.shapes.push(shape);
}

Paint.prototype.render = function() {
	ctx.clearRect(0, 0, this.element.width, this.element.height);

	for (var i=0; i<this.shapes.length; i++) {
		try {
			this.shapes[i].makeSelection();
		}
		catch(err) {}
		try {
			this.shapes[i].makeCurvedRect();
		}
		catch(err) {}
	}

	ctx.beginPath();
	ctx.fillStyle='white';
	ctx.fillRect(0, 0, 750, 25);
	ctx.stroke();

	for (var i=0; i<this.shapes.length; i++) {
		try {
			this.shapes[i].makeBox();
		}
		catch(err) {}
	}

	ctx.beginPath();
	ctx.fillStyle='#BC77BA';
	ctx.fillRect(0, 450, 750, 50);
	ctx.stroke();

	ctx.font='bold 10px Noto Sans';
	ctx.fillStyle='#9F3A9B';
	ctx.textAlign='center';
	ctx.fillText('Phrase Practice', 365, 17);

	for (var i=0; i<this.shapes.length; i++) {
		try {
			this.shapes[i].makeInteractiveButton();
		}
		catch(err) {}
	}
}

Paint.prototype.setHovered = function(shape) {
	for (var i=0; i<this.shapes.length; i++) {
		this.shapes[i].hovered = this.shapes[i] == shape;
	}
	this.render();
}

Paint.prototype.setClicked = function(shape) {
	for (var i=0; i<this.shapes.length; i++) {
		this.shapes[i].clicked = this.shapes[i] == shape;
	}
	this.render();
}

Paint.prototype.setUnclicked = function(shape) {
	for (var i=0; i<this.shapes.length; i++) {
		if (shape.constructor.name==this.shapes[i].constructor.name) {
			this.shapes[i].clicked = false;
		 	if (shape instanceof selectionForMenu) {
				this.shapes[i].lastClicked = this.shapes[i] == shape;
			}
		}
	}
	this.render();
}

Paint.prototype.select = function(x, y) {
	for (var i=this.shapes.length-1; i >= 0; i--) {
		if (this.shapes[i].hitTest(x, y)) {
			return this.shapes[i];
		}
	}
	return null
}

imageID = 0;

var paint = new Paint(c);
var img = new curvedRect(imageID, 112.5, 100, 175, 175);
var selection = [];
for (i=0; i<=30; i++) {
	selection.push(new selectionForMenu(i, i, 25+(i*30)));
}

paint.addShape(img);
for (i=0; i<30; i++) {
	paint.addShape(selection[i])
}

paint.render();

var clickedShape=0;
var i=0;
function mouseDown(event) {
	var x = event.x - canvasX;
	var y = event.y - canvasY;
	var shape = paint.select(x, y);
	if (shape instanceof selectionForMenu) {
		imageTextID = shape.id;
		if (i==0) {
			clickedShape=shape;
			i=1;
		} else if (i==1) {
			i=0;
		}
	}
	paint.setClicked(shape);
}

function mouseUp(event) {
	var x = event.x - canvasX;
	var y = event.y - canvasY;
	var shape = paint.select(x, y);
	if (clickedShape instanceof selectionForMenu) {
		if (x>400 && y>25 && y<450) {
			paint.setUnclicked(shape);
		} else if (shape && !(shape instanceof selectionForMenu)) {
			paint.setUnclicked(shape);
		}
	}
}

function mouseMove(event) {
	var x = event.x - canvasX;
	var y = event.y - canvasY;
	var shape = paint.select(x, y);

	paint.setHovered(shape);
}

c.addEventListener('mousedown', mouseDown);
c.addEventListener('mouseup', mouseUp);
c.addEventListener('mousemove', mouseMove);
canvas {
  z-index: -1;
  margin: 1em auto;
  border: 1px solid black;
  display: block;
  background: #9F3A9B;
}

1 个答案:

答案 0 :(得分:1)

修复了您的代码https://jsfiddle.net/0wq0hked/2/

你可以看看我改变了什么,但基本上你没有初始化并将多个curvedRect添加到Paint.shapes数组。我还将图像添加为curvedRect的属性。

我还必须在您的形状中添加visible参数,因为鼠标悬停Paint.select功能无法正常运行。你的工作方式,共享相同(x,y)的形状不允许其他形状徘徊,即使它们不可见。因此,占据左侧图像区域的多个形状阻止了悬停的正常工作。我想你可以在绘制时保留你的Paint.select和实例/删除形状,但据我所知,你没有形状去除功能。

此外,您在每个事件上调用渲染,这是一个坏主意。看看requestAnimationFrame并尝试以屏幕刷新率而不是用户输入进行绘制。