How to create multiple shapes on canvas on mouse drag and make them overlap?

huangapple go评论99阅读模式
英文:

How to create multiple shapes on canvas on mouse drag and make them overlap?

问题

在一个canvas元素内,我想要能够在鼠标拖动时绘制多个矩形(包括左键和右键)。到目前为止,我有以下代码:

  1. class Waveform {
  2. constructor(container_selector) {
  3. this.render(container_selector);
  4. }
  5. render(container_selector) {
  6. this.canvas = document.querySelector(container_selector);
  7. this.canvas.width = 800;
  8. this.canvas.height = 150;
  9. this.canvas.style.border = '1px solid black';
  10. this.ctx = this.canvas.getContext('2d');
  11. this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)';
  12. this.canvas.addEventListener('mousedown', this.mouseDown);
  13. this.canvas.addEventListener('mousemove', this.mouseMove);
  14. this.canvas.addEventListener('mouseup', this.mouseUp);
  15. }
  16. mouseDown = e => {
  17. this.drag = true;
  18. this.rect = {};
  19. this.rect.x = e.clientX - this.canvas.offsetLeft;
  20. this.rect.y = 0;
  21. this.rect.w = 1;
  22. this.rect.h = this.canvas.height;
  23. this.ctx.fillRect(
  24. this.rect.x,
  25. this.rect.y,
  26. this.rect.w,
  27. this.rect.h
  28. );
  29. }
  30. mouseMove = e => {
  31. if (this.drag) {
  32. this.ctx.clearRect(this.rect.x, this.rect.y, this.rect.w, this.rect.h);
  33. this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
  34. this.ctx.fillRect(
  35. this.rect.x,
  36. this.rect.y,
  37. this.rect.w,
  38. this.rect.h
  39. );
  40. }
  41. }
  42. mouseUp = e => {
  43. this.drag = false;
  44. }
  45. }
  46. let waveform = new Waveform('#waveform');

这段代码的问题在于,当我拖动一个矩形覆盖到已经存在的矩形上时,已经存在的部分会被擦除。我理解为什么会这样,但我希望矩形可以重叠,以便可以同时存在两个(或更多)。如何实现这一点?

如果要让矩形重叠而不是擦除已经存在的部分,你可以在绘制新矩形时不清除之前的矩形。修改mouseMove方法如下:

  1. mouseMove = e => {
  2. if (this.drag) {
  3. this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
  4. this.ctx.fillRect(
  5. this.rect.x,
  6. this.rect.y,
  7. this.rect.w,
  8. this.rect.h
  9. );
  10. }
  11. }

这样,新的矩形将在鼠标拖动时重叠在已存在的矩形上,而不会擦除之前的矩形。

英文:

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

  1. class Waveform {
  2. constructor(container_selector) {
  3. this.render(container_selector)
  4. }
  5. render(container_selector) {
  6. this.canvas = document.querySelector(container_selector)
  7. this.canvas.width = 800
  8. this.canvas.height = 150
  9. this.canvas.style.border = &#39;1px solid black&#39;
  10. this.ctx = this.canvas.getContext(&#39;2d&#39;)
  11. this.ctx.fillStyle = &#39;rgba(200, 0, 0, 0.7)&#39;
  12. this.canvas.addEventListener(&#39;mousedown&#39;, this.mouseDown)
  13. this.canvas.addEventListener(&#39;mousemove&#39;, this.mouseMove)
  14. this.canvas.addEventListener(&#39;mouseup&#39;, this.mouseUp)
  15. }
  16. mouseDown = e =&gt; {
  17. this.drag = true
  18. this.rect = {}
  19. this.rect.x = e.clientX - this.canvas.offsetLeft
  20. this.rect.y = 0
  21. this.rect.w = 1
  22. this.rect.h = this.canvas.height
  23. this.ctx.fillRect(
  24. this.rect.x,
  25. this.rect.y,
  26. this.rect.w,
  27. this.rect.h,
  28. )
  29. }
  30. mouseMove = e =&gt; {
  31. if (this.drag) {
  32. this.ctx.clearRect(this.rect.x, this.rect.y, this.rect.w, this.rect.h)
  33. this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
  34. this.ctx.fillRect(
  35. this.rect.x,
  36. this.rect.y,
  37. this.rect.w,
  38. this.rect.h,
  39. )
  40. }
  41. }
  42. mouseUp = e =&gt; {
  43. this.drag = false
  44. }
  45. }
  46. let waveform = new Waveform(&#39;#waveform&#39;)

<!-- language: lang-html -->

  1. &lt;html&gt;
  2. &lt;head&gt;
  3. &lt;/head&gt;
  4. &lt;body&gt;
  5. &lt;canvas id=&quot;waveform&quot;&gt;&lt;/canvas&gt;
  6. &lt;/body&gt;
  7. &lt;/html&gt;

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

  1. class Waveform {
  2. constructor(container_selector, logger_selector) {
  3. this.rects = []
  4. this.logger = new Logger(logger_selector)
  5. this.render(container_selector)
  6. }
  7. render(container_selector) {
  8. this.canvas = document.querySelector(container_selector)
  9. this.canvas.width = 800
  10. this.canvas.height = 150
  11. this.canvas.style.border = '1px solid black'
  12. this.ctx = this.canvas.getContext('2d')
  13. this.ctx.fillStyle = 'rgba(200, 0, 0, 0.7)'
  14. this.canvas.addEventListener('mousedown', this.mouseDown)
  15. this.canvas.addEventListener('mousemove', this.mouseMove)
  16. this.canvas.addEventListener('mouseup', this.mouseUp)
  17. }
  18. mouseDown = e => {
  19. this.drag = true
  20. this.rect = {}
  21. this.rect.x = e.clientX - this.canvas.offsetLeft
  22. this.rect.y = 0
  23. this.rect.w = 1
  24. this.rect.h = this.canvas.height
  25. this.ctx.fillRect(
  26. this.rect.x,
  27. this.rect.y,
  28. this.rect.w,
  29. this.rect.h,
  30. )
  31. }
  32. mouseMove = e => {
  33. if (this.drag) {
  34. this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
  35. this.ctx.fillRect(
  36. this.rect.x,
  37. this.rect.y,
  38. this.rect.w,
  39. this.rect.h,
  40. )
  41. }
  42. }
  43. mouseUp = e => {
  44. this.drag = false
  45. this.rects.push(this.rect)
  46. this.logger.add(this.rect)
  47. }
  48. getRects() {
  49. return this.rects
  50. }
  51. }
  52. class Logger {
  53. constructor(container_selector) {
  54. this.list = document.querySelector(container_selector)
  55. }
  56. add(obj) {
  57. let li = document.createElement("li")
  58. li.textContent = JSON.stringify(obj)
  59. this.list.appendChild(li)
  60. }
  61. }
  62. 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 -->

  1. class Waveform {
  2. constructor(container_selector, logger_selector) {
  3. this.rects = []
  4. this.logger = new Logger(logger_selector)
  5. this.render(container_selector)
  6. }
  7. render(container_selector) {
  8. this.canvas = document.querySelector(container_selector)
  9. this.canvas.width = 800
  10. this.canvas.height = 150
  11. this.canvas.style.border = &#39;1px solid black&#39;
  12. this.ctx = this.canvas.getContext(&#39;2d&#39;)
  13. this.ctx.fillStyle = &#39;rgba(200, 0, 0, 0.7)&#39;
  14. this.canvas.addEventListener(&#39;mousedown&#39;, this.mouseDown)
  15. this.canvas.addEventListener(&#39;mousemove&#39;, this.mouseMove)
  16. this.canvas.addEventListener(&#39;mouseup&#39;, this.mouseUp)
  17. }
  18. mouseDown = e =&gt; {
  19. this.drag = true
  20. this.rect = {}
  21. this.rect.x = e.clientX - this.canvas.offsetLeft
  22. this.rect.y = 0
  23. this.rect.w = 1
  24. this.rect.h = this.canvas.height
  25. this.ctx.fillRect(
  26. this.rect.x,
  27. this.rect.y,
  28. this.rect.w,
  29. this.rect.h,
  30. )
  31. }
  32. mouseMove = e =&gt; {
  33. if (this.drag) {
  34. this.rect.w = (e.clientX - this.canvas.offsetLeft) - this.rect.x;
  35. this.ctx.fillRect(
  36. this.rect.x,
  37. this.rect.y,
  38. this.rect.w,
  39. this.rect.h,
  40. )
  41. }
  42. }
  43. mouseUp = e =&gt; {
  44. this.drag = false
  45. this.rects.push(this.rect)
  46. this.logger.add(this.rect)
  47. }
  48. getRects() {
  49. return this.rects
  50. }
  51. }
  52. class Logger {
  53. constructor(container_selector) {
  54. this.list = document.querySelector(container_selector)
  55. }
  56. add(obj) {
  57. let li = document.createElement(&quot;li&quot;)
  58. li.textContent = JSON.stringify(obj)
  59. this.list.appendChild(li)
  60. }
  61. }
  62. let waveform = new Waveform(&#39;#waveform&#39;, &#39;#list&#39;)

<!-- language: lang-html -->

  1. &lt;html&gt;
  2. &lt;head&gt;
  3. &lt;/head&gt;
  4. &lt;body&gt;
  5. &lt;canvas id=&quot;waveform&quot;&gt;&lt;/canvas&gt;
  6. &lt;/body&gt;
  7. &lt;ul id=&quot;list&quot;&gt;
  8. &lt;/ul&gt;
  9. &lt;/html&gt;

<!-- end snippet -->

I suggest you to change fill color for each rect you insert in your canvas.

huangapple
  • 本文由 发表于 2020年1月6日 23:48:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615054.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定