2016-07-21 11 views
0

Ich versuche, einen Punkt um den äußeren Umfang eines großen Kreises mit der Maus zu ziehen und diesen Punkt so erscheinen zu lassen, dass er eine dicke Linie um den äußeren Umfang hinter sich aufschreibt. Ich kann alles zum Laufen bringen, außer dass ich die äußere Linie hinter dem Punkt ritze. Ich habe viele Ideen recherchiert und viele eigene ausprobiert, aber die Linie produziert immer noch "spotted" Ergebnisse. Hier ist ein Bild, um zu zeigen, was ich versuche. MounseDrag Scribed Line Vielen Dank, dass Sie sich die Zeit genommen haben, meine Frage zu lesen. :-)Ritzen einer Zickzacklinie in Canvas

<script type="text/javascript"> 
    var canvas1 = document.getElementById("canvas1"), 
     canvas2 = document.getElementById("canvas2"), 
     c1 = canvas1.getContext("2d"), 
     c2 = canvas2.getContext("2d"), 
     dot = 7, 
     started = false, 
     width = 350, 
     height = 350, 
     radians = 0, 
     cRad = 165, // Circle Radius 
     cord = {mX:0, mY:0, csX:0, snY:0, x:0, y:0}, 
     init = function(){ 
     cord.mX = 0; 
     cord.mY = 0; 
     cord.csX = width /2 + cRad; 
     cord.snY = height /2; 
     cord.x = width /2; 
     cord.y = height /2; 
     }; 

    init(); 
    canvas1.width = width; 
    canvas1.height = height; 
    canvas2.width = width; 
    canvas2.height = height; 
    canvas1.addEventListener("mousemove", function(event) { 
    cord.mX = event.clientX - canvas1.offsetLeft; 
    cord.mY = event.clientY - canvas1.offsetTop; 
    }); 

    canvas1.addEventListener("mousedown", function(event) { 
    if (started) { 
     started = false; 
    } else { 
     started = true; 
     render(); 
    }; 
    }); 

    function update() { 
    radians = Math.atan2(cord.mY - width/2, cord.mX - height/2); 
    cord.csX = width/2 - Math.cos(radians) * cRad * -1; 
    cord.snY = height/2 - Math.sin(radians) * cRad * -1; 
    }; 

    function outerTheta() { 
    c2.beginPath(); 
    c2.arc(cord.csX, cord.snY, 3, 0, Math.PI * 2); 
    c2.closePath(); 
    c2.fillStyle = "#000"; 
    c2.fill(); 
    }; 

    function render() { 
    c1.clearRect(0, 0, width, height); 
    c1.beginPath(); 
    c1.moveTo(cord.x, cord.y); 
    c1.lineTo(cord.csX, cord.snY); 
    c1.lineWidth = 3; 
    c1.strokeStyle = "#000"; 
    c1.stroke(); 

    c1.beginPath(); //<---------------------------------- Drag-Dot 
    c1.arc(cord.csX, cord.snY, dot, 0, Math.PI * 2); 
    c1.closePath(); 
    c1.fillStyle = "#000"; 
    c1.fill(); 

    if(started){ 
     update(); 
     outerTheta(); 
     requestAnimationFrame(render); 
    }; 
    }; 
    render(); 
</script> 

Antwort

2

Der Browser ist die Animation zu Zyklus so schnell wie die Maus bewegt sich nicht in der Lage. Wenn Sie die Maus langsam bewegen, überlappen sich die Punkte, die in jedem Animationszyklus gezeichnet werden, und der Kreis hat eine durchgezogene Linie. Wenn Sie die Maus schnell bewegen, überlappen sich die Punkte nicht und Sie werden "entdeckt".

Wenn Sie genau auf die Arbeitsweise von Zeichenprogrammen achten, sehen Sie, dass das Werkzeug "Stift" eine durchgehende Linie zeichnet. Wenn Sie die Maus während der Verwendung des Werkzeugs schnell bewegen, besteht die durchgehende Linie aus Liniensegmenten, die sich von jedem Punkt erstrecken, den der Computer erfassen konnte, während sich die Maus schnell bewegte.

ich Ihr Programm so modifiziert, dass ein Liniensegment zwischen jedem erfassten Punkt während der Animationszyklus erstreckt:

https://jsfiddle.net/17hvw5pp

var canvas1 = document.getElementById("canvas1"), 
     canvas2 = document.getElementById("canvas2"),    
     c1 = canvas1.getContext("2d"), 
     c2 = canvas2.getContext("2d"), 
     dot = 7, 
     started = false, 
     width = 350, 
     height = 350, 
     radians = 0, 
     cRad = 165, // Circle Radius 
     cord = {mX:0, mY:0, csX:0, snY:0, x:0, y:0}, 
     init = function(){ 
     cord.mX = 0; 
     cord.mY = 0; 
     cord.csX = width /2 + cRad; 
     cord.snY = height /2; 
     cord.lastCSX = cord.csX; 
     cord.lastSNY = cord.snY; 
     cord.x = width /2; 
     cord.y = height /2;   
     }; 

    canvas1.style.position="absolute"; 
    canvas2.style.position="absolute"; 

    init(); 
    canvas1.width = width; 
    canvas1.height = height; 
    canvas2.width = width; 
    canvas2.height = height; 
    canvas1.addEventListener("mousemove", function(event) { 
    cord.mX = event.clientX - canvas1.offsetLeft; 
    cord.mY = event.clientY - canvas1.offsetTop; 
    }); 

    canvas1.addEventListener("mousedown", function(event) { 
    if (started) { 
     started = false; 
    } else { 
     started = true; 
     render(); 
    }; 
    }); 

    function update() { 
    radians = Math.atan2(cord.mY - width/2, cord.mX - height/2);  
    cord.csX = width/2 - Math.cos(radians) * cRad * -1; 
    cord.snY = height/2 - Math.sin(radians) * cRad * -1; 
    }; 

    function outerTheta() { 
    //draw a line from the last known coordinate to the new known coordinate 
    c2.beginPath(); 
    c2.moveTo(cord.lastCSX, cord.lastSNY); 
    c2.lineTo(cord.csX, cord.snY); 
    c2.lineWidth=5; 
    c2.strokeStyle="#000"; 
    c2.stroke(); 
    cord.lastCSX = cord.csX; 
    cord.lastSNY = cord.snY; 

    c2.beginPath(); 
    c2.arc(cord.csX, cord.snY, 3, 0, Math.PI * 2); 
    c2.closePath(); 
    c2.fillStyle = "#000"; 
    c2.fill(); 
    }; 

    function render() { 
    c1.clearRect(0, 0, width, height); 
    c1.beginPath(); 
    c1.moveTo(cord.x, cord.y); 
    c1.lineTo(cord.csX, cord.snY); 
    c1.lineWidth = 3; 
    c1.strokeStyle = "#000"; 
    c1.stroke(); 

    c1.beginPath(); //<---------------------------------- Drag-Dot 
    c1.arc(cord.csX, cord.snY, dot, 0, Math.PI * 2); 
    c1.closePath(); 
    c1.fillStyle = "#000"; 
    c1.fill(); 

    if(started){ 
     update(); 
     outerTheta(); 
     requestAnimationFrame(render); 
    }; 
    }; 
    render(); 

Das funktioniert besser, aber nicht perfekt: Wenn Sie die Maus schnell bewegen, das Liniensegment wird zu einem Akkord über den Kreis und dies ruiniert den Effekt.

ich versuchte, das Programm zu ändern, einen Bogen zwischen den zwei bekannten Punkten zu zeichnen:

https://jsfiddle.net/17hvw5pp/1/

Sie können sehen, dass diese Umsetzung auch nicht ideal ist, weil die Bogenfunktion, über die Richtung verwirrt wird zu ziehen der Teilkreis basiert auf nur zwei Radiantenkoordinaten. Die Verwendung von Quaternion-Mathematik löst dieses Problem für Sie.

https://en.wikipedia.org/wiki/Quaternion

Aber das kann mehr Komplikation, die Sie in dieses Projekt einführen wollen.

+0

Verwenden Sie für Demos bitte die internen [Snippets] von Stackoverflow (https://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) anstelle von externen Fiddles. :-) – markE

+0

Ich kann dir nicht genug danken für deine Zeit und Hilfe! Die Info Sie haben mir sehr aufgeschlossen. Ich habe zwar etwas Offensichtliches vermisst. Ich kann sehen, das Problem ist eigentlich ziemlich schwierig zu lösen und das wird sehr hilfreich sein. Ich werde noch etwas daran arbeiten und sehen, was ich damit machen kann. Danke nochmal Matt! –