javascript - Bagaimana cara menggambar persegi panjang seleksi dengan seret dan lepas di kanvas HTML?
Saya ingin menggambar persegi panjang seleksi (dengan menyeret dan melepaskan mouse, seperti di MS Paint) di kanvas HTML.
Cuplikan berikut bekerja, tetapi dengan dua kanvas yang berbeda.
Pertanyaan: Bagaimana melakukan ini pada satu kanvas, sedemikian rupa sehingga foto gambar dari kanvas tersebut dapat diubah nanti tanpa menghapus kotak seleksi?
Haruskah kita menggunakan 2 kanvas yang berbeda (jika iya, bagaimana menempatkan kanvas #2 tepat di atas yang pertama, tanpa menggunakan absolute positioning untuk keduanya)?
Atau apakah mungkin dengan cara yang lebih sederhana menggunakan satu kanvas saja? (dan sesuatu seperti ctx.globalCompositeOperation="source-over"; atau metode serupa)
var c1 = document.getElementById("c1"), c2 = document.getElementById("c2");
var ctx1 = c1.getContext("2d"), ctx2 = c2.getContext("2d");
ctx2.setLineDash([5, 5]);
var origin = null;
window.onload = () => { ctx1.drawImage(document.getElementById("img"), 0, 0); }
c1.onmousedown = e => { origin = {x: e.offsetX, y: e.offsetY}; };
window.onmouseup = e => { origin = null; };
c1.onmousemove = e => {
if (!!origin) {
ctx2.strokeStyle = "#ff0000";
ctx2.clearRect(0, 0, c2.width, c2.height);
ctx2.beginPath();
ctx2.rect(origin.x, origin.y, e.offsetX - origin.x, e.offsetY - origin.y);
ctx2.stroke();
}
};#img { display: none; }
#c1 { border: 1px solid green; }
#c2 { border: 1px solid blue; }<img id="img" src="https://i.imgur.com/okSIKkW.jpg">
<canvas id="c1" height="200" width="200"></canvas>
<canvas id="c2" height="200" width="200"></canvas>Jawaban #1
Solusi berikut menggunakan satu kanvas dan merender ulang saat pergerakan mouse.
https://jsfiddle.net/uhtdv0mj/3/
const c1 = document.getElementById("c1");
const ctx1 = c1.getContext("2d");
const drawImage = () => {
ctx1.drawImage(document.getElementById("img"), 0, 0);
};
const drawSelection = (e) => {
ctx1.strokeStyle = "#000";
ctx1.beginPath();
ctx1.rect(origin.x, origin.y, e.offsetX - origin.x, e.offsetY - origin.y);
ctx1.stroke();
};
const clear = () => {
ctx1.clearRect(0, 0, c1.width, c1.height);
};
const render = (e) => {
clear();
drawImage();
if (origin) drawSelection(e);
};
window.onload = drawImage;
let origin = null;
c1.onmousedown = e => { origin = {x: e.offsetX, y: e.offsetY}; };
c1.onmouseup = e => { origin = null; render(e); };
c1.onmousemove = render;
Jawaban #2
Mungkin ada solusi yang lebih baik dengan satu <canvas> saja dan beberapa lapisan (jika iya, silakan posting jawaban lain), tetapi akhirnya saya menggunakan metode yang mirip dengan elemen html5 - canvas - Beberapa lapisan dengan overlay dari 2 canvas:
var c1 = document.getElementById("c1"), c2 = document.getElementById("c2");
var ctx1 = c1.getContext("2d"), ctx2 = c2.getContext("2d");
ctx2.setLineDash([5, 5]);
var origin = null;
window.onload = () => { ctx1.drawImage(document.getElementById("img"), 0, 0); }
c2.onmousedown = e => { origin = {x: e.offsetX, y: e.offsetY}; };
window.onmouseup = e => { origin = null; };
c2.onmousemove = e => {
if (!!origin) {
ctx2.strokeStyle = "#ff0000";
ctx2.clearRect(0, 0, c2.width, c2.height);
ctx2.beginPath();
ctx2.rect(origin.x, origin.y, e.offsetX - origin.x, e.offsetY - origin.y);
ctx2.stroke();
}
};#img { display: none; }
#canvas-container { position: relative; }
canvas { position: absolute; left: 0; top: 0; }
#c1 { z-index: 0; }
#c2 { z-index: 1; }<img id="img" src="https://i.imgur.com/okSIKkW.jpg">
<div id="canvas-container">
<canvas id="c1" height="200" width="200"></canvas>
<canvas id="c2" height="200" width="200"></canvas>
</div>