OpenLayers OpenLayers

Ticket #1709 (closed bug: fixed)

Opened 2 years ago

Last modified 2 years ago

Vector feature with external image / background image artifact on map setCenter

Reported by: openlayers Assigned to:
Priority: critical Milestone: 2.7 Release
Component: Renderer.Elements Version: 2.6
Keywords: Cc: jstern81@gmail.com
State: Complete

Description

Platform: Windows XP

Browsers with issue: Firefox 3.0.1, Safari 3.1.2 (unable to reproduce in IE7)

Vector features with an external image, that are rendered and visible on the initial map load, appear to hang around in their absolute position when setCenter is invoked on the map to center on a different location/zoom level.

example: http://t2gnow.com/sundials-osm.html Click the 'Click Me' link

Attachments

1709-r7900-A0.patch (0.5 kB) - added by jstern81 on 08/29/08 18:10:03.
1709-r7900-A1.patch (0.8 kB) - added by jstern81 on 08/30/08 17:00:40.
1709-r7900-A2.patch (1.1 kB) - added by jstern81 on 09/01/08 13:44:01.

Change History

08/28/08 20:44:22 changed by jstern81

This issue is partly resolved by applying the following patch: http://trac.openlayers.org/attachment/ticket/1675/1675-r7782-A1.patch

With it, the externalGraphic is properly cleared from the map, however a backgroundGraphic set on the vector feature is not.

Example using the patch: http://t2gnow.com/1709/sundials-osm.html

(follow-up: ↓ 7 ) 08/28/08 22:56:30 changed by jstern81

I was able to resolve the backgroundGraphic issue by adding the following code in the file OpenLayers/Renderer/Elements.js, after applying the patch above:

    drawGeometry: function(geometry, style, featureId) {
        ...
        if (style.display != "none") {
            this.redrawNode(geometry.id, geometry, style, featureId); 
        } else {
            var node = OpenLayers.Util.getElement(geometry.id);
            if (node) {
                node.parentNode.removeChild(node);
            }
            
>            node = OpenLayers.Util.getElement(geometry.id+this.BACKGROUND_ID_SUFFIX);
>            if (node) {
>                node.parentNode.removeChild(node);
>            }
        }
    },

08/29/08 03:51:08 changed by ahocevar

Thanks for the catch. This fix is absolutely valid, not only after applying the patch for #1675.

If you are able, can you please create a patch with that fix (against trunk, using svn diff or diff -u)? You would also have to sign a Contributors License Agreement (see http://trac.openlayers.org/wiki/HowToContribute).

Thanks!

08/29/08 04:35:07 changed by ahocevar

  • owner changed.
  • priority changed from minor to critical.
  • state set to Awaiting User Feedback.
  • component changed from general to Renderer.Elements.

08/29/08 04:36:24 changed by ahocevar

  • summary changed from Vector feature with external image artifact on map setCenter to Vector feature with external image / background image artifact on map setCenter.

08/29/08 18:10:03 changed by jstern81

  • attachment 1709-r7900-A0.patch added.

08/29/08 18:11:02 changed by jstern81

  • state changed from Awaiting User Feedback to Review.

(in reply to: ↑ 2 ) 08/29/08 18:14:14 changed by jstern81

Attached the patch 1709-r7900-A0.patch with the fix above for the background graphic

08/30/08 06:47:58 changed by ahocevar

  • state changed from Review to Needs More Work.

Just thinking: calling OpenLayers.Util::getElement is quite expensive, so we do not want to do that too often. So I would suggest to do this only if we have a style.backgroundGraphic. This all could go in the

if (style.backgroundGraphic) {
    this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
}

block (L467-469), so it would look something like this:

if (style.backgroundGraphic) {
    if (style.display != "none") {
        this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
    } else {
        node = OpenLayers.Util.getElement(geometry.id + this.BACKGROUND_ID_SUFFIX);
        if (node) {
            node.parentNode.removeChild(node);
        }
    }
}

This would also give us another performance improvement, by not having to call redrawBackgroundNode if we have a display: "none" style.

08/30/08 11:59:00 changed by jstern81

I agree completely, that's a much better solution. In fact, it's what my original attempt to fix the issue for this ticket looked like, however it naturally didn't accomplish what I wanted with the 1675-r7782-A1.patch applied because of the following in Renderer.js:

    drawFeature: function(feature, style) {
        if(style == null) {
            style = feature.style;
        }
        if (feature.geometry) {
            if (!feature.geometry.getBounds().intersectsBounds(this.extent)) {
                style = {display: "none"};
            }
            return this.drawGeometry(feature.geometry, style, feature.id);
        }
    },

Now if instead of setting style like we are there, we did something more like this:

                style = OpenLayers.Util.extend({}, style);
                style.display = "none";

It would work out and my background graphics would be properly hidden. I know that's maybe sort of outside the scope of this issue, but just as a heads up.

I'll attach a new patch with the check for background graphic.

08/30/08 17:00:40 changed by jstern81

  • attachment 1709-r7900-A1.patch added.

08/31/08 08:31:50 changed by ahocevar

You're right, I was not thinking about that. Since copying the whole style element may also be expensive, we could rely on the stored _style on the node, something like that:

        if (style.display != "none") {
            this.redrawNode(geometry.id, geometry, style, featureId);
            if (style.backgroundGraphic) {
                this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
            } 
        } else {
            node = OpenLayers.Util.getElement(geometry.id);
            if (node) {
                if (node._style.backgroundGraphic) {
                    node.parentNode.removeChild(document.getElementById(
                        geometry.id + this.BACKGROUND_ID_SUFFIX));
                }
                node.parentNode.removeChild(node);
            }
        }

09/01/08 11:02:57 changed by ahocevar

The more I think about it, the more I am convinced that the above solution is the correct one: If we have a node when style.display=="none", then the node has already be drawn, and will have a node._style hash attached. If this _style hash has a backgroundGraphic property set, we know that we have to remove a background graphic node, because this is still there from the previous drawGeometry call.

jstern81: Sorry for the inconvenience with all the change requests around this patch. Just let me know if you don't want to continue working on it, then I can take care of finishing it.

09/01/08 13:44:01 changed by jstern81

  • attachment 1709-r7900-A2.patch added.

09/01/08 13:51:19 changed by jstern81

Nice, that seems like the best solution so far. I made one small tweak from the above code for the latest patch: I'm redrawing the background node before the foreground one.

ahocevar: don't worry about it, I'm happy to help out and this way I'm actually learning a bit more than I would have otherwise. But on the other hand if there's any other small changes and it's more convenient for you to just make the change without waiting around for me, please feel free to do so. I'll still be hanging around to see what the final change looks like. cheers

09/01/08 16:46:27 changed by ahocevar

(In [7919]) Let's take care that background graphic nodes of features with backgroundGraphic style get removed properly when the style is changed to display: "none".

This solves the backgroundGraphic issue of #1709, the remaining issue with externalGraphic will be fixed by #1675.

Thanks jstern81 for the patch, and I am truly impressed by jstern81 finding the right spot in the codebase that needs to be fixed -- as an OpenLayers newcomer.

Tests added by myself. r=me. (references #1709)

09/02/08 12:21:30 changed by crschmidt

  • status changed from new to closed.
  • state changed from Needs More Work to Complete.
  • resolution set to fixed.

r7930 /trunk/openlayers/ (12 files in 7 dirs): New vector rendering for better performance and less renderer specific limitations. r=elemoine (closes #1675, closes #1656, closes #1631, closes #1431, closes #1709)