英文:
How to create multiple shapes on canvas on mouse drag and make them overlap?
问题
在一个canvas
元素内,我想要能够在鼠标拖动时绘制多个矩形(包括左键和右键)。到目前为止,我有以下代码:
class Waveform {
constructor(container_selector) {
this.render(container_selector);
}
render(container_selector) {
this.canvas = document.querySelector(container_selector);
this.canvas.width = 800;
this.canvas.height = 150;
this.canvas.style.border = '1px solid black';
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)';
this.canvas.addEventListener('mousedown', this.mouseDown);
this.canvas.addEventListener('mousemove', this.mouseMove);
this.canvas.addEventListener('mouseup', this.mouseUp);
}
mouseDown = e => {
this.drag = true;
this.rect = {};
this.rect.x = e.clientX - this.canvas.offsetLeft;
this.rect.y = 0;
this.rect.w = 1;
this.rect.h = this.canvas.height;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h
);
}
mouseMove = e => {
if (this.drag) {
this.ctx.clearRect(this.rect.x, this.rect.y, this.rect.w, this.rect.h);
this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h
);
}
}
mouseUp = e => {
this.drag = false;
}
}
let waveform = new Waveform('#waveform');
这段代码的问题在于,当我拖动一个矩形覆盖到已经存在的矩形上时,已经存在的部分会被擦除。我理解为什么会这样,但我希望矩形可以重叠,以便可以同时存在两个(或更多)。如何实现这一点?
如果要让矩形重叠而不是擦除已经存在的部分,你可以在绘制新矩形时不清除之前的矩形。修改mouseMove
方法如下:
mouseMove = e => {
if (this.drag) {
this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h
);
}
}
这样,新的矩形将在鼠标拖动时重叠在已存在的矩形上,而不会擦除之前的矩形。
英文:
Inside a canvas
element, I want to be able to draw multiple rectangles on mouse drag (both left and right). So far I have the following:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
class Waveform {
constructor(container_selector) {
this.render(container_selector)
}
render(container_selector) {
this.canvas = document.querySelector(container_selector)
this.canvas.width = 800
this.canvas.height = 150
this.canvas.style.border = '1px solid black'
this.ctx = this.canvas.getContext('2d')
this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)'
this.canvas.addEventListener('mousedown', this.mouseDown)
this.canvas.addEventListener('mousemove', this.mouseMove)
this.canvas.addEventListener('mouseup', this.mouseUp)
}
mouseDown = e => {
this.drag = true
this.rect = {}
this.rect.x = e.clientX - this.canvas.offsetLeft
this.rect.y = 0
this.rect.w = 1
this.rect.h = this.canvas.height
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
mouseMove = e => {
if (this.drag) {
this.ctx.clearRect(this.rect.x, this.rect.y, this.rect.w, this.rect.h)
this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
}
mouseUp = e => {
this.drag = false
}
}
let waveform = new Waveform('#waveform')
<!-- language: lang-html -->
<html>
<head>
</head>
<body>
<canvas id="waveform"></canvas>
</body>
</html>
<!-- end snippet -->
The issue with this code is that when I drag a rectangle over an already existing one, the portion of the existing one will be erased. I understand why it is so, but I want the rectangles overlap instead, so that two (or more) can exist at the same time. How to achieve this?
答案1
得分: 0
这里提供了一个解决方案,我删除了你的clearReact
行。
class Waveform {
constructor(container_selector, logger_selector) {
this.rects = []
this.logger = new Logger(logger_selector)
this.render(container_selector)
}
render(container_selector) {
this.canvas = document.querySelector(container_selector)
this.canvas.width = 800
this.canvas.height = 150
this.canvas.style.border = '1px solid black'
this.ctx = this.canvas.getContext('2d')
this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)'
this.canvas.addEventListener('mousedown', this.mouseDown)
this.canvas.addEventListener('mousemove', this.mouseMove)
this.canvas.addEventListener('mouseup', this.mouseUp)
}
mouseDown = e => {
this.drag = true
this.rect = {}
this.rect.x = e.clientX - this.canvas.offsetLeft
this.rect.y = 0
this.rect.w = 1
this.rect.h = this.canvas.height
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
mouseMove = e => {
if (this.drag) {
this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
}
mouseUp = e => {
this.drag = false
this.rects.push(this.rect)
this.logger.add(this.rect)
}
getRects() {
return this.rects
}
}
class Logger {
constructor(container_selector) {
this.list = document.querySelector(container_selector)
}
add(obj) {
let li = document.createElement("li")
li.textContent = JSON.stringify(obj)
this.list.appendChild(li)
}
}
let waveform = new Waveform('#waveform', '#list')
我建议你为每个插入到画布中的矩形更改填充颜色。
英文:
Here a solution where I removed your clearReact line.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
class Waveform {
constructor(container_selector, logger_selector) {
this.rects = []
this.logger = new Logger(logger_selector)
this.render(container_selector)
}
render(container_selector) {
this.canvas = document.querySelector(container_selector)
this.canvas.width = 800
this.canvas.height = 150
this.canvas.style.border = '1px solid black'
this.ctx = this.canvas.getContext('2d')
this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)'
this.canvas.addEventListener('mousedown', this.mouseDown)
this.canvas.addEventListener('mousemove', this.mouseMove)
this.canvas.addEventListener('mouseup', this.mouseUp)
}
mouseDown = e => {
this.drag = true
this.rect = {}
this.rect.x = e.clientX - this.canvas.offsetLeft
this.rect.y = 0
this.rect.w = 1
this.rect.h = this.canvas.height
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
mouseMove = e => {
if (this.drag) {
this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
this.ctx.fillRect(
this.rect.x,
this.rect.y,
this.rect.w,
this.rect.h,
)
}
}
mouseUp = e => {
this.drag = false
this.rects.push(this.rect)
this.logger.add(this.rect)
}
getRects() {
return this.rects
}
}
class Logger {
constructor(container_selector) {
this.list = document.querySelector(container_selector)
}
add(obj) {
let li = document.createElement("li")
li.textContent = JSON.stringify(obj)
this.list.appendChild(li)
}
}
let waveform = new Waveform('#waveform', '#list')
<!-- language: lang-html -->
<html>
<head>
</head>
<body>
<canvas id="waveform"></canvas>
</body>
<ul id="list">
</ul>
</html>
<!-- end snippet -->
I suggest you to change fill color for each rect you insert in your canvas.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论