Próbuję narysować prostokąt, tak jak robisz to w programie Paint. Ale obecnie, kiedy próbuję naszkicować prostokąt, tak wygląda moje płótno - podwójne rysunki, niechlujne prostokąty.

Tak wygląda cały mój kod:

(usunięty kod)

Jak narysować prostokąt, który wygląda tak: jak jeden prostokąt?

-2
intuitiveprogramming 4 kwiecień 2020, 00:57

3 odpowiedzi

Najlepsza odpowiedź

Przede wszystkim myślę, że jest to bardziej jasne, jeśli przechowujesz współrzędne w oddzielnych zmiennych zamiast w tablicy (startX, startY, lastX, lastY).

Powinieneś także odjąć pozycję płótna od pozycji myszy, aby uzyskać współrzędne wewnątrz płótna, teraz to trochę działa, ponieważ płótno znajduje się na górze strony.

Widzę, że chcesz zachować starą zawartość, użyłem płótna do przechowywania poprzednio narysowanej treści, a następnie przed narysowaniem bieżącego prostokąta musisz przerysować starą zawartość (używając ctx.drawImage).

Powinieneś dodać 0,5 do współrzędnych, aby linie nie były rozmazane, dzieje się tak tylko wtedy, gdy narysujesz linię o nieparzystej szerokości (1, 3, 5). Dzieje się tak, ponieważ jeśli spróbujesz narysować linię 1px na, powiedzmy, współrzędnej x = 1, musisz narysować pół piksela po obu stronach (0,5 do 1,5), więc wygląda na rozmazany.

Ale jeśli narysujesz to na powiedzmy x = 0,5, narysujesz linię od 0 do 1, czyli dokładnie jeden piksel.

var isDown = false;
var startX, startY;
var lastX, lastY;

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var canvasRect = canvas.getBoundingClientRect();

var backBuffer = canvas.cloneNode(true);
var backBufferCtx = backBuffer.getContext('2d');

canvas.addEventListener('mousedown', function down() {
    startX = event.clientX - canvasRect.left;
    startY = event.clientY - canvasRect.top;
    isDown = true;
});

canvas.addEventListener('mouseup', function up() {
    isDown = false;

    // Draw Current Canvas Content
    updateCanvas();

    // Save current content
    backBufferCtx.clearRect(0, 0, backBuffer.width, backBuffer.height);
    backBufferCtx.drawImage(canvas, 0, 0);
});

canvas.addEventListener('mousemove', function move() {
    if (! isDown) return;

    lastX = event.clientX - canvasRect.left;
    lastY = event.clientY - canvasRect.top;
    updateCanvas();
});

function updateCanvas() {
    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Draw Current Canvas Content
    ctx.drawImage(backBuffer, 0, 0);

    // Draw New Rectangle
    ctx.beginPath();
    // add 0.5 so the line do not get blurry
    ctx.rect(startX + 0.5, startY + 0.5, lastX - startX, lastY - startY);
    ctx.stroke();
}
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000; margin-top: 100px"></canvas>
0
sney2002 3 kwiecień 2020, 23:29

Kontekst płótna to bardzo potężna rzecz, sugeruję sprawdzenie wszystkich jego właściwości, metod na https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D

W szczególności dla twojego przypadku użycia: kontekst dostarcza metody bezpośredniego odczytu i zapisu danych kanwy, getImageData() - putImageData() jest do tego parą metod. Używając ich, możesz przechowywać wszystko, co zawiera płótno, gdy użytkownik zacznie rysować nowy prostokąt, i przywrócić go, gdy rozmiar bieżącego prostokąta zostanie zmieniony. Przechowywane dane mogą nawet oferować jednoetapową funkcję „Cofnij” jako produkt uboczny:

var cnv=document.getElementById("cnv"),
    ctx=cnv.getContext("2d"),
    col=document.getElementById("color"),
    ubtn=document.getElementById("undo"),
    copy,
    pick=false;

function mdown(event){
  copy=ctx.getImageData(0,0,cnv.width,cnv.height);
  pick={
    x:event.offsetX,
    y:event.offsetY
  };
}

function mup(event){
  pick=false;
  ubtn.disabled=false;
}

function mmove(event){
  if(pick){
    ctx.putImageData(copy,0,0);
    ctx.strokeStyle=col.value;
    ctx.lineWidth=2;
    ctx.strokeRect(pick.x,pick.y,event.offsetX-pick.x,event.offsetY-pick.y);
  }
}

function undo(){
  ctx.putImageData(copy,0,0);
  ubtn.disabled=true;
}
<input type="color" id="color"><button id="undo" disabled onclick="undo()">Undo</button><br>
<canvas id="cnv" width="300" height="140" style="border:1px solid black;cursor:crosshair" onmousedown="mdown(event)" onmousemove="mmove(event)" onmouseup="mup(event)"></canvas>
0
tevemadar 4 kwiecień 2020, 10:39

Kod, który wysyłasz, zawiera tablice:
ctx.rect(x[x1],y[y1]
ale przypuszczam, że rysujesz więcej niż tylko prostokąty ...

Oto próbka:

ctx = document.getElementById('c').getContext('2d');
ctx.lineWidth = 2;
x = [5, 30, 90]
y = [5, 50, 30]

for (i = 0; i < x.length; i++) {
  ctx.rect(x[i], y[i], 50, 20)
}
ctx.stroke();
<canvas height="100" width="300" id="c">

Tylko prostokąty nic więcej, żadnych podwójnych rysunków ani bałaganu, podany kod nie powinien powodować żadnych problemów, takich jak to, co pokazujesz na obrazku.


Oto aktualizacja oparta na Twoim nowym kodzie ...

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");
ctx.lineWidth = 2;

var x = 0;
var y = 0;
draw = false;

function down() {
  x = event.clientX;
  y = event.clientY;
  draw = true;
}

function move() {
  if (draw) {
    var a = event.clientX;
    var b = event.clientY;

    ctx.clearRect(0, 0, canvas.width, canvas.height)
    addCircles()
    ctx.beginPath()
    ctx.rect(x, y, a - x, b - y);
    ctx.stroke();
  }
}

function up() {
  draw = false
}


function addCircles() {
  ctx.beginPath()
  ctx.fillStyle = '#F00';
  ctx.arc(50, 50, 30, 0, Math.PI * 2)
  ctx.fill();
  ctx.beginPath()
  ctx.fillStyle = '#0F0';
  ctx.arc(100, 100, 30, 0, Math.PI * 2)
  ctx.fill();
  ctx.beginPath()
  ctx.fillStyle = '#00F';
  ctx.arc(200, 80, 30, 0, Math.PI * 2)
  ctx.fill();
}


addCircles()
<canvas id="myCanvas" width="300" height="160" style="border:1px solid #000000;" onmousedown="down()" onmousemove="move()" onmouseup="up()"> </canvas>

Miałeś bałagan zmiennych, usunąłem wszystko, co nie było absolutnie wymagane do narysowania prostokąta, możesz to skomplikować później i tak lubisz rysować wiele obiektów, ale zalecałbym częste testowanie kodu, małe przyrostowe zmiany, upewniając się, że robi to, co chcesz.

0
Helder Sepulveda 3 kwiecień 2020, 23:35