【发布时间】:2017-07-12 15:43:16
【问题描述】:
在下面的 HTML 画布中,我有一个选择菜单,它根据所选内容触发在其旁边绘制图像(下例中的数字 1-5)。 JavaScript 使用伪对象方法来存储/操作在画布上绘制的图像。除了EventListener 附加到画布之外,还有一个EventListener 附加到整个窗口,当窗口大小改变时,它会在严格的纵横比内调整画布的大小。
我目前遇到的问题是,当 EventListener 被触发时(当窗口大小改变时),选择被清除。要在下面的示例中复制这一点,您必须在全屏模式下运行代码 sn-p 并更改浏览器窗口的大小。相反,我希望在窗口(以及相应的画布')大小更改后保持当前选择。我尝试将当前选择分配给一个变量,但我只能让它留下一个静态选择,其中 onHover 动画不起作用。
此外,与此相关,我正在尝试设置在第一次画布绘制时选择的初始选择,直到选择其他选项之一。在这种情况下,当脚本最初加载时,我希望自动选择/显示数字 1 及其对应的图像,直到做出新的选择。同样,将其分配为initialSelection 变量或独立调用makeCurvedRect 会留下静态选择,我的意思是curvedRect(图像)不是动画onHover。
我非常不确定如何实现这些结果,因此我们将不胜感激。为大量代码道歉,但我无法压缩它。
var c=document.getElementById('game'),
rect = c.getBoundingClientRect(),
ctx=c.getContext('2d');
c.width = window.innerWidth;
c.height = (2/3)*c.width;
numberImages = ['https://i.stack.imgur.com/TZIUz.png','https://i.stack.imgur.com/6beTF.png','https://i.stack.imgur.com/wZk2H.png','https://i.stack.imgur.com/1K743.png','https://i.stack.imgur.com/jMMmQ.png'];
var curvedRect = function(number, x, y, w, h) {
this.text = number.toString();
this.img = new Image();
this.img.src=numberImages[number-1];
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.hovered = false;
this.clicked = false;
this.visible = false;
}
var selected;
curvedRect.prototype.makeCurvedRect = function() {
var delta=0, theta=0;
if (this.hovered) {
delta = (c.height*(3/500));
theta = -0.01;
shadowColor = '#000000';
shadowBlur = 20;
shadowOffsetX = 5;
shadowOffsetY = 5;
} else {
delta = 0;
theta = 0;
shadowColor = '#9F3A9B';
shadowBlur = 0;
shadowOffsetX = 0;
shadowOffsetY = 0;
}
var x = this.x-delta;
var y = this.y-delta;
var w = this.w+(2*delta);
var h = this.h+(2*delta);
var cornerRounder = (c.height*(10/500))
ctx.rotate(theta);
ctx.beginPath();
ctx.lineWidth='12';
ctx.strokeStyle='white';
ctx.moveTo(x+cornerRounder, y);
ctx.lineTo(x+w-cornerRounder, y);
ctx.quadraticCurveTo(x+w, y, x+w, y+cornerRounder);
ctx.lineTo(x+w, y+h-cornerRounder);
ctx.quadraticCurveTo(x+w, y+h, x+w-cornerRounder, y+h);
ctx.lineTo(x+cornerRounder, y+h);
ctx.quadraticCurveTo(x, y+h, x, y+h-cornerRounder);
ctx.lineTo(x, y+cornerRounder);
ctx.quadraticCurveTo(x, y, x+cornerRounder, 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(this.img, x+(c.width*(2.5/750)), y+(c.height*(2.5/500)), w-cornerRounder/2, h-cornerRounder/2);
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;
this.visible = true;
}
function makeTextForSelected(text, y) {
ctx.font='bold '+(c.height*(12/500))+'px Noto Sans'; // check
ctx.fillStyle='white';
ctx.textAlign='center';
ctx.fillText(text, (c.width*(200/750)), y);
}
selectionForMenu.prototype.makeSelection = function() {
ctx.globalAlpha=0.75;
var fillColor='#A84FA5';
if (this.hovered) {
if (this.clicked) {
if (this.lastClicked) {
fillColor='#E4C7E2';
makeTextForSelected(this.text, c.height*(375/500));
} else {
fillColor='#D5A9D3';
}
} else if (this.lastClicked) {
fillColor='#D3A4D0';
makeTextForSelected(this.text, c.height*(375/500));
} else {
fillColor='#BA74B7';
}
} else if (this.lastClicked) {
fillColor='#C78DC5';
makeTextForSelected(this.text, c.height*(375/500));
} else {
fillColor='#A84FA5';
}
ctx.beginPath();
ctx.fillStyle=fillColor;
ctx.fillRect(c.width*(400/750), this.y, c.width*(350/750), c.height*(100/500))
ctx.stroke();
ctx.font=c.height*(10/500)+'px Noto Sans';
ctx.fillStyle='white';
ctx.textAlign='left';
ctx.fillText(this.text, c.width*(410/750), this.y+(c.height*(38/500)));
ctx.globalAlpha=1;
}
selectionForMenu.prototype.hitTest = function(x, y) {
return (x >= (c.width*(400/750)) && (x <= c.width) && (y >= this.y) &&
(y <= (this.y+(c.height*(100/500))) && !((x >= c.width*(400/750) && (y > c.height*(450/500))))));
}
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 {
if(this.shapes[i].lastClicked == true) {
this.shapes[i].rect.makeCurvedRect();
}
}
catch(err) {}
}
ctx.beginPath();
ctx.fillStyle='white';
ctx.fillRect(0, 0, c.width, (c.height*(25/500)));
ctx.stroke();
ctx.beginPath();
ctx.fillStyle='#BC77BA';
ctx.fillRect(0, (c.height*(450/500)), c.width, (c.height*(50/500)));
ctx.stroke();
ctx.font='bold '+(c.height*(10/500))+'px Noto Sans';
ctx.fillStyle='#9F3A9B';
ctx.textAlign='center';
ctx.fillText('Test', (c.width*(365/750)), (c.height*(17/500)));
}
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;
if (this.shapes[i].lastClicked == true) {
this.shapes[i].rect.visible = true;
} else {
this.shapes[i].rect.visible = false;
}
}
}
}
this.render();
}
Paint.prototype.select = function(x, y) {
for (var i=this.shapes.length-1; i >= 0; i--) {
if (this.shapes[i].visible == true && this.shapes[i].hitTest(x, y)) {
return this.shapes[i];
}
}
return null
}
var numbers = [1,2,3,4,5];
var paint = new Paint(c);
var selection = [];
for (var i=0; i<numbers.length; i++) {
selection.push(new selectionForMenu(i+1, numbers[i], c.height*(25/500)+(c.height*((i*100)/500))));
}
for (var i=0; i<numbers.length; i++) {
var img = new curvedRect(i+1, (c.width*(112.5/750)), (c.height*(100/500)), (c.height*(175/500)), (c.height*(175/500)));
paint.addShape(img)
selection[i].rect = img;
}
for (var i=0; i<numbers.length; i++) {
paint.addShape(selection[i])
}
paint.render();
var clickedShape, clickIndex=0;
function mouseDown(event) {
var x = (event.pageX-rect.left)/(rect.right-rect.left)*c.width;
var y = (event.pageY-rect.top)/(rect.bottom-rect.top)*c.height;
var shape = paint.select(x, y);
if (shape instanceof selectionForMenu) {
if (clickIndex==0) {
clickedShape=shape;
clickIndex=1;
} else if (clickIndex==1) {
clickIndex=0;
}
}
paint.setClicked(shape);
}
function mouseUp(event) {
var x = (event.pageX-rect.left)/(rect.right-rect.left)*c.width;
var y = (event.pageY-rect.top)/(rect.bottom-rect.top)*c.height;
var shape = paint.select(x, y);
if (clickedShape instanceof selectionForMenu) {
if (x>c.width*(400/750) && y>c.height*(25/500) && y<c.height*(450/500)) {
paint.setUnclicked(shape);
} else if (shape && !(shape instanceof selectionForMenu)) {
paint.setUnclicked(shape);
}
}
}
function mouseMove(event) {
var x = (event.pageX-rect.left)/(rect.right-rect.left)*c.width;
var y = (event.pageY-rect.top)/(rect.bottom-rect.top)*c.height;
var shape = paint.select(x, y);
paint.setHovered(shape);
}
function paintCanvas() {
c.width = window.innerWidth;
c.height = (2/3)*c.width;
ctx=c.getContext('2d');
rect = c.getBoundingClientRect();
paint = new Paint(c);
selection = [];
for (var i=0; i<numbers.length; i++) {
selection.push(new selectionForMenu(i+1, numbers[i], c.height*(25/500)+(c.height*((i*100)/500))));
}
for (var i=0; i<numbers.length; i++) {
var img = new curvedRect(i+1, (c.width*(112.5/750)), (c.height*(100/500)), (c.height*(175/500)), (c.height*(175/500)));
paint.addShape(img)
selection[i].rect = img;
}
for (var i=0; i<numbers.length; i++) {
paint.addShape(selection[i])
}
paint.render();
}
paintCanvas();
window.addEventListener('resize', paintCanvas);
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;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='wordpractice.css' media='screen'></style>
</head>
<body>
<div id='container'>
<canvas id="game"></canvas>
</div>
<script type='text/javascript' src='scaleStack.js'></script>
</body>
</html>
【问题讨论】:
标签: javascript html events canvas