Md Rahatur Rahman
Md Rahatur Rahman

Reputation: 3246

Which google map API is used to render this mouse over region select

Which google map API is used to render the mouse over region selection on map? I have attached an image of the mouse over event. See the darker portion. On mouse over different regions are automatically selected. Here is the site that implemented that feature: http://www.apartmentlist.com/ny/new-york#map

enter image description here

How do you define the zone on the map?

Upvotes: 1

Views: 1069

Answers (1)

Michael Geary
Michael Geary

Reputation: 28870

It's using google.maps.Polygon() to draw each the polygons with zero opacity, and then listening for the mouseover event on those polygons to set a nonzero opacity, and mouseout to set the opacity back to zero.

Here's the section of code where they do it:

function makeWidgets(maps) {

    function AreaPolygon(kwargs) {
        _.assertKeys(kwargs, "id", "coordinates", "type", "zoom"),
        this.id = kwargs.id,
        this.polygon = this.makePolygon(kwargs.coordinates),
        this.type = kwargs.type,
        this.zoom = kwargs.zoom, this.bindEvents()
    }
    return _.extend(AreaPolygon.prototype, {
        options: {
            mouseover: {
                strokeWeight: 1,
                strokeOpacity: .5,
                fillOpacity: .2
            },
            mouseout: {
                strokeWeight: 0,
                strokOpacity: 0,
                fillOpacity: 0
            }
        },
        polygonStyles: {
            fillColor: "#000",
            strokeColor: "#000"
        },
        polygonsState: "mouseout",
        makePolygon: function(coordinates) {
            var paths = this.makePaths(coordinates),
                kwargs = _.extend({
                    paths: paths
                }, this.polygonStyles, this.options.mouseout);
            return new maps.Polygon(kwargs)
        },
        setOptions: function() {
            return this.polygon.setOptions(
                this.options[this.polygonsState]
            ),
            this
        },
        getMap: function() {
            return this.map
        },
        setMap: function(map) {
            return map !== this.map &&
            (this.map = map, this.polygon.setMap(map)),
            this
        },
        getLatLngs: function() {
            return _chain(this.polygon.getPaths())
                .invoke("getArray")
                .flatten()
                .invoke("getArray")
                .flatten()
                .value()
        },
        onMouseOver: function() {
            app.broker.modify("view:map:polygon:current", function() {
                return this.id
            }, this)
        },
        onMouseOut: function() {
            app.broker.modify("view:map:polygon:current", function(current) {
                return current === this.id ? null : current
            }, this)
        },
        onClickMarker: function(e) {
            this.onClick(e.latLng)
        },
        eventSpec: {
            click: "onClickMarker",
            mouseover: "onMouseOver",
            mouseout: "onMouseOut"
        },
        bindEvents: function() {
            return this.bindings || (this.bindings = _.map(this.eventSpec, function(fname, event) {
                return maps.event.addListener(this.polygon, event, _.bind(this[fname], this))
            }, this)), this
        },
        cancelEvents: function() {
            return _.each(this.bindings, function(listener) {
                maps.event.removeListener(listener)
            }, this), delete this.bindings, this
        },
        onClick: function(point) {
            app.broker.set("view:map:user_move", !1);
            if ( !! this.map && app.broker.get("view:map:mode") === "clusters") {
                var currentZoom = this.map.getZoom(),
                    defaultTargetZoom =
                        app.broker.get("view:map:polygon:default_target_zoom"),
                    targetZoom = this.zoom.target || defaultTargetZoom,
                    targetType = this.type;
                targetType === "Neighborhood" ?
                    targetZoom = Math.min(currentZoom + 2, defaultTargetZoom) :
                    targetZoom <= currentZoom &&
                        (targetZoom = Math.min(currentZoom + 1, defaultTargetZoom)),
                    app.broker.setAll({ "user:position": {
                        center: point.toJSON(),
                        zoom: targetZoom
                    },
                    "view:map:polygon:clicked_id": this.id
                })
            }
            return this
        },
        getBounds: function() {
            return maps.LatLngBounds.fromLatLngs(this.getLatLngs())
        },
        getBoundsCenter: function() {
            return this.getBounds().getCenter()
        },
        isPoint: function(arr) {
            return arr.length === 2 && _.all(arr, _.isNumber)
        },
        makePaths: function(coordinates) {
            return this.isPoint(coordinates) ?
                new maps.LatLng(coordinates[1], coordinates[0]) :
                _.map(coordinates, this.makePaths, this)
        },
        destroy: function() {
            return this.setMap(null), this.cancelEvents(), this
        }
    }), {
        AreaPolygon: AreaPolygon,
        CountLabel: CountLabel,
        MapTooltip: MapTooltip
    }
}

This part is interesting:

    options: {
        mouseover: {
            strokeWeight: 1,
            strokeOpacity: .5,
            fillOpacity: .2
        },
        mouseout: {
            strokeWeight: 0,
            strokOpacity: 0,
            fillOpacity: 0
        }
    },

See the misspelled strokOpacity in the mouseout section? I'll bet that's why they added the strokeWeight: 0. They were probably debugging this, didn't notice that they'd misspelled strokeOpacity and added the strokeWeight: 0 to fix it by giving the stroke zero width. If they'd fixed the misspelling this wouldn't have been necessary.

There's another bug in the getLatLngs function. Where it says _chain it should be _.chain. Presumably getLatLngs() is never called in their code or they would have run across this error.

Upvotes: 2

Related Questions