2015-07-18 8 views
5

Ich habe eine Leinwand und ich möchte den Benutzer-Cursor ändern (wie Stil Cursor Zeiger Fadenkreuz verschieben etc.). Ist es möglich, den Benutzer-Cursor während eines bestimmten Bereichs meiner Leinwand zu ändern, ohne "Hit-Boxen" mit Stil des Cursors auf diesen Hit-Boxen einzuführen?Ändern Sie den Cursor in Abhängigkeit von Abschnitt der Leinwand

+2

Die c Das anvas-Element empfängt nur Mausereignisse relativ zu seinem Ganzen. Um Cursor auf Unterabschnitten der Zeichenfläche zu ändern, müssen Sie in der Tat einen Treffer-Test durchführen, indem Sie die Mausposition relativ zur Zeichenfläche verwenden. – markE

+0

Danke @MarkE, so Hit-Tests zu tun die einzige Möglichkeit ist, andere DOM-Elemente auf der Leinwand überlagert? – Noitidart

+2

Ja, das Testen von Treffern ist die einzige Möglichkeit zu überprüfen, ob sich die Maus über einer auf der Leinwand gezeichneten Form befindet. Sie müssen jedoch keine DOM-Elemente hinzufügen, die als Hover-Ziele fungieren. Ich habe eine Antwort geschrieben, in der erläutert wird, wie die Methode 'context.isPointInPath' verwendet wird, um einzelne Formen im Schwebezustand zu testen. – markE

Antwort

10

Auf der Zeichenfläche gezeichnete Formen erhalten keine Mausereignisse, daher können einzelne Formen keine Hover-Ereignisse empfangen.

Eine Form auf der Leinwand gezeichnet dargestellt werden kann als ein Satz von Pfad

Befehle
A Shape == A set of path commands. 

// Example: A set of path commands drawing a triangle 
context.beginPath(); 
context.moveTo(50,50); 
context.lineTo(75,100); 
context.lineTo(25,100); 
context.closePath(); 

Cursor zu ändern, wenn sie über einzelne Formen schweben Sie mit der Maus gegen jede Form getroffen Tests tun müssen (im Vergleich zu jedem Pfad).

Sie können eine Form (einen Pfad) mit der Methode isPointInPath testen.

isPointInPath Sie verwenden müssen für eine Form den Pfad Befehl re-issue (aber keine Notwendigkeit, Schlaganfall oder füllen) und dann isPointInPath mit der aktuellen Maus rufen Koordinaten:

// first re-issue the path commands for the shape being tested 
// and then test if the mouse is inside the shape using isPointInPath 
if(context.isPointInPath(mouseX,mouseY)){ 
    alert('The mouse is inside this shape'); 
} 

Hier ist Beispielcode und eine Demo:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 
function reOffset(){ 
 
    var BB=canvas.getBoundingClientRect(); 
 
    offsetX=BB.left; 
 
    offsetY=BB.top;   
 
} 
 
var offsetX,offsetY; 
 
reOffset(); 
 
window.onscroll=function(e){ reOffset(); } 
 
window.onresize=function(e){ reOffset(); } 
 

 
var isDown=false; 
 
var startX,startY; 
 

 
var cursors=['default','w-resize','n-resize']; 
 
var currentCursor=0; 
 

 
var shapes=[]; 
 
shapes.push({ 
 
    points:[{x:20,y:50},{x:100,y:10},{x:180,y:50},{x:100,y:90}], 
 
    cursor:1, 
 
}); 
 
shapes.push({ 
 
    points:[{x:200,y:50},{x:250,y:150},{x:200,y:250},{x:150,y:150}], 
 
    cursor:2, 
 
}); 
 

 
for(var i=0;i<shapes.length;i++){ 
 
    var s=shapes[i]; 
 
    definePath(s.points); 
 
    ctx.stroke(); 
 
} 
 

 

 
$("#canvas").mousemove(function(e){handleMouseMove(e);}); 
 

 

 
function definePath(p){ 
 
    ctx.beginPath(); 
 
    ctx.moveTo(p[0].x,p[0].y); 
 
    for(var i=1;i<p.length;i++){ 
 
    ctx.lineTo(p[i].x,p[i].y); 
 
    } 
 
    ctx.closePath(); 
 
} 
 

 
function handleMouseMove(e){ 
 
    // tell the browser we're handling this event 
 
    e.preventDefault(); 
 
    e.stopPropagation(); 
 

 
    mouseX=parseInt(e.clientX-offsetX); 
 
    mouseY=parseInt(e.clientY-offsetY); 
 

 
    // Put your mousemove stuff here 
 
    var newCursor; 
 
    for(var i=0;i<shapes.length;i++){ 
 
    var s=shapes[i]; 
 
    definePath(s.points); 
 
    if(ctx.isPointInPath(mouseX,mouseY)){ 
 
     newCursor=s.cursor; 
 
     break; 
 
    } 
 
    } 
 
    if(!newCursor){ 
 
    if(currentCursor>0){ 
 
     currentCursor=0; 
 
     canvas.style.cursor=cursors[currentCursor];    
 
    } 
 
    }else if(!newCursor==currentCursor){ 
 
    currentCursor=newCursor; 
 
    canvas.style.cursor=cursors[currentCursor];    
 
    } 
 
}
body{ background-color: ivory; } 
 
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
<h4>Move the mouse over the shapes and the cursor will change.</h4> 
 
<canvas id="canvas" width=300 height=300></canvas>

+0

Vielen Dank für Ihre tolle Antwort! Was ich mache, ist ein Firefox-Addon zu erstellen, das einen Screenshot von allen Monitoren erstellt und sie dann auf Leinwände pro Monitor zeichnet, jetzt im Aufbau eines Editors: https://www.youtube.com/watch?v=tzS3YgXhtLU – Noitidart

+1

Oh, das ist brillant!! Dieser Test in Punkt Sache mit Mauszeiger macht Cursor Änderung so absolut genau! Und keine DOM Elemente überlagert !! Dies ist eine großartige Antwort, vielen Dank dafür !!! Es hilft mir eine Tonne! – Noitidart

+2

Das Ganze kam mir gerade wieder recht! Ich habe ein Feature hinzugefügt, um Linien zu zeichnen, die nur ein Strich sind. Also gibt es äquivalent zu 'isPointInPath', aber es ist' isPointInStroke', absolut großartig, nochmals danke @markE! – Noitidart

Verwandte Themen