comment supprimer les points dans la toile html?
Tout d'abord, j'ai essayé toutes les questions et réponses liées à ce sujet. De plus, j'ai essayé des questions connexes et essayé de les résoudre, mais sans succès. Veuillez donc lire attentivement ma question.
Problème: supprimez uniquement le point rouge sans toile transparente.
Je souhaite supprimer uniquement les points rouges et non la suppression ou le rechargement de la toile complète.
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>
Réponses
Depuis que vous avez dessiné le cercle rouge ( x, la yposition) ( 100px, 100px) avec un diamètre 6px, la surface qu'il occupe est:
x : 100 - (6 / 2)
y : 100 - (6 / 2)
width : 6
height : 6
Vous pouvez effacer une section du canevas avec la clearRectméthode.
context.clearRect(97, 97, 6, 6);
Si votre canevas a un arrière-plan, vous devrez soit effacer tout le canevas et tout redessiner à l'exception du point rouge, soit appeler fillRect… en supposant qu'il context.fillStylesoit défini sur la couleur d'arrière-plan.
context.fillRect(97, 97, 6, 6);
Vous devrez en quelque sorte savoir où le point rouge a été peint (et quelle taille il était), avant de le peindre.
Edit: voir mon exemple POO en suivant la démo ci-dessous!
Démo
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 à la rescousse!
Une meilleure approche serait de connaître le point rouge en dehors du rendu de la toile. Vous pouvez envelopper le contexte du canevas dans une classe qui gère les calques et les dessinables.
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>
Comme la réponse existante l'a démontré l'adage OO ...
- "J'ai demandé une banane, mais j'ai trouvé un gorille dans la jungle avec une banane." ,
J'ai ajouté cette réponse pour démontrer une approche OO unique JavaScript plus concise.
La raison: la bataille contre la complexité.
La complexité est l'ennemi numéro un des codeurs, ajoutant des couches d'abstraction inutiles, dupliquant les comportements existants, anticipant les besoins non définis, tout cela ajoute de la complexité.
Je pensais que cela n'avait pas d'importance s'il n'y avait que moins de 100 lignes, pour les grands projets, le code supplémentaire s'ajoute rapidement et chaque ligne est une source supplémentaire de bogues.
JavaScript fournit un modèle OO simple et très flexible, avec un accent sur le polymorphisme via la construction et l'extension d'objets ad hoc. Il dispose également d'un ensemble important de raccourcis de codage qui contribuent grandement à réduire le nombre de lignes nécessaires pour implémenter les comportements
Le résultat est deux fois moins de code avec presque les mêmes fonctionnalités,
Exemple
- Utilise le
Arrayprototype pour implémenter des couches circleHéritedrawableen passant un type au constructeur.- Supprime par
color, plutôt que par index ou référence
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>
(Et j'ajouterai qu'il n'y a rien de mal avec le code de M. Polywhirl )