我有一个自定义代码,用于在HTML5画布上创建和渲染对象。
class Rectangle extends Shape {
constructor(options, canvas, type = 'rectangle') {
super(...); // derived from super class
this._options = options;
this._canvas = canvas;
this._context = canvas.context2D;
this._type = type;
this._hovered = false;
this._dragged = false;
this.init();
this.canvas.canvas.onmousemove = (e) => {
this.onMouseHover(e);
};
this.canvas.canvas.onmousedown = (e) => {
this.onMouseDrag(e);
console.log('dragging');
}
this.canvas.canvas.onmouseup = (e) => {
this.onMouseRelease(e);
console.log('release');
}
}
static draw(options, canvas) {
return new Rectangle(options, canvas);
}
// Getter and setter
init() {
this.drawRectangle(...);
}
onMouseHover(e) {
if( // mouse is in the above of shape position
e.clientX >= this.x &&
e.clientX <= this.x + this.width &&
e.clientY >= this.y &&
e.clientY <= this.y + this.height
) {
this.drawRectangle(...) // inverse the border color with background
this.canvas.canvas.style.cursor = 'pointer';
} else {
this.drawRectangle(...) // revert to original
this.canvas.canvas.style.cursor = 'default';
}
}
onMouseDrag(e) {
if( // mouse is in the above of shape position
e.clientX >= this.x &&
e.clientX <= this.x + this.width &&
e.clientY >= this.y &&
e.clientY <= this.y + this.height &&
!this.isDragged
) {
this.canvas.canvas.onmousemove = (drag) => { // while dragging
this.eraseRectangle(...); // erase the rectangle
this.drawRectangle(...); // draw the rectangle while dragging
this.x = drag.clientX; // set the new x position
this.y = drag.clientY; // set the new y position
}
this.isDragged = true;
}
}
onMouseRelease(e) {
if(this.isDragged) {
this.isDragged = false;
this.canvas.canvas.onmousemove = (e) => { // reset it to original
this.onMouseHover(e);
}
}
}
drawRectangle(width, height, x, y, fillStyle, strokeStyle) {
this.context.beginPath();
this.context.fillStyle = fillStyle;
this.context.strokeStyle = strokeStyle;
this.context.rect(x, y, width, height);
this.context.fill();
this.context.stroke();
}
eraseRectangle(width, height, x, y) {
this.context.beginPath();
this.context.clearRect(x-1, y-1, width+2, height+2);
}
}
在主要班级。
class Main {
static ready() {
// Basic options
const options = {
width: window.innerWidth,
height: window.innerHeight,
background: 'black'
}
// Create the canvas object
const canvas = HTMLCanvas.build('workspace', options);
const context = canvas.context2D;
const rect1 = Rectangle.draw({
width: 200,
height: 100,
x: 100,
y: 200,
border: 'blue',
background: 'white',
label: 'rect1'
}, canvas);
const rect2 = Rectangle.draw({
width: 300,
height: 75,
x: 200,
y: 400,
border: 'green',
background: 'white',
label: 'rect2'
}, canvas);
}
}
// Initialize everything
Main.ready();
通过上面的代码,我能够在画布中呈现矩形形状。但是,问题是对象rect1
正在丢失其引用。
rect1
lose reference to the canvas
我无法拖动或悬停rect1
对象,但我仍然可以悬停并拖放rect2
对象。当rect2
悬停拖过rect1
时,rect2
会删除rect1
。
我们如何跟踪每个HTML5画布对象的鼠标事件?大多数解决方案最终会迭代所有对象(将在画布中绘制)并将鼠标事件绑定到它。我希望它在对象本身内,而不是在工厂类中。
答案 0 :(得分:0)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
var imageWidth = 180;
var imageHeight = 160;
var canvas = null;
var ctx = null;
var bounds = null;
var selectedBox = null;
var panX = 0;
var panY = 0;
var mouseX = 0;
var mouseY = 0;
var oldMouseX = 0;
var oldMouseY = 0;
var mouseHeld = false;
var boxArray = [];
function DraggableBox(x,y,width,height,text) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.text = text;
this.isSelected = false;
}
DraggableBox.prototype.isCollidingWidthPoint = function(x,y) {
return (x > this.x && x < this.x + this.width)
&& (y > this.y && y < this.y + this.height);
}
DraggableBox.prototype.drag = function(newX,newY) {
this.x = newX - this.width * 0.5;
this.y = newY - this.height * 0.5;
}
DraggableBox.prototype.draw = function() {
if (this.isSelected) {
ctx.fillStyle = "darkcyan";
ctx.fillRect(
this.x - panX,
this.y - panY,
this.width,
this.height
);
ctx.fillStyle = "black";
} else {
ctx.fillRect(
this.x - panX,
this.y - panY,
this.width,
this.height
);
}
ctx.fillStyle = "white";
ctx.fillText(
this.text,
this.x + this.width * 0.5 - panX,
this.y + this.height * 0.5 - panY,
this.width
);
ctx.fillStyle = "black";
}
window.onmousedown = function(e) {
mouseHeld = true;
if (!selectedBox) {
for (var i = boxArray.length - 1; i > -1; --i) {
if (boxArray[i].isCollidingWidthPoint(mouseX + panX,mouseY + panY)) {
selectedBox = boxArray[i];
selectedBox.isSelected = true;
requestAnimationFrame(draw);
return;
}
}
}
}
window.onmousemove = function(e) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
if (mouseHeld) {
if (!selectedBox) {
panX += oldMouseX - mouseX;
panY += oldMouseY - mouseY;
} else {
selectedBox.x = mouseX - selectedBox.width * 0.5 + panX;
selectedBox.y = mouseY - selectedBox.height * 0.5 + panY;
}
}
oldMouseX = mouseX;
oldMouseY = mouseY;
requestAnimationFrame(draw);
}
window.onmouseup = function(e) {
mouseHeld = false;
if (selectedBox) {
selectedBox.isSelected = false;
selectedBox = null;
requestAnimationFrame(draw);
}
}
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,imageWidth,imageHeight);
var box = null;
var xMin = 0;
var xMax = 0;
var yMin = 0;
var yMax = 0;
ctx.fillStyle = "black";
for (var i = 0; i < boxArray.length; ++i) {
box = boxArray[i];
xMin = box.x - panX;
xMax = box.x + box.width - panX;
yMin = box.y - panY;
yMax = box.y + box.height - panY;
if (xMax > 0 && xMin < imageWidth && yMax > 0 && yMin < imageHeight) {
box.draw();
}
}
}
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
bounds = canvas.getBoundingClientRect();
ctx = canvas.getContext("2d");
ctx.textAlign = "center";
ctx.font = "15px Arial"
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,25,"This is a draggable text box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"Another text box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"Text in a box"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,100,50,"I find this box quite texing"));
boxArray.push(new DraggableBox(Math.random() * 320,Math.random() * 240,150,50,"You weren't supposed to find this box"));
requestAnimationFrame(draw);
}
window.onunload = function() {
canvas = null;
ctx = null;
bounds = null;
selectedBox = null;
boxArray = null;
}
</script>
</body>
</html>
&#13;