2015-09-22 20 views
5

Ich habe ein HTML-Canvas-Element und habe einen Pinsel implementiert, der die Ereignisse mousedown, mousemove und mouseup des Canvas-Elements erfasst. Dies alles funktioniert gut für das Zeichnen auf der Leinwand. Ich glaube jedoch nicht, dass es mir gefällt, wie man eine Zeichnung nicht fortsetzen kann, wenn die Maus den Canvas-Strich hinterlässt. Es schneidet irgendwie ab. Es ist sehr unversöhnlich für die Person und meiner Meinung nach nicht sehr benutzerfreundlich.Wie zeichne ich außerhalb eines HTML-Canvas-Elements?

Wenn Sie Microsoft Paint öffnen und mit dem Pinsel oder der Ellipse oder ähnlichem beginnen, können Sie die Maus an einer beliebigen Stelle auf dem Bildschirm ziehen und die Zeichenfläche erneut eingeben, wenn Sie innerhalb der Zeichenfläche beginnen. Es erleichtert beispielsweise auch das Zeichnen von Viertelkreisen in Ecken, da Sie das Ellipsenwerkzeug außerhalb des Bildschirms ziehen können. Ich hoffe das macht Sinn.

Wie auch immer, ich fragte mich, ob es eine Möglichkeit gab, dies mit dem HTML5-Canvas zu implementieren, oder wie ich das umsetzen würde. Der Benutzer müsste nie etwas gesehen haben, das da drüben gezeichnet wäre; es wird meistens nur ein Merkmal für Benutzerfreundlichkeit sein.

Edit: Ein Problem mit vielen dieser Lösungen ist, wie mit Koordinaten umzugehen. Momentan befindet sich meine Leinwand in der Mitte des Bildschirms und die obere linke Ecke der Leinwand ist (0, 0) und unten rechts ist (500, 500). Die Übersetzungsarbeit der Koordinaten muss ebenfalls berücksichtigt werden.

Edit2: Ich habe herausgefunden, dass Sie die Canvas-Grenzen scheinbar gut abziehen können. Sie können beispielsweise negative Breiten, Höhen und Koordinaten angeben, und das Canvas-Element kann damit problemlos umgehen. Im Grunde wird die Lösung wahrscheinlich nur die mousemove und mouseup des Dokuments erfassen und nur die x und y übersetzen, um in der oberen linken Ecke des Canvas zu starten.

+3

Könnten Sie die Maus erfassen Ereignisse auf dem Fenster selbst und dann an die Leinwand delegieren? – zero298

+0

Vielleicht versuchen Sie ein Beispiel von dem, was Sie gerade haben. Es ist einfacher zu helfen, wenn wir nicht erst unser eigenes "kaputtes" Beispiel neu erstellen müssen. – duncanhall

+0

Vielleicht könnten Sie auch das Canvas-Element in voller Breite und Höhe des Fensters und der Zeichenfläche etwas kleiner in der Leinwand machen? –

Antwort

1

Hier ist ein äußerst grober erster Entwurf, wie Sie für Mausereignisse auf dem Fenster zu hören, anstatt die Leinwand kontinuierlich ziehen können:

var logger = document.getElementById("logger"), 
 
    mState = document.getElementById("mState"), 
 
    mX = document.getElementById("mX"), 
 
    mY = document.getElementById("mY"), 
 
    cX = document.getElementById("cX"), 
 
    cY = document.getElementById("cY"), 
 
    c = document.getElementById("canvas"), 
 
    ctx = c.getContext("2d"); 
 

 
var mouse = { 
 
    x: 0, 
 
    y: 0, 
 
    state: "" 
 
}; 
 

 
function printCanvasLocation() { 
 
    var b = c.getBoundingClientRect(); 
 
    cX.innerHTML = b.top; 
 
    cY.innerHTML = b.left; 
 
} 
 

 
function setState(mouseE, state) { 
 
    mouse.x = mouseE.clientX; 
 
    mouse.y = mouseE.clientY; 
 

 
    mX.innerHTML = mouseE.clientX; 
 
    mY.innerHTML = mouseE.clientY; 
 
    if (state) { 
 
    mState.innerHTML = state; 
 
    mouse.state = state; 
 
    } 
 
} 
 

 
window.addEventListener("mousedown", function(mouseE) { 
 
    setState(mouseE, "down"); 
 
}); 
 

 
window.addEventListener("mouseup", function(mouseE) { 
 
    setState(mouseE, "up"); 
 
}); 
 

 
window.addEventListener("mousemove", function(mouseE) { 
 
    var offset = c.getBoundingClientRect(); 
 

 
    var fix = { 
 
    x1: (mouse.x - offset.left), 
 
    y1: (mouse.y - offset.top), 
 
    x2: (mouseE.clientX - offset.left), 
 
    y2: (mouseE.clientY - offset.top) 
 
    }; 
 

 
    if (mouse.state === "down") { 
 
    ctx.moveTo(fix.x1, fix.y1); 
 
    ctx.lineTo(fix.x2, fix.y2); 
 
    ctx.strokeStyle = "#000"; 
 
    ctx.stroke(); 
 
    } 
 
    setState(mouseE); 
 
}); 
 

 
window.addEventListener("resize", function() { 
 
    printCanvasLocation(); 
 
}); 
 

 
printCanvasLocation();
  .center { 
 

 
       text-align: center; 
 

 
      } 
 

 
      canvas { 
 

 
       background-color: lightblue; 
 

 
      }
<main> 
 
    <div class="center"> 
 
    <canvas id="canvas" width="128" height="128">If you can see me, you should update your browser</canvas> 
 
    </div> 
 
    <div id="logger" role="log"> 
 
    <span>State: </span><span id="mState">Unknown</span> 
 
    <span>X: </span><span id="mX">Unknown</span> 
 
    <span>Y: </span><span id="mY">Unknown</span> 
 
    <span>Canvas X: </span><span id="cX">Unknown</span> 
 
    <span>Canvas Y: </span><span id="cY">Unknown</span> 
 
    </div> 
 
</main>

+0

Ihr 'Canvas X' und' Canvas Y' sind rückwärts aber ansonsten eine tolle Antwort! Ich denke, das wird es tun. –

2

Dies ist eine Möglichkeit, Sie Zeichnung halten können, wenn reenter die Leinwand:

  • eine globale Variable erstellen und festlegen, dass man auf true mousedown-
  • ein globales Ereignis für mouseup hinzufügen, so dass Sie, wenn jemand fangen tun, dass außerhalb der Leinwand, und wenn ja, globalen Variable auf false gesetzt, und das mouseup Bedarf natürlich des Canvas-Elements auch
  • auf mousemove- die gleiche Variable zu setzen, überprüfen Sie für globalen Variable um wahr zu sein, bevor zeichnen

Um "draussen" die Leinwand zu zeichnen, wie Viertelkreise in einer Ecke, würde ich alle Ereignisse auf die Dokumentebene als globalen Handler verschieben und das Canvas-Element beim Klicken abfangen und seine Clientkoordinaten mit den Dokumentkoordinaten berechnen lassen .