วิธีลบจุดในผ้าใบ html
ประการแรกฉันลองใช้คำถามและคำตอบทั้งหมดที่เกี่ยวข้องกับหัวข้อนี้ นอกจากนี้และฉันได้ลองใช้คำถามที่เกี่ยวข้องและพยายามแก้ไข แต่ไม่ประสบความสำเร็จ ดังนั้นโปรดอ่านคำถามของฉันอย่างละเอียด
ปัญหา:ลบเฉพาะจุดสีแดงโดยไม่มีผ้าใบที่ชัดเจน
ฉันต้องการลบเฉพาะจุดสีแดงที่ไม่ใช่การลบแบบเต็มผ้าใบหรือโหลดซ้ำ
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>
คำตอบ
เนื่องจากคุณวาดวงกลมสีแดงที่ ( x, y) ตำแหน่ง ( 100px, 100px) ด้วยเส้นผ่านศูนย์กลาง6pxพื้นที่ที่จะขึ้นคือ:
x : 100 - (6 / 2)
y : 100 - (6 / 2)
width : 6
height : 6
คุณสามารถล้างส่วนของผืนผ้าใบด้วยclearRectวิธีการ
context.clearRect(97, 97, 6, 6);
หากผืนผ้าใบของคุณมีพื้นหลังคุณจะต้องล้างผืนผ้าใบทั้งหมดและวาดทุกอย่างใหม่ยกเว้นจุดสีแดงหรือคุณอาจเรียกfillRectว่า ... สมมติว่าcontext.fillStyleตั้งค่าเป็นสีพื้นหลัง
context.fillRect(97, 97, 6, 6);
คุณจะต้องรู้ว่าจุดสีแดงถูกวาดไว้ที่ไหน (และขนาดเท่าไหร่) ก่อนที่จะทาสี
แก้ไข:ดูตัวอย่าง OOP ของฉันตามการสาธิตด้านล่าง!
การสาธิต
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 เพื่อช่วยเหลือ!
แนวทางที่ดีกว่าคือการรู้เกี่ยวกับจุดสีแดงนอกการแสดงผลแคนวาส คุณสามารถรวมบริบทผ้าใบไว้ในคลาสที่จัดการเลเยอร์และสิ่งที่วาดได้
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>
ดังที่คำตอบที่มีอยู่ได้แสดงให้เห็นถึงคำพูด OO ...
- "ฉันขอกล้วย แต่ได้กอริลลาในป่าถือกล้วย" ,
ฉันได้เพิ่มคำตอบนี้เพื่อแสดงให้เห็นถึงแนวทาง OO เฉพาะของ JavaScript ที่กระชับยิ่งขึ้น
เหตุผล: การต่อสู้กับความซับซ้อน
ความซับซ้อนเป็นศัตรูหมายเลขหนึ่งของนักเขียนโค้ดการเพิ่มชั้นนามธรรมที่ไม่จำเป็นการทำซ้ำพฤติกรรมที่มีอยู่การคาดการณ์ความต้องการที่ไม่ได้กำหนดไว้ล้วนเพิ่มความซับซ้อน
คิดว่าอาจไม่สำคัญว่าจะมีเพียงน้อยกว่า 100 บรรทัดสำหรับโครงการขนาดใหญ่รหัสเพิ่มเติมจะเพิ่มขึ้นอย่างรวดเร็วและทุกบรรทัดเป็นแหล่งที่มาของข้อบกพร่องเพิ่มเติม
JavaScript ให้โมเดล OO ที่เรียบง่ายและยืดหยุ่นมากโดยเน้นที่ความหลากหลายผ่านการสร้างและขยายวัตถุเฉพาะกิจ นอกจากนี้ยังมีชุดทางลัดการเข้ารหัสจำนวนมากที่ช่วยลดจำนวนบรรทัดที่ต้องใช้ในการปรับพฤติกรรม
ผลลัพธ์คือโค้ดครึ่งหนึ่งที่มีฟังก์ชันการทำงานเกือบเหมือนกัน
ตัวอย่าง
- ใช้
Arrayต้นแบบเพื่อใช้งานเลเยอร์ circleสืบทอดdrawableโดยการส่งผ่านชนิดไปยังตัวสร้าง- ลบโดย
colorแทนที่จะเป็นดัชนีหรือการอ้างอิง
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>
(และฉันจะเพิ่มว่าไม่มีอะไรผิดปกติกับรหัสของ Mr.Polywhirl )