Canvas Halbkreis mit Maus bewegen

05/20/2015 23:31 Mr.Tr33#1
Hallo,

ich habe heute angefangen mit Canvas zu hantieren und es macht riessig spaß ... solange man etwas hinbekommt :D

Ich musste schnell realisieren, dass bei Canvas die Sachen jedes mal neu gemalten werden müssen. Das heißt, man kann nicht so direkt Objekte ansprechen (soweit ich weiß).

Erst mal was ich vorhabe:
[Only registered and activated users can see links. Click Here To Register...]

Stellt euch vor das auf dem Bild ist eine Uhr für eine Heizung
Das drumrum sind 3 Regler für die Stärke. Der innere Kreis ist für von 0 - 12 Uhr und der äussere Kreis von 12 - 24 Uhr. Blau steht für schwach, also niedrige Temperatur, grün für normal und rot für stark. Dazu müsst ihr euch vorstellen, dass an jedem Anfang und Ende jeder Farbe ein kleiner Balken ist um die länge der Temperaturen zu ändern.

So, mein Ziel ist es jetzt, dass ich einen der Balken anklicken kann und die dauer jeder Temperatur ändern kann, aber niemals auf 0 setzen. Dazu soll die andere Temperatur im selben Kreis automatisch mit veränderändert werden, sodass volle 12 Stunden entstehen. Also, wenn ich blau kleiner mache, dann füllt grün den Teil der eig. frei wäre.

Was ich bis jetzt geschafft habe:
Ich habe bis jetzt die Uhr gezeichnet und geschafft einen Halbkreis (als test) richtung Maus bewegen zu lassen (Google und so ... :D).
Ich wüste jetzt nicht, wenn ich 2 Halbkreise hätte, wie ich Canvas sage, dass ich nur ein Halbkreis bewegen will, wenn ich den einen angeklickt habe.
Ich vermute mal, dass ich die Koordinaten abfragen müssten wo die Maus gerade ist und den Halbkreis dann bewegen ... aber das ist so extrem umständlich o.O

Kennt jemand von euch eine leichtere Methode meine Idee umzusetzen? Vielleicht mit einer Libary? Ich habe zich verschiedene schon ergoogelt jedoch weiß ich nicht welche wirklich geeignet wäre für mein Vorhaben :/

MfG
Mr.Tr33
05/21/2015 00:23 Mikesch01#2
Ich schätze mal du hast deine Canvas-Zeichnung mittels JavaScript erstellt oder?

Du könntest die Logik mit JavaScript-Funktionen bauen in dem du mathematische Formeln für den Kreis benutzt. Eben dazu halt noch deine Anforderungen einbaust.
05/21/2015 01:41 Mr.Tr33#3
Danke, dass du versuchst mir zu helfen ... leider schade, dass du mein Text nicht vollständig gelesen hast. Ich habe nämlich bereits erklärt, dass ich die Uhr, also den Kreis erfolgreich gezeichnet habe und auch ein Halbkreis Richtung Mausposition bewegen kann.
05/21/2015 01:48 Mikesch01#4
Ich habe deinen Text gelesen und auch verstanden. Das ändert für mich trotzdem nichts an der Tatsache, dass es mittels Mathematik und weiteren logisch davon abhängenden Funktionen umsetzbar ist.

Du weisst ja das dein Kreis 360° hat und wenn du 80° verwendest für deinen grünen Anteil, dann bleibt halt der Rest für die Anderen. Und wenn du eben jenen Anteil änderst, dann kannst du die anderen Teile neu berechnen und zeichnen lassen.
05/21/2015 02:02 Mr.Tr33#5
Mein Problem ist nicht das Zeichnen bzw füllen der leeren Stellen, sondern eher das "woher weiß ich, dass ich jetzt genau auf den grünen Anfangsbalken im inneren Kreis klicke und nicht auf den roten Endbalken auf dem äußeren Kreis? Dazu der Gedanke, wenn die Balken alle 1x bereits verschoben sind und somit nicht in der Anfangsposition liegen".

Klar kann ich alles schön immer Zwischenspielen und dann alles mathematisch ausrechnen, das ist aber am Ende so viel Rechnerei, dass ich Angst habe, dass der Browser am Ende nicht mit macht. Daher suche ich nach anderen Möglichkeiten dies lösen. Objekte wäre eine simple Lösung, jedoch habe ich dazu noch nichts wirklich gefunden.
05/21/2015 09:29 Devsome#6
Quote:
Originally Posted by Mikesch01 View Post
[...]Du weisst ja das dein Kreis 360° hat und wenn du 80° verwendest für deinen grünen Anteil, dann bleibt halt der Rest für die Anderen. Und wenn du eben jenen Anteil änderst, dann kannst du die anderen Teile neu berechnen und zeichnen lassen.
Quote:
Originally Posted by Mr.Tr33 View Post
[...] dass ich jetzt genau auf den grünen Anfangsbalken im inneren Kreis klicke und nicht auf den roten Endbalken auf dem äußeren Kreis? [...]
Also ich verstehe das so, dass man dann jeweils jeden gemalten Kreis speichert den man ausgerechnet hat und gemalt hat.
Da man nun jeden 80° Kreis gemalt hat, kann man diesen auch seperat ansprechen und behandeln :3
05/21/2015 13:26 Mr.Tr33#7
Hö wie denn? Genau das ist ja meine Frage.
05/23/2015 09:17 Mr.Tr33#8
Kleines Update meinerseits:
Ich habe es jetzt mit oCanvas ausprobiert: [Only registered and activated users can see links. Click Here To Register...]
Jedoch hat es einen Bug. Diesen kann der ersteller von oCanvas selbst auch nicht lösen (habe ihn angeschrieben).

Kennt jemand eine Alternative zu oCanvas womit ich mein Vorhaben realisieren könnte?
05/23/2015 12:35 Serraniel#9
Quote:
Originally Posted by Mr.Tr33 View Post
Ich vermute mal, dass ich die Koordinaten abfragen müssten wo die Maus gerade ist und den Halbkreis dann bewegen ... aber das ist so extrem umständlich o.O
Ich kenn mich jetzt nicht mit den Canvas aus und weiß da möglich ist und was nicht, aber diese Aussage ist insofern falsch, dass da nichts dran umständlich ist.

Wenn du weißt an welcher Stelle der Klick passiert kannst du doch ganz einfach ermitteln auf welchem Kreis man geklickt hat.
Da die Kreise eine "dicke" Linie sind, werden die Kreise durch 2 weitere kreise beschränkt, dessen Radius du jeweils kennst.
Abstand Cursor Mittelpunkt berechnen und nun gucken: Abstand zwischen äußerer Rand und innerer Rand des inneren Kreises oder dasselbe mit dem äußeren vergleichen.
Die einzigen Rechenoperationen sind einmal Norm (oder für nicht Mathematiker: Abstand) berechnen, und zwischen 2 und 4 Vergleichsoperationen. Da geht keine Performance bei verloren....
05/23/2015 15:18 Mr.Tr33#10
Du sagst das so einfach :D
Klar kann man recht "einfach" berechnen wo der Halbkreis ist und wie dick der ist.
Jedoch macht es keinen Spaß das nochmal alles selbst zu machen bzw. die Funktionen zu erstellen. Daher habe ich nach alternativen von oCanvas gesucht die mir das bereits geben, will ja nicht das Rad neu erfinden :)
05/23/2015 23:40 Mr.Tr33#11
So Herr Serraniel, ich frage mich gerade ob du die Rechenleistung mit einberechnet hast.

Ich habe es jetzt mit simpler Mathematik ausprobiert und mein Browser ist fast abgeschmiert als ich nur einmal kurz durch das Objekt durchgewischt habe :D

Folgenden Code habe ich mir zusammen gebastelt:
Code:
var a = {
	type: 'arc',
	start: 270,
	end: 180,
	radius: 70,
	stroke: '3 #f00'
}

function checkHover(a, x, y){
	if (a['type'] == 'arc'){
		var start = [], end = [], radius_start = 0, radius_end = a['radius'];
		
		if (a['end'] < a['start']){ // z.B. start 270, end 180 -> Halbkreis => ) (wie die klammer, in der Mitte ist 0)
			start[0] = a['start']; // es wird von 270 bis 360 abgefragt und von 0 bis 180
			end[0] = 360;
			start[1] = 0;
			end[1] = a['end'];
		}else{
			start[0] = a['start'];
			end[0] = a['end'];
		}
		
		if (a['background'] == 'transparent') radius_start = a['radius']; // wenn es nur ein Bogen ist, dann fällt der innere Teil raus
		if (!a['stroke'] != '0 transparent') radius_end = radius_start+a['stroke'].split(' ')[0]; // wenn ein bogen existiert, dann wird der radius zur berechnung um die breite erweitert
		
		
		for (i = radius_start; i <= radius_end; i++){
			for(j = 0; j < start.length; j++){
				for (k = start[j]; k <= end[j]; k++){
					var readX = Math.round(a['x'] + Math.cos(k) * (i));
					var readY = Math.round(a['y'] + Math.sin(k) * (i));
					
					console.log(readX, readY);
					
					if (readX == x && readY == y) return true;
				}
			}
		}
	
	}
}
Ich habe einfach von der Mitte aus, Radius für Radius jede Koordinate berechnet und mit der Mausposition abgefragt. Das sind in diesem Beispiel (360-270)+180*(70+3) = 19710 Durchläufe der For Schleifen insgesammt pro Mausposition.

Jetzt möchte ich mal gerne wissen wie man es besser lösen kann, ausser 1x alle Positionen berechnen und zwischenspeichern. Das wären vermutlich ca. 17739 Stück (90%), wenn man die Doppelten (wegen dem Runden) abzieht.

/Edit:
Okay, ich habe mich echt doof angestellt und konnte einfach das Volumen nehmen. Dann wäre das Thema für ein Kreis gegessen.
Problem ist jedoch ein Kreisring oder noch größer nur ein Teil eines Kreisringes, weil man hierbei nicht einfach angeben kann wo es anfang und aufhört.
05/25/2015 21:49 Serraniel#12
hab mir jetzt nicht alles angeschaut aber: Zahlen statt Strings als Arrayindex sollte mehr Performence haben denke ich (weiß aber nicht wie javascript das implementiert, gehe ich jedoch stark von aus).
Quote:
PHP Code:
for (radius_start<= radius_endi++){
            for(
0start.lengthj++){
                for (
start[j]; <= end[j]; k++){
                    var 
readX Math.round(a['x'] + Math.cos(k) * (i));
                    var 
readY Math.round(a['y'] + Math.sin(k) * (i));
                    
                    
console.log(readXreadY);
                    
                    if (
readX == && readY == y) return true;
                }
            }
        } 
Sieht auf den ersten Blick mehr als unnötig aus wenn ich ehrlich bin.

PHP Code:
function checkHover(centermousecircle)
{
    
//center, mouse, circle are all three arrays with length 2; x coord and y coord stored into. For the circle we have innerRadius and outerRadius.
    
    
var distance Math.sqrt(Math.pow(mouse[0] - center[0], 2) + Math.pow(mouse[1] - center[1], 2));
    
    return (
circle[0] <= distance && distance <= circle[1]);

Edit:
Hab nicht 100% auf Syntax geachtet, aber so in der Art war die Aussage von mir mathematisch gemeint.

Edit2: Gerade dir als Mod sollte übrigends die Funktionalität der Edit Taste bekannt sein, sowie das Thema Doppelposting ;) (falls dazwischen ein Beitrag lag der Entfernt wurde zieh ich die Aussage zurück^^)
05/26/2015 00:49 Mr.Tr33#13
Habe es im Edit erwähnt, dass es mit dem Volumen ebenfalls geht. Habe nicht an die Lösung gedacht haha :D

Das Problem mit dem Kreisring und Kuchenform habe ich bereits auch Volumenmässig gelöst :)
05/26/2015 09:23 Serraniel#14
Das hat mit Volumen doch nichts zu tun...
05/26/2015 12:01 Mr.Tr33#15
Meine Flächeninhalt :D
man verschiebt den Kreis auf 0 0 und guckt ob die Maus (natürlich mit verschoben) auch darauf ist bzw in dem Radius :)
Aber ist ja jetzt Wurst