简体   繁体   English

如何删除画布html中的点?

[英]how remove dots in canvas html?

Firstly, I tried all the questions & answers related to this topic.首先,我尝试了与此主题相关的所有问题和答案。 Additionally and I tried related questions and try to solve it but no success.此外,我尝试了相关问题并尝试解决它,但没有成功。 So please read my question thoroughly.所以请仔细阅读我的问题。

Problem: Remove Only Red Dot without a clear canvas.问题:在没有清晰画布的情况下仅删除点。

I want to Remove only Red Dotes not Full Canvas Remove or Reload .我只想删除 Red Dotes 而不是 Full Canvas Remove 或 Reload 。

 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>

Since you drew the red circle at ( x , y ) position ( 100px , 100px ) with a diameter of 6px , the area it takes up is:由于您在 ( x , y ) 位置 ( 100px , 100px ) 处6px了直径为6px的红色圆圈,因此它占用的区域为:

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

You can clear a section of the canvas with the clearRect method.您可以使用clearRect方法清除画布的clearRect

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

If your canvas has a background, you will either need to clear the entire canvas and redraw everything except for the red dot, or you could call fillRect … assuming that context.fillStyle is set to the background color.如果您的画布有背景,您将需要清除整个画布并重绘除红点之外的所有内容,或者您​​可以调用fillRect ...假设context.fillStyle设置为背景颜色。

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

You would somehow have to know where the red dot was painted (and what size it was), prior to painting it.在绘制之前,您必须以某种方式知道红点的绘制位置(以及它的大小)。

Edit: See my OOP example following the demo below!编辑:在下面的演示之后查看我的 OOP 示例!


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 to the rescue! OOP 来救援!

A better approach would be knowing about the red dot outside the canvas rendering.更好的方法是了解画布渲染外的红点。 You could wrap the canvas context inside a class that manages layers and 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>

As the existing answer has demonstrated the OO adage...由于现有答案已经证明了 OO 格言......

  • "I asked for a banana, but got a gorilla in the jungle holding a banana." “我要了一根香蕉,但在丛林中得到了一只拿着香蕉的大猩猩。” , ,

I have added this answer to demonstrate a more concise JavaScript unique OO approach.我添加了这个答案来演示更简洁的 JavaScript 独特的 OO 方法。

The reason: The battle against complexity.原因:与复杂性的斗争。

Complexity is a coders number one enemy, adding unneeded layers of abstraction, duplicating existing behaviours, anticipating undefined needs, all add complexity.复杂性是编码人员的头号敌人,添加不需要的抽象层、复制现有行为、预测未定义的需求,所有这些都会增加复杂性。

Thought it may not matter if there is only less than 100 lines, for large projects the additional code adds up quickly, and every line is an additional source of bugs.认为只有不到 100 行可能没有关系,对于大型项目,额外的代码加起来很快,每一行都是错误的额外来源。

JavaScript provides a simple and very flexible OO model, with an emphasis on polymorphism via ad hoc object construction and extension. JavaScript 提供了一个简单且非常灵活的 OO 模型,强调通过临时对象构造和扩展实现的多态性。 It also has a substantial set of coding shortcuts that go a long way in reducing the number of lines need to implement behaviours它还具有大量的编码快捷方式,可以大大减少实现行为所需的行数

The result is half as much code with almost the same functionality,结果是功能几乎相同的代码减少了一半,

Example例子

  • Uses the Array prototype to implement layers使用Array原型来实现层
  • circle Inherits drawable by passing a type to constructor. circle通过将类型传递给构造函数来继承drawable
  • Removes by color , rather than index or referencecolor删除,而不是索引或引用

 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>

(And I will add that there is nothing wrong with Mr. Polywhirl's code) (我要补充一点, Polywhirl 先生的代码没有任何问题)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM