OpenLayers: Flackern von OpenLayers.Popup bei Mausbewegung

Hallo Forum,

die OpenLayers-Projekte auf meiner Webseite sind so ziemlich fertig. Was mich allerdings stört und was ich auch unbedingt abstellen möchte, ist das lästige Flackern von Popup-Boxes.

Das OpenLayers.Features.Vector-Objekt wird wie folgt erzeugt:


select = new OpenLayers.Control.SelectFeature(vl, {
 hover: true,
 toggle: true,
 id: "SELECT_LAYER_KLICK_HUETTEN",
 eventListeners: {
  featurehighlighted: wk_onFeatureOver_Huette,
  featureunhighlighted: wk_onFeatureOut_Huette
 }
});
if (select) {
 map.addLayer(vl);
 map.addControl(select);
 select.activate();
}

Jedesmal wenn man mit der Maus über dieses Objekt fährt, öffnet sich eine Popupbox. Wenn man nun mit der Maus in die Nähe der Popupbox kommt, fängt diese an zu flackern. Das kann hier ausprobiert werden: http://www.dankoweit.de/cgi-bin/bergtouren.pl?lkz=AT&region=&typ=0

Meine Frage nun, wie stelle ich dieses nervende und unschöne Flackern ab. Tante Google und Onkel Bing haben keine verwertbaren Ergebnisse gebracht.

Danke schon mal für die Antworten und einen schönen Sonntag

Jürgen

Hi, ich hab leider keine Lösung aber eine diffuse Vermutung:

Alle Boxes überlappen sich. Eventuell kommt da wer/was durcheinander? Erstelle mal eine Box, die völlig “losgelöst” ist und schau, ob es da immer noch flackert.

Wirklich nur 'ne vage Idee aber das sollte man als Ursache ausklammern können.

Gruss
walter

Ich hab das gleiche Problem, hab mich aber noch nicht drum gekümmert.

Also wenn Du eine Lösung findest, lass es uns bitte wissen.

Gruß,
Norbert

Hallo Walter,

Diese Ursache kann man ausklammern. Inzwischen habe ich herausgefunden, warum die Popupbox flackert, wenn man die Maus bewegt.
Die komplette Popupbox inklusive “Rüssel” wird aus Bitmaps mit transparentem Hintergrund zusammengesetzt - das mache ich nicht in meinem Code, sondern das macht OpenLayers selber. Die gesamte Popupbox bildet so eine große Bitmap. Wenn man nun die Maus in die Nähe der Box bewegt und diese Bitmap erreicht, wird ein beim Feature ein Event “onmouseout” erzeugt, der die Popupbox schließt.

Nach einigem Grübeln bin ich nun auf die Idee gekommen, dass die Position des “Rüssels” am Rand des Features liegen muss, dann hört das Flackern auf. Aber die Lösung ist nicht trivial.
Mal sehen, da fällt mir auch noch der passende Code ein:)

Viele Grüße und schönen Abend

Jürgen

Hallo Norbert,

Eh kloar;)

Grüße

Jürgen

Hi Jürgen,

schöne Seite, besonders die Darstellung von Zwischenzielen einer Tour finde ich hübsch. Zum Flackerproblem kann ich leider nichts beitragen, ausser die Vermutung mit dem “Rüssel” bestätigen…

Bei den einzelnen Wanderkarten ist mir aufgefallen, dass Deinen Maßstäben ein geodesic:true gut täte. Bei den eingeblendeten UTM-Gittern fällt das recht stark auf, dass Du so kurze Kilometer hast :wink:

Grüße, Max

Das ist Bergsteigerpsychologie :smiley:

Wird eingebaut, danke für den Hinweis.

Viele Grüße

JueDan

Ich würde lieber den Event abfangen oder erst gar nicht auslösen wollen. Ist aber evtl. auch nicht ganz einfach.

Gruß,
Norbert

Hallo ikonor, wambacher, maxbe und Forum

puuuuuuh, das Problem ist - wenn auch unkonventionell - gelöst. Das Flackern hat ein Ende.

Die Lösung war der “Rüssel” bei OpenLayers.Popup.FramedCloud und dessen Ankerpunkt anchor, den man im Konstruktur definieren kann und sollte. Man schreibt sich eine Funktion, welche die Position dieses Ankerpunktes so berechnet, dass der “Rüssel” genau auf dem Rand der Boundingbox eines Features ansetzt. Diese Funktion erfordert einiges an Tüftelei, aber das macht nix, weil man so einen tieferen Einblick in OpenLayers erhält :slight_smile:
Diese Funktion berücksichtigt nicht nur rechteckige, sondern auch runde Features. Zu polygonalen Features und Text-Features ist mir noch nix eingefallen, da sie mein Problem nicht tangieren.

Schaut hier: Beschreibung

Viele Grüße und vielleicht hilft es dem Einen oder Anderen weiter.

Jürgen

Danke für die Beschreibung Deiner Lösung. Leider passt das für meinen Fall nicht so ganz, da ich auch Polygone und Linien habe und zudem die Mausposition als Anker verwende.

Deshalb hab ich noch nach einer anderen Lösung gesucht und bin nach einigem Probieren und Suchen auf eine sehr einfache Lösung gestoßen: es gibt eine CSS Eigenschaft “pointer-events”, mit der man für ein Element bestimmen kann, dass es keine Maus-Events bekommt (“none”), die erhält dann das darunterliegene Element. pointer-events für HTML Elemente ist offiziell allerdings erst für CSS4 vorgesehen und nicht in Opera und IE verfügbar (MDN, caniuse.com).

Bei mir hab ich das nach dem Erzeugen des Popups eingebaut (Popup.div ist kein API-Property!):


popup.div.style['pointer-events'] = 'none';

Gruß,
Norbert

Hallo Norbert,

Schickst Du mir mal einen Link auf Deine Seite/Anwendung. Vielleicht läßt es sich doch anwenden. Schließlich mache ich in meinem Code nichts anderes, als den Ankerpunkt an den Rand eines Features zu verschieben.

Interessant. Kannst Du weiterhin Links in der Popupbox anklicken?

Viele Grüße

Jürgen

Danke für das Angebot, aber ich denke, ich bin mit der jetzigen Lösung erst mal zufrieden. Die Anwendung ist noch in Entwicklung und noch nicht veröffentlicht, nur eine nicht ganz aktuelle Vorschau. Dort verwende ich noch das übliche feature.geometry.getBounds().getCenterLonLat(). Das hat mir aber nicht gefallen, weil:

  • bei nicht geraden LineStrings das Bounds-Zentrum dann irgendwo liegt, aber nicht auf der Linie
  • der Anker bei hohem Zoom auch außerhalb des Anzeigebereichs liegen kann, wenn die Geometrie nur teilweise innerhalb liegt
    (betrifft auch Deine Lösung - der Popup schiebt sich dann zwar dann in den Anzeigebereich, aber das gefällt mir nicht)

Das kann man zwar alles lösen, aber nur mit sehr viel Aufwand und ohne Garantie, dass das Ergebnis dann zufriedenstellend ist. Daher nehme ich einfach die Mausposition als Anker - denn da schaut man ja auch gerade hin - hebe das selektierte Feature hervor (ohne Rüssel), und nehme in Kauf, dass das Feature durch den Popup evtl. teilweise verdeckt wird.

Nein, das geht dann nicht. Da mache ich noch eine Unterscheidung und setze das nur, wenn hover=true.

Gruß,
Norbert

Hallo Forum,

bei Features mit Icons oder Images flackert die Popupbox nun auch nicht mehr:
http://www.dankoweit.de/Projekte/hp_projekte_openlayers.shtml#Popupboxes_ohne_Flackern

Viele Grüße

Jürgen

Die URL lautet nun:
http://www.dankoweit.de/Projekte/hp_projekte_openlayers.html

Ich habe diesen Code angewendet, er funktioniert. Es hat mir aber überhaupt nicht gefallen, dass die Popups machmal “in der Gegend rumschwirrten” und keinen direkten Bezug zum Objekt hatten. Deshalb wende ich zumindest für Polygone folgendes an:


function richtung(feature) {
	var bounds=feature.geometry.bounds;
	var quadrant=this.map.getExtent().determineQuadrant(bounds.getCenterLonLat());
	quadrant=OpenLayers.Bounds.oppositeQuadrant(quadrant);
	return (quadrant); //(“br” “tr” “tl” “bl”)
}

function anker(feature) {
	var quadrant=richtung(feature);
	var bounds=feature.geometry.bounds;
	var point;
	if (quadrant=="br") point = new OpenLayers.Geometry.Point(bounds.right,bounds.bottom);
	if (quadrant=="tr") point = new OpenLayers.Geometry.Point(bounds.right,bounds.top);
	if (quadrant=="tl") point = new OpenLayers.Geometry.Point(bounds.left,bounds.top);
	if (quadrant=="bl") point = new OpenLayers.Geometry.Point(bounds.left,bounds.bottom);
	
	var dist=(point.distanceTo(feature.geometry,{details:true}));
	return(new OpenLayers.LonLat(dist.x1,dist.y1));
}

function onFeatureOver(event) {
	var feature = event.feature;
	var pos = anker(feature);
	var content = "Text";
	feature.popup = new OpenLayers.Popup.FramedCloud(
		"hover",
		pos,
		null, content, null, true, null
	);
	feature.popup.calculateRelativePosition = function () {
		return richtung(feature);
	}
	map.addPopup(feature.popup);
	this.map.div.style.cursor = 'pointer';
} 

Damit befindet sich das Popup unmittelbar am Polygon.

Viele Grüße.
Petra