como remover pontos em html de tela?

Sep 11 2020

Em primeiro lugar, tentei todas as perguntas e respostas relacionadas a este tópico. Além disso, tentei perguntas relacionadas e tentei resolvê-las, mas sem sucesso. Então, por favor, leia minha pergunta cuidadosamente.

Problema: Remova apenas o ponto vermelho sem uma tela transparente.

Desejo remover apenas pontos vermelhos, não remover ou recarregar totalmente a tela.

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
    
context.beginPath();
context.arc(100, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "red";
context.fill();

context.beginPath();
context.arc(36, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "Orange";
context.fill();

context.beginPath();
context.arc(123, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "Green";
context.fill();

function removeRedDot(){
 // remove code
 alert('Remove Red Dot');
}
#canvas{
border:1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h4>Approach the circle with the mouse</h4> <button onclick="removeRedDot()"> Red Remove Dot</button>
<canvas id="canvas" width=300 height=200></canvas>

Respostas

3 Mr.Polywhirl Sep 11 2020 at 18:37

Desde que você desenhou o círculo vermelho em ( x, y) posição ( 100px, 100px) com um diâmetro de 6px, a área que ele ocupa é:

x      : 100 - (6 / 2)
y      : 100 - (6 / 2)
width  : 6
height : 6

Você pode limpar uma seção da tela com o clearRectmétodo.

context.clearRect(97, 97, 6, 6);

Se sua tela tiver um fundo, você precisará limpar toda a tela e redesenhar tudo, exceto o ponto vermelho, ou você pode chamar fillRect... presumindo que context.fillStylea cor de fundo esteja definida.

context.fillRect(97, 97, 6, 6);

De alguma forma, você teria que saber onde o ponto vermelho foi pintado (e qual o tamanho dele), antes de pintá-lo.

Edit: Veja meu exemplo OOP seguindo a demonstração abaixo!


Demo

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

context.beginPath();
context.arc(100, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "red";
context.fill();

context.beginPath();
context.arc(36, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "Orange";
context.fill();

context.beginPath();
context.arc(123, 100, 3, 0, Math.PI * 2, true); // Outer circle
context.lineWidth = 0;
context.fillStyle = "Green";
context.fill();

function removeRedDot() {
  context.clearRect(97, 97, 6, 6);
  alert('Removed Red Dot');
}
#canvas {
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h4>Approach the circle with the mouse</h4> <button onclick="removeRedDot()"> Red Remove Dot</button>
<canvas id="canvas" width=300 height=200></canvas>


OOP para o resgate!

Uma abordagem melhor seria saber sobre o ponto vermelho fora da renderização da tela. Você pode envolver o contexto da tela dentro de uma classe que gerencia camadas e drawables.

const ctx = document.getElementById('canvas').getContext('2d');

const main = () => {
  const canvas = new Canvas(ctx);
  const layer = canvas.addLayer();
  const circles = [
    new Circle({ x: 50, y: 50 }, 3, 'red'),
    new Circle({ x: 100, y: 100 }, 6, 'green'),
    new Circle({ x: 150, y: 150 }, 12, 'blue')
  ];
  layer.add(...circles);
  canvas.render();
  
  // After 2 second, remove the red dot and re-render.
  setTimeout(() => {
    alert('Removing "red" circle, and adding a "cyan" circle...');
    layer.remove(circles[0]);
    layer.add(new Circle({ x: 150, y: 50 }, 8, 'cyan'));
    canvas.render();
  }, 2000);
};

class Drawable {
  constructor(origin) {
    this.origin = origin;
  }
  draw(ctx) { }
}

class Layer {
  constructor(name) {
    this.name = name;
    this.drawables = [];
  }
  add(...drawables) {
    drawables.forEach(drawable => this.drawables.push(drawable));
  }
  remove(drawableOrIndex) {
    if (isNaN(drawableOrIndex)) {
      drawableOrIndex = this.drawables.indexOf(drawableOrIndex);
    }
    if (drawableOrIndex > -1) {
      this.drawables.splice(drawableOrIndex, 1);
    }
  }
  render(ctx) {
    this.drawables.forEach(drawable => drawable.render(ctx));
  }
}

class Canvas {
  constructor(ctx) {
    this.ctx = ctx;
    this.layers = [];
  }
  addLayer(name) {
    const newLayer = new Layer(name || 'layer-' + this.layers.length);
    this.layers.push(newLayer);
    return newLayer;
  }
  getLayer(nameOrIndex) {
    return isNaN(nameOrIndex)
      ? this.layers.find(layer => layer.name === nameOrIndex)
      : this.layers[nameOrIndex];
  }
  render() {
    const { width, height } = this.ctx.canvas;
    this.ctx.clearRect(0, 0, width, height);
    this.layers.forEach(layer => layer.render(this.ctx));
  }
}

class Circle extends Drawable {
  constructor(origin, radius, color) {
    super(origin);
    this.radius = radius;
    this.color = color;
  }
  render(ctx) {
    const { x, y } = this.origin;
    const diameter = this.radius * 2;
    ctx.save();
    ctx.beginPath();
    ctx.arc(x, y, this.radius, 0, Math.PI * 2, true);
    ctx.lineWidth = 0;
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.restore();
  }
}

main();
#canvas {
  border: 1px solid black;
}
<canvas id="canvas" width=300 height=200></canvas>

Blindman67 Sep 11 2020 at 22:13

Como a resposta existente demonstrou o ditado OO ...

  • "Pedi uma banana, mas encontrei um gorila na selva segurando uma banana." ,

Eu adicionei esta resposta para demonstrar uma abordagem OO exclusiva de JavaScript mais concisa.

O motivo: a batalha contra a complexidade.

A complexidade é o inimigo número um dos codificadores, adicionando camadas desnecessárias de abstração, duplicando comportamentos existentes, antecipando necessidades indefinidas, tudo isso adiciona complexidade.

Embora não importe se houver apenas menos de 100 linhas, para grandes projetos o código adicional aumenta rapidamente e cada linha é uma fonte adicional de bugs.

JavaScript fornece um modelo OO simples e muito flexível, com ênfase no polimorfismo por meio da construção e extensão de objetos ad hoc. Ele também tem um conjunto substancial de atalhos de codificação que ajudam muito a reduzir o número de linhas necessárias para implementar comportamentos

O resultado é a metade do código com quase a mesma funcionalidade,

Exemplo

  • Usa o Arrayprotótipo para implementar camadas
  • circleHerda drawablepassando um tipo para o construtor.
  • Remove por color, em vez de índice ou referência

const ctx = canvas.getContext("2d");
const P2 = (x = 0, y = 0) => ({x,y});
const Drawable = (pos, color, size = 10, type = Circle) => ({pos, size, color, ...type});
const Circle = {
    draw(ctx) {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.pos.x, this.pos.y, this.size, 0, Math.PI * 2);
        ctx.fill();
    }
};
const drawables = Object.assign([], {
       draw(ctx) { for (const d of this) { d.draw(ctx) } },
       remove(color) {
           const idx = this.findIndex(d => d.color === color);
           return (idx > -1 && (this.splice(idx, 1)[0])) || undefined;
       },
    }
);
drawables.push(...[...document.querySelectorAll("#buttons button")].map((but, idx)=>
    Drawable(P2(100 + idx * 100, 50), but.dataset.color)
));
drawables.draw(ctx);   
buttons.addEventListener("click", e => {
    if (drawables.remove(e.target.dataset.color)) {
       ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
       drawables.draw(ctx);
    }
});
<canvas id="canvas" width="400" height="100"></canvas>
<div id="buttons">
    <button data-color="red">Remove Red</button>
    <button data-color="green">Remove Green</button>
    <button data-color="blue">Remove Blue</button>
</div>

(E vou acrescentar que não há nada de errado com o código do Sr. Polywhirl )