让isis支持高德地图

概述

由于项目需要用到地图,虽然isis的插件库里有个现成的地图实现,不过用的google地图,虽然google地图可以不用注册Appkey,但完全打不开。所以打算改成国产地图。

效果

先看下运行效果。

列表中的效果:

整体效果:

详细效果:

实现思路

高德地图的API跟Google地图类似,编程模型也相同,甚至很多类的命名都一样的。所以,从Google迁到高德还是比较容易的。

高德跟Google一样,用一个DIV来渲染地图。根据Vicket的编程方式,这个Div使用一个组件来表示,这个组件包含了相应的属性和呈现出来的模板及脚本。

先看下Google的模板,很简单在Panel里放了一个Div:

<html xmlns:wicket>
    <body>
    <wicket:panel>
        <div wicket:id="map" style="width:100%; height:100%"></div>
    </wicket:panel>
</body>
</html>

 Google的客户端对应的初始化脚本:

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Wicket GMap3
 *
 * @author Tilman M�ller
 * @author Joachim F. Rohde
 */
// Wicket Namespace
if (typeof(Wicket) === 'undefined') {
    window.Wicket = {};
}
else if (typeof(Wicket) !== "object") {
    throw new Error("Wicket already exists but is not an object");
}

function WicketClientGeocoder() {

    try {
        this.coder = new google.maps.Geocoder();
    } catch (e) {
        if( !Wicket.maps['_failSilently'] ) {
            throw e;
        }
    }

    this.getLatLng = function(callBack, addressId){

        var address = Wicket.$(addressId).value;

        this.coder.geocode({
            'address': address
        }, function(results, status){

            if (status === google.maps.GeocoderStatus.OK) {
                callBack = callBack + '&address=' + results[0].formatted_address;
                callBack = callBack + '&coordinates=' + results[0].geometry.location;
            }
            callBack = callBack + '&status=' + status;

            Wicket.Ajax.ajax({
                'u':callBack
            });
        });
    }
}

Wicket.maps = {}

function WicketMap(id, failSilently) {
    Wicket.maps[id] = this;

    if(failSilently) {
        Wicket.maps['_failSilently'] = failSilently;
    }

    this.options = {};
    try {
        this.map = new google.maps.Map(Wicket.$(id));
    } catch (e) {
        if(!failSilently) {
            throw e;
        }
    }
    this.overlays = {};

    this.onEvent = function(callBack, params) {
        params['center'] = this.map.getCenter();
        params['bounds'] = this.map.getBounds();
        params['zoom'] = this.map.getZoom();
        params['currentMapType'] = this.getMapTypeString(this.map.getMapTypeId());

        for ( var key in params) {
            callBack = callBack + '&' + key + '=' + params[key];
        }

        Wicket.Ajax.ajax({
            'u':callBack
        });
    }

    this.addListener = function(event, callBack) {
        var self = this;

        google.maps.event.addListener(this.map, event, function() {
            var params = {};
            for ( var p = 0; p < arguments.length; p++) {

                if (arguments[p] != null) {
                    if (arguments[p].latLng != null)
                    {
                        params['lat'] = arguments[0].latLng.lat();
                        params['lng'] = arguments[0].latLng.lng();
                    }
                }
            }

            self.onEvent(callBack, params);
        });
    }


    this.addOverlayListener = function(overlayID, event) {
        var self = this;
        var overlay = this.overlays[overlayID];

        google.maps.event.addListener(overlay, event, function() {
            var params = {};
            for ( var p = 0; p < arguments.length; p++) {
                if (arguments[p] != null) {
                    params['argument' + p] = arguments[p];
                }
            }

            if (overlay.getPosition) {
                params['overlay.latLng'] = overlay.getPosition();
            }
            else if (overlay.getCenter) {
                // Circle uses #getCenter() instead
                params['overlay.latLng'] = overlay.getCenter();
            }

            if (overlay.getRadius) {
                // Circle
                params['overlay.radius'] = overlay.getRadius();
            }

            if (overlay.getBounds) {
                params['overlay.bounds'] = overlay.getBounds();
            }

            params['overlay.overlayId'] = overlay.overlayId;
            params['overlay.event'] = event;

            self.onEvent(self.overlayListenerCallbackUrl, params);
        });
    }

    this.clearOverlayListeners = function(overlayID, event) {
        var overlay = this.overlays[overlayID];

        google.maps.event.clearListeners(overlay, event);
    }

    this.setDraggingEnabled = function(enabled) {
        this.options.draggable = enabled;
        this.map.setOptions(this.options);
    }

    this.setDoubleClickZoomEnabled = function(enabled) {
        this.options.disableDoubleClickZoom = enabled;
        this.map.setOptions(this.options);
    }

    this.setScrollWheelZoomEnabled = function(enabled) {
        this.options.scrollwheel = enabled;
        this.map.setOptions(this.options);
    }

    this.setScaleControlEnabled = function(enabled) {
        this.options.scaleControl = enabled;
        this.map.setOptions(this.options);
    }

    this.setZoomControlEnabled = function(enabled) {
        this.options.zoomControl = enabled;
        this.map.setOptions(this.options);
    }

    this.setMapTypeControlEnabled = function(enabled) {
        this.options.mapTypeControl = enabled;
        this.map.setOptions(this.options);
    }

    this.setStreetViewControlEnabled = function(enabled) {
        this.options.streetViewControl = enabled;
        this.map.setOptions(this.options);
    }

    this.setPanControlEnabled = function(enabled) {
        this.options.panControl = enabled;
        this.map.setOptions(this.options);
    }
    
    this.fitBounds = function(bounds) {
        this.options.bounds = bounds;
        this.map.setOptions(this.options);
        this.map.fitBounds(bounds);
    }
    
    this.panToBounds = function(bounds) {
        this.options.bounds = bounds;
        this.map.setOptions(this.options);
        this.map.panToBounds(bounds);
    }
	
    this.setMinZoom = function(minZoom) {
        this.options.minZoom = minZoom;
        this.map.setOptions(this.options);
    }
	
    this.setMaxZoom = function(maxZoom) {
        this.options.maxZoom = maxZoom;
        this.map.setOptions(this.options);
    }

    this.getMapTypeString = function(mapType) {
        switch (mapType) {
            case google.maps.MapTypeId.ROADMAP:
                return 'ROADMAP';
                break;
            case google.maps.MapTypeId.SATELLITE:
                return 'SATELLITE';
                break;
            case google.maps.MapTypeId.HYBRID:
                return 'HYBRID';
                break;
            case google.maps.MapTypeId.TERRAIN:
                return 'TERRAIN';
                break;
            default:
                return 'unknown';
                break;
        }
    }

    this.setMapType = function(mapType) {
        this.map.setMapTypeId(mapType);
    }

    this.setZoom = function(level) {
        this.map.setZoom(level);
    }

    this.setCenter = function(center) {
    //设置地图中心 this.map.setCenter(center); } this.setCenterFailSafe = function(lat, lng, unbounded) { try { this.map.setCenter( new google.maps.LatLng(lat, lng, unbounded) ); } catch (e) { // do nothing } } this.panTo = function(center) { this.map.panTo(center); } this.panDirection = function(dx, dy) { this.map.panBy(dx, dy); } this.zoomOut = function() { this.map.setZoom(this.map.getZoom()-1) } this.zoomIn = function() { this.map.setZoom(this.map.getZoom()+1) } this.addOverlay = function(overlayId, overlay) { this.overlays[overlayId] = overlay; overlay.overlayId = overlayId; overlay.setMap(this.map); overlay.toString = function() { return overlayId; }; } this.removeOverlay = function(overlayId) { if (this.overlays[overlayId] != null) { this.overlays[overlayId].setMap(null); this.overlays[overlayId] = null; } } this.clearOverlays = function() { if (this.overlays) { for (i in this.overlays) { this.overlays[i].setMap(null); } } this.overlays = {}; } this.triggerEvent = function(event) { google.maps.event.trigger(this.map, event); } this.triggerResize = function() { this.triggerEvent('resize'); } } Wicket.Event.add(window, "load", function(event){ if(typeof(Wicket.geocoder) === 'undefined') Wicket.geocoder = new WicketClientGeocoder(); });

 Java部分的实现,可以看出其属性与客户端的JS是一一对应的,这是Vicket的一种机制,将服务端的对象映射到客户端,这样在服务端设置属性就跟在客户端设置一样:

/*
 *
 * ==============================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.wicketstuff.gmap;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.util.string.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wicketstuff.gmap.api.GEvent;
import org.wicketstuff.gmap.api.GLatLng;
import org.wicketstuff.gmap.api.GLatLngBounds;
import org.wicketstuff.gmap.api.GMapType;
import org.wicketstuff.gmap.api.GMarker;
import org.wicketstuff.gmap.api.GMarkerCluster;
import org.wicketstuff.gmap.api.GMarkerOptions;
import org.wicketstuff.gmap.api.GOverlay;
import org.wicketstuff.gmap.event.GEventListenerBehavior;

/**
 * Wicket component to embed <a href="http://maps.google.com">Google Maps</a> into your pages.
 * <p>
 */
public class GMap extends Panel implements GOverlayContainer
{

    /** log. */
    private static final Logger log = LoggerFactory.getLogger(GMap.class);
    private static final long serialVersionUID = 1L;
    // Center is Palo Alto
    private GLatLng center = new GLatLng(37.4419, -122.1419);
    private boolean draggingEnabled = true;
    private boolean doubleClickZoomEnabled = false;
    private boolean scrollWheelZoomEnabled = false;
    private boolean streetViewControlEnabled = false;
    private boolean zoomControlEnabled = true;
    private boolean mapTypeControlEnabled = true;
    private boolean scaleControlEnabled = false;
    private boolean panControlEnabled = true;
    private GMapType mapType = GMapType.ROADMAP;
    private int zoom = 13;
    private int minZoom = 0;
    private int maxZoom = 0;
    private final Map<String, GOverlay> overlays = new HashMap<String, GOverlay>();
    protected final WebMarkupContainer map;
    private GLatLngBounds bounds;
    private OverlayListener overlayListener = null;
    private List<GLatLng> markersToShow = new ArrayList<GLatLng>();
    
    /**
     * If set to true map loading will not produce any JavaScript errors in case
     * google maps API cannot be found (e.g. no Internet connection)
     */
    private boolean failSilently = false;
    private GMarkerCluster markerCluster;

    /**
     * Constructor.
     *
     * Default the header contributor of the component will added and the gmap
     * will be initiated directly on rendering of the map.
     *
     * @param id wicket id
     * @param apiKey your Google API key
     */
    public GMap(final String id, String apiKey)
    {
        this(id, new GMapHeaderContributor("http", apiKey));
    }

    /**
     * Constructor.
     *
     * Default the header contributor of the component will added and the gmap
     * will be initiated directly on rendering of the map.
     *
     * @param id wicket id
     * @param scheme the scheme ("http" or "https") which should be used
     * @param apiKey your Google API key
     */
    public GMap(final String id, String apiKey, String scheme)
    {
        this(id, new GMapHeaderContributor(scheme, apiKey));
    }

    /**
     * Construct.
     *
     * Default the header contributor of the component will added and the gmap
     * will be initiated directly on rendering of the map.
     *
     * @param id wicket id
     * @deprecated since 22th June 2016 Google Maps requires an API-key,
     * therefore you should use
     * {@link #GMap(java.lang.String, java.lang.String) } or {@link #GMap(java.lang.String, java.lang.String, java.lang.String)
     * }
     * instead of this constructor
     * @see
     * http://googlegeodevelopers.blogspot.de/2016/06/building-for-scale-updates-to-google.html
     */
    public GMap(final String id)
    {
        this(id, new GMapHeaderContributor());
    }

    /**
     * @deprecated Since the sensor-parameter is no longer required from Google
     * {@link #GMap(java.lang.String, java.lang.String) } or {@link #GMap(java.lang.String, java.lang.String, java.lang.String)
     * }
     * instead of this constructor
     */
    public GMap(final String id, final boolean sensor)
    {
        this(id, new GMapHeaderContributor(sensor));
    }

    /**
     * Construct.
     *
     * @param id
     * @param headerContrib
     */
    public GMap(final String id, final GMapHeaderContributor headerContrib)
    {
        super(id);

        if (headerContrib != null)
        {
            add(headerContrib);
        }

        map = new WebMarkupContainer("map");
        map.setOutputMarkupId(true);
        add(map);

        overlayListener = getOverlayListener();
        add(overlayListener);

    }
    
    protected OverlayListener getOverlayListener()
    {
    	return new OverlayListener();
    }

    /**
     * @return the markup-id of the container
     */
    public String getMapId()
    {
        return map.getMarkupId();
    }

    @Override
    protected void onBeforeRender()
    {
        super.onBeforeRender();

        if (getApplication().usesDevelopmentConfig()
                && !getApplication().getMarkupSettings().getStripWicketTags())
        {
            log.warn("Application is in DEVELOPMENT mode && Wicket tags are not stripped,"
                    + "Some Chrome Versions will not render the GMap."
                    + " Change to DEPLOYMENT mode  || turn on Wicket tags stripping." + " See:"
                    + " http://www.nabble.com/Gmap2-problem-with-Firefox-3.0-to18137475.html.");
        }
    }

    @Override
    public void renderHead(IHeaderResponse response)
    {
        response.render(OnDomReadyHeaderItem.forScript(getJSinit()));
    }

    /**
     * Add an overlay.
     *
     * @see GOverlayContainer#addOverlay(GOverlay)
     * @param overlay
     * overlay to add
     * @return This
     */
    @Override
    public GMap addOverlay(final GOverlay overlay)
    {
        overlays.put(overlay.getId(), overlay);
        overlay.setParent(this);

        AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
        if (target != null && findPage() != null)
        {
            target.appendJavaScript(overlay.getJS());
        }

        return this;
    }

    /**
     * Remove an overlay.
     *
     * @see GOverlayContainer#removeOverlay(GOverlay)
     * @param overlay
     * overlay to remove
     * @return This
     */
    @Override
    public GMap removeOverlay(final GOverlay overlay)
    {
        while (overlays.containsKey(overlay.getId()))
        {
            overlays.remove(overlay.getId());
        }

        AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class);
        if (target != null && findPage() != null)
        {
            target.appendJavaScript(overlay.getJSremove());
        }

        overlay.setParent(null);

        return this;
    }

    /**
     * Clear all overlays.
     *
     * @see GOverlayContainer#removeAllOverlays()
     * @return This
     */
    @Override
    public GMap removeAllOverlays()
    {
        for (final GOverlay overlay : overlays.values())
        {
            overlay.setParent(null);
        }
        overlays.clear();
        AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
        if (target != null && findPage() != null)
        {
            target.appendJavaScript(getJSinvoke("clearOverlays()"));
        }
        return this;
    }

    /**
     * @see GOverlayContainer#getOverlays()
     */
    @Override
    public List<GOverlay> getOverlays()
    {
        return Collections.unmodifiableList(new ArrayList<GOverlay>(overlays.values()));
    }

    public GLatLngBounds getBounds()
    {
        return bounds;
    }

    public void setBounds(GLatLngBounds bounds)
    {
		this.bounds = bounds;
	}

    /**
     * Returns the script for triggering an event on map.
     *
     * @param event
     * @return
     */
    public CharSequence getTriggerEventScript(String event) {
		return "Wicket.maps['"+getMapId()+ "'].triggerEvent('"+event+"')";
	}

    /**
     * @return returns the script to make map re-paint after resize.
     */
	public CharSequence getTriggerResizeScript() {
		return "Wicket.maps['"+getMapId()+ "'].triggerResize();";
	}

    /**
     * Sets if dragging should be allowed or not.
     * @param enabled true if dragging should be allowed, false otherwise
     */
    public void setDraggingEnabled(final boolean enabled)
    {
        if (this.draggingEnabled != enabled)
        {
            draggingEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetDraggingEnabled(enabled));
            }
        }
    }

    /**
     * Is dragging allowed? Enabled by default.
     *
     * @return true if it's allowed, false if not
     */
    public boolean isDraggingEnabled()
    {
        return draggingEnabled;
    }

    /**
     * Sets if zooming-by-doubleclicking should be allowed or not.
     * @param enabled true if zooming-by-doubleclicking should be allowed, false otherwise
     */
    public void setDoubleClickZoomEnabled(final boolean enabled)
    {
        if (this.doubleClickZoomEnabled != enabled)
        {
            doubleClickZoomEnabled = enabled;

            AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetDoubleClickZoomEnabled(enabled));
            }
        }
    }

    /**
     * Is the function zooming-by-doubleclick enabled?
     * Disabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isDoubleClickZoomEnabled()
    {
        return doubleClickZoomEnabled;
    }

    /**
     * Sets if zooming-by-mousewheel should be allowed or not.
     * @param enabled true if zooming-by-mousewheel should be allowed, false otherwise
     */
    public void setScrollWheelZoomEnabled(final boolean enabled)
    {
        if (this.scrollWheelZoomEnabled != enabled)
        {
            scrollWheelZoomEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetScrollWheelZoomEnabled(enabled));
            }
        }
    }

    /**
     * Is the function zooming-by-mousewheel enabled?
     * Disabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isScrollWheelZoomEnabled()
    {
        return scrollWheelZoomEnabled;
    }

    /**
     * Is the StreetView control enabled?
     * Disabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isStreetViewControlEnabled()
    {
        return streetViewControlEnabled;
    }

    /**
     * Sets if the StreeView control should be visible or not.
     * @param enabled true if StreetView should be allowed, false otherwise
     */
    public void setStreetViewControlEnabled(boolean enabled)
    {
        if (this.streetViewControlEnabled != enabled)
        {
            streetViewControlEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetStreetViewControlEnabled(enabled));
            }
        }
    }

    /**
     * Is the zoom control enabled?
     * Enabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isZoomControlEnabled()
    {
        return zoomControlEnabled;
    }

    /**
     * Sets if the zoom control should be visible or not.
     * @param enabled true if the zoom-control should be enabled, false otherwise
     */
    public void setZoomControlEnabled(boolean enabled)
    {
        if (this.zoomControlEnabled != enabled)
        {
            this.zoomControlEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetZoomControlEnabled(enabled));
            }
        }
    }

    /**
     * Is the map type control enabled?
     * Enabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isMapTypeControlEnabled()
    {
        return mapTypeControlEnabled;
    }

    /**
     * Sets if the map type control should be visible or not.
     * @param enabled true if you want the user to have the possibility to
     * change the map type, false otherwise
     */
    public void setMapTypeControlEnabled(boolean enabled)
    {

        if (this.mapTypeControlEnabled != enabled)
        {
            this.mapTypeControlEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetMapTypeControlEnabled(enabled));
            }
        }
    }

    /**
     * Is the scale control enabled?
     * Disabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isScaleControlEnabled()
    {
        return scaleControlEnabled;
    }

    /**
     * Sets if the scale control should be visible or not.
     * @param enabled true if the scale-control should be enabled, false otherwise
     */
    public void setScaleControlEnabled(boolean enabled)
    {
        if (this.scaleControlEnabled != enabled)
        {
            this.scaleControlEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetScaleControlEnabled(enabled));
            }
        }
    }

    /**
     * Is the pan control enabled?
     * Enabled by default.
     *
     * @return true if enabled, false if disabled
     */
    public boolean isPanControlEnabled()
    {
        return panControlEnabled;
    }

    /**
     * Sets if the pan control should be visible or not.
     * @param enabled true if the pan-control should be enabled, false otherwise
     */
    public void setPanControlEnabled(boolean enabled)
    {
        if (this.panControlEnabled != enabled)
        {
            this.panControlEnabled = enabled;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetPanControlEnabled(enabled));
            }
        }
    }

    /**
     * @return the current map type.
     * @see GMapType
     */
    public GMapType getMapType()
    {
        return mapType;
    }

    /**
     * Sets the map type which should be used.
     * @param mapType the map type
     * @see GMapType
     */
    public void setMapType(final GMapType mapType)
    {
        if (this.mapType != mapType)
        {
            this.mapType = mapType;

            AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(mapType.getJSsetMapType(GMap.this));
            }
        }
    }

    /**
     * @return the current zoom level
     */
    public int getZoom()
    {
        return zoom;
    }
	
    /**
     * @return the minZoom level
     */
    public int getMinZoom()
    {
        return minZoom;
    }
	
    /**
     * @return the maxZoom level
     */
    public int getMaxZoom()
    {
        return maxZoom;
    }

    /**
     * Sets a new zoom level.
     * @param level the new zoom level
     */
    public void setZoom(final int level)
    {
        if (this.zoom != level)
        {
            this.zoom = level;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetZoom(zoom));
            }
        }
    }
	
    /**
     * Sets a new minZoom limit.
     * @param level the new minZoom level
     */
    public void setMinZoom(final int level)
    {
        if (this.minZoom != level)
        {
            this.minZoom = level >= 0 ? level : 0;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetMinZoom(minZoom));
            }
        }
    }
	
    /**
     * Sets a new maxZoom limit.
     * @param level the new maxZoom level
     */
    public void setMaxZoom(final int level)
    {
        if (this.maxZoom != level)
        {
            this.maxZoom = level >= 0 ? level : 0;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetMaxZoom(maxZoom));
            }
        }
    }

    /**
     * @return the current center point
     */
    public GLatLng getCenter()
    {
        return center;
    }

    /**
     * Set the center.
     *
     * @param center
     * center to set
     */
    public void setCenter(final GLatLng center)
    {
        if (!this.center.equals(center))
        {
            this.center = center;

            AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSsetCenter(center));
            }
        }
    }

    /**
     * Changes the center point of the map to the given point. If the point is already visible in the current map view,
     * change the center in a smooth animation.
     *
     * @param center
     * the new center of the map
     */
    public void panTo(final GLatLng center)
    {
        if (!this.center.equals(center))
        {
            this.center = center;

            AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
            if (target != null && findPage() != null)
            {
                target.appendJavaScript(getJSpanTo(center));
            }
        }
    }
    
    public void setMarkerCluster(GMarkerCluster markerCluster)
    {
        if(markerCluster == null)
            throw new IllegalArgumentException("GMarkerCluster argument should not be null.");
        this.markerCluster = markerCluster;
        if (getBehaviors(GMapMarkerClustererHeaderContributor.class).isEmpty()) 
        {
            add(new GMapMarkerClustererHeaderContributor());
        }
    }

    public boolean isMarkerClusterEnabled()
    {
        return markerCluster != null;
    }
    
    /**
     * Generates the JavaScript used to instantiate this GMap3 as an JavaScript class on the client side.
     *
     * @return The generated JavaScript
     */
    public String getJSinit()
    {
        final StringBuilder js = new StringBuilder("new WicketMap('" + getMapId() + "', "+isFailSilently() +");\n");

        js.append(getJSinvoke("clearOverlays()"));
        js.append(overlayListener.getJSinit());
        js.append(getJSsetCenter(getCenter()));
        js.append(getJSsetZoom(getZoom()));
        js.append(getJSsetMinZoom(getMinZoom()));
        js.append(getJSsetMaxZoom(getMaxZoom()));
        js.append(getJSfitBounds());
        js.append(getJSsetDraggingEnabled(draggingEnabled));
        js.append(getJSsetDoubleClickZoomEnabled(doubleClickZoomEnabled));
        js.append(getJSsetScrollWheelZoomEnabled(scrollWheelZoomEnabled));
        js.append(getJSsetStreetViewControlEnabled(streetViewControlEnabled));
        js.append(getJSsetZoomControlEnabled(zoomControlEnabled));
        js.append(getJSsetScaleControlEnabled(scaleControlEnabled));
        js.append(getJSsetMapTypeControlEnabled(mapTypeControlEnabled));
        js.append(getJSsetPanControlEnabled(panControlEnabled));
        js.append(getJSFitMarkers());
        js.append(mapType.getJSsetMapType(this));

        // Add the overlays.
        for (final GOverlay overlay : overlays.values())
        {
            js.append(overlay.getJS());
        }
        for (final Object behavior : getBehaviors(GEventListenerBehavior.class))
        {
            js.append(((GEventListenerBehavior) behavior).getJSaddListener());
        }
        
        js.append(getJSMarkerCluster());

        return js.toString();
    }

    /**
     * Convenience method for generating a JavaScript call on this GMap with the given invocation.
     *
     * @param invocation
     * The JavaScript call to invoke on this GMap.
     * @return The generated JavaScript.
     */
    public String getJSinvoke(final String invocation)
    {
        return getJsReference() + "." + invocation + ";\n";
    }

    /**
     * Build a reference in JS-Scope.
     */
    public String getJsReference()
    {
        return "Wicket.maps['" + getMapId() + "']";
    }

    /**
     * @see #fitMarkers(List, boolean, double)
     */
    public void fitMarkers(final List<GLatLng> markersToShow)
    {
        fitMarkers(markersToShow, false, 0.0);
    }

    /**
     * @see #fitMarkers(List, boolean, double)
     */
    public void fitMarkers(final List<GLatLng> markersToShow, final boolean showMarkersForPoints)
    {
        fitMarkers(markersToShow, showMarkersForPoints, 0.0);
    }

    /**
     * <p>
     * Makes the map zoom out and centre around all the GLatLng points in markersToShow.
     * <p>
     * Big ups to Doug Leeper for the code.
     *
     * @see <a href= "http://www.nabble.com/Re%3A-initial-GMap2-bounds-question-p19886673.html" >Doug's Nabble post</a>
     * @param markersToShow
     * the points to centre around.
     * @param showMarkersForPoints
     * if true, will also add basic markers to the map for each point focused on. Just a simple convenience
     * method - you will probably want to turn this off so that you can show more information with each
     * marker when clicked etc.
     */
    public void fitMarkers(final List<GLatLng> markersToShow, final boolean showMarkersForPoints,
            final double zoomAdjustment)
    {
        this.markersToShow = markersToShow;
        
        // show the markers
        if (showMarkersForPoints)
        {
            for (final GLatLng location : markersToShow)
            {
                this.addOverlay(new GMarker(new GMarkerOptions(this, location)));
            }
        }
    }
    
    private String getJSFitMarkers() {
        if (markersToShow.isEmpty())
        {
            return "";
        }
        
        final StringBuilder buf = new StringBuilder();
        buf.append("var bounds = new google.maps.LatLngBounds();\n");
        // Ask google maps to keep extending the bounds to include each point
        for (final GLatLng point : markersToShow)
        {
            buf.append("bounds.extend( ").append(point.getJSconstructor()).append(" );\n");
        }
        
        buf.append(getJSinvoke("fitBounds(bounds)"));
        buf.append(getJSinvoke("panToBounds(bounds)"));
        
        return buf.toString();
    }
    
    private String getJSsetDraggingEnabled(final boolean enabled)
    {
        return getJSinvoke("setDraggingEnabled(" + enabled + ")");
    }

    private String getJSsetDoubleClickZoomEnabled(final boolean enabled)
    {
        return getJSinvoke("setDoubleClickZoomEnabled(" + enabled + ")");
    }

    private String getJSsetScrollWheelZoomEnabled(final boolean enabled)
    {
        return getJSinvoke("setScrollWheelZoomEnabled(" + enabled + ")");
    }

    private String getJSsetStreetViewControlEnabled(final boolean enabled)
    {
        return getJSinvoke("setStreetViewControlEnabled(" + enabled + ")");
    }

    private String getJSsetZoomControlEnabled(final boolean enabled)
    {
        return getJSinvoke("setZoomControlEnabled(" + enabled + ")");
    }

    private String getJSsetScaleControlEnabled(final boolean enabled)
    {
        return getJSinvoke("setScaleControlEnabled(" + enabled + ")");
    }

    private String getJSsetMapTypeControlEnabled(final boolean enabled)
    {
        return getJSinvoke("setMapTypeControlEnabled(" + enabled + ")");
    }

    private String getJSsetPanControlEnabled(final boolean enabled)
    {
        return getJSinvoke("setPanControlEnabled(" + enabled + ")");
    }

    private String getJSsetZoom(final int zoom)
    {
        return getJSinvoke("setZoom(" + zoom + ")");
    }
	
    private String getJSsetMinZoom(final int minZoom)
    {
        return getJSinvoke("setMinZoom(" + minZoom + ")");
    }
	
    private String getJSsetMaxZoom(final int maxZoom)
    {
        return getJSinvoke("setMaxZoom(" + maxZoom + ")");
    }

    /**
     * Build the JavaScript for fitBounds() with the bounds property
     * 
     * @return JavaScript for the fitBounds-Function
     */
	private String getJSfitBounds() {
		if (null == bounds || Strings.isEmpty(bounds.getJSconstructor())) {
			return "";
		} // else
		return getJSinvoke("fitBounds(" + bounds.getJSconstructor() + ")");
	}


    private String getJSsetCenter(final GLatLng center)
    {
        if (center != null)
        {
        	if( !failSilently )
        	{
        		return getJSinvoke("setCenter(" + center.getJSconstructor() + ")");
        	} else {
        		return getJSinvoke("setCenterFailSafe(" + center.getArguments() + ")");
        	}
        }
        return "";
    }

    private String getJSpanDirection(final int dx, final int dy)
    {
        return getJSinvoke("panDirection(" + dx + "," + dy + ")");
    }

    private String getJSpanTo(final GLatLng center)
    {
        return getJSinvoke("panTo(" + center.getJSconstructor() + ")");
    }

    private String getJSzoomOut()
    {
        return getJSinvoke("zoomOut()");
    }

    private String getJSzoomIn()
    {
        return getJSinvoke("zoomIn()");
    }
    
    private String getJSMarkerCluster()
    {
    	if(markerCluster != null)
    	{
    		
    		return markerCluster.getJSconstructor();
    	}
    	return "";
    }
    
    

    /**
     * Update state from a request to an AJAX target.
     * You need to call this method explictly if you want to have up-to-date values.
     */
    public void update()
    {
        // Attention: don't use setters as this will result in an endless
        // AJAX request loop
        IRequestParameters requestParameters = getRequest().getRequestParameters();
        bounds = GLatLngBounds.parse(requestParameters.getParameterValue("bounds").toString());
        center = GLatLng.parse(requestParameters.getParameterValue("center").toString());
        zoom = requestParameters.getParameterValue("zoom").toInt(zoom);
        String requestMapType = requestParameters.getParameterValue("currentMapType").toString();
        mapType = requestMapType != null ? GMapType.valueOf(requestParameters.getParameterValue("currentMapType").toString()) : mapType;
    }

    public void setOverlays(final List<GOverlay> overlays)
    {
        removeAllOverlays();
        for (final GOverlay overlay : overlays)
        {
            addOverlay(overlay);
        }
    }

    private static abstract class JSMethodBehavior extends Behavior
    {
        private static final long serialVersionUID = 1L;
        private final String attribute;

        public JSMethodBehavior(final String attribute)
        {
            this.attribute = attribute;
        }

        @Override
        public void onComponentTag(final Component component, final ComponentTag tag)
        {
            String invoke = getJSinvoke();

            if (attribute.equalsIgnoreCase("href"))
            {
                invoke = "javascript:" + invoke;
            }

            tag.put(attribute, invoke);
        }

        protected abstract String getJSinvoke();
    }

    public class ZoomOutBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;

        public ZoomOutBehavior(final String event)
        {
            super(event);
        }

        @Override
        protected String getJSinvoke()
        {
            return getJSzoomOut();
        }
    }

    public class ZoomInBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;

        public ZoomInBehavior(final String event)
        {
            super(event);
        }

        @Override
        protected String getJSinvoke()
        {
            return getJSzoomIn();
        }
    }

    public class PanDirectionBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;
        private final int dx;
        private final int dy;

        public PanDirectionBehavior(final String event, final int dx, final int dy)
        {
            super(event);
            this.dx = dx;
            this.dy = dy;
        }

        @Override
        protected String getJSinvoke()
        {
            return getJSpanDirection(dx, dy);
        }
    }

    public class SetZoomBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;
        private final int zoomBehavior;

        public SetZoomBehavior(final String event, final int zoom)
        {
            super(event);
            zoomBehavior = zoom;
        }

        @Override
        protected String getJSinvoke()
        {
            return getJSsetZoom(zoomBehavior);
        }
    }

    public class SetCenterBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;
        private final GLatLng gLatLng;

        public SetCenterBehavior(final String event, final GLatLng gLatLng)
        {
            super(event);
            this.gLatLng = gLatLng;
        }

        @Override
        protected String getJSinvoke()
        {
            return getJSsetCenter(gLatLng);
        }
    }

    public class SetMapTypeBehavior extends JSMethodBehavior
    {
        private static final long serialVersionUID = 1L;
        private final GMapType mapTypeBehavior;

        public SetMapTypeBehavior(final String event, final GMapType mapType)
        {
            super(event);
            mapTypeBehavior = mapType;
        }

        @Override
        protected String getJSinvoke()
        {
            return mapTypeBehavior.getJSsetMapType(GMap.this);
        }
    }

    public class OverlayListener extends AbstractDefaultAjaxBehavior
    {
        private static final long serialVersionUID = 1L;

        @Override
        protected void respond(final AjaxRequestTarget target)
        {
            final Request request = RequestCycle.get().getRequest();

            final String overlayId = request.getRequestParameters().getParameterValue("overlay.overlayId").toString().replace("overlay", "");
            final String event = request.getRequestParameters().getParameterValue("overlay.event").toString();
            final GOverlay overlay = overlays.get(overlayId);
            if (overlay != null)
            {
                overlay.onEvent(target, GEvent.valueOf(event));
            }
        }

        public Object getJSinit()
        {
            return GMap.this.getJSinvoke("overlayListenerCallbackUrl = '" + this.getCallbackUrl() + "'");

        }
    }

	public boolean isFailSilently() {
		return failSilently;
	}

	public void setFailSilently(boolean failSilently) {
		this.failSilently = failSilently;
	}
}

 看下怎么往地图上添加标记,可以看到我们不用直接在客户端写JS,服务端操作即可:

	private GMap buildGui() {

		final EntityModel model = getModel();
		final ObjectAdapter adapter = model.getObject();
		Location l = (Location) adapter.getObject();
		GLatLng latLng = new GLatLng(l.getLatitude(), l.getLongitude());

		final boolean visible = latLng != null;

		final GMap map = new GMap(ID_MAP, apiKey);
		// map.setStreetViewControlEnabled(true);
		map.setScaleControlEnabled(false);
		map.setPanControlEnabled(false);
		map.setDoubleClickZoomEnabled(false);
		map.setZoom(17);

		if (visible) {

			// centre the map on the first object that has a location.
			map.setCenter(latLng);
		}

		addOrReplace(map);

		addMarker(map, adapter);

		return map;
	}

	private void addMarker(final GMap map, ObjectAdapter adapter) {

		ObjectAdapter dereferencedAdapter = dereference(adapter);

		final GMarker gMarker = createGMarker(map, adapter, dereferencedAdapter);
		if (gMarker != null) {
			map.addOverlay(gMarker);
			// addClickListener(gMarker, dereferencedAdapter);
		}
		List<GLatLng> glatLngsToShow = Lists.newArrayList();
		map.fitMarkers(glatLngsToShow);
	}

下边开始尝试替换相应的内容:

GMapHeaderContributor类,改成高德的接口

public class GMapHeaderContributor extends Behavior {

	private static final long serialVersionUID = 1L;
	// URL for Google Maps' API endpoint.
	private static final String GMAP_API_URL = "%s://webapi.amap.com/maps?v=1.3&key=%s";
	private static final String HTTP = "http";
	// We have some custom Javascript.
	private static final ResourceReference WICKET_GMAP_JS = new JavaScriptResourceReference(GMap.class,
			"wicket-gmap.js");

//...
}

wicket-gmap.js

//...
//地图对象的实例化
function WicketClientGeocoder() {

    this.coder = new AMap.Geocoder();

    this.getLatLng = function(callBack, addressId){
    
        var address = Wicket.$(addressId).value;
        
        this.coder.geocode({
            'address': address
        }, function(results, status){
        
            var params = {};
            if (status == AMap.GeocoderStatus.OK) {
                params['address'] = results[0].formatted_address;
                params['coordinates'] = results[0].geometry.location;
                params['status'] = status;
            }
            
            for ( var key in params) {
                callBack = callBack + '&' + key + '=' + params[key];
            }
            
            Wicket.Ajax.ajax({
                'u':callBack, 
                'ep': params
            });
        });
    }
}

//其它API有差异的地方也相应的改一下,此处略
//...

实现集合页UI适配工厂:

/*
 *  Copyright 2013~2014 Dan Haywood
 *
 *  Licensed under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package com.itisys.map.ui;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;

import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.isis.viewer.wicket.ui.CollectionContentsAsFactory;
import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
import org.apache.isis.viewer.wicket.ui.ComponentType;
import org.apache.wicket.Component;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.itisys.map.applib.AmapApplibConstants;
import com.itisys.map.applib.Locatable;

public class CollectionOfEntitiesAsLocatablesFactory extends ComponentFactoryAbstract implements CollectionContentsAsFactory {

    private static final long serialVersionUID = 1L;

    private static final String ID_MAP = "map";

    private boolean determinedWhetherInternetReachable;
    private boolean internetReachable;

    public CollectionOfEntitiesAsLocatablesFactory() {
        super(ComponentType.COLLECTION_CONTENTS, ID_MAP);
    }

    @Override
    public ApplicationAdvice appliesTo(IModel<?> model) {

        final String apiKey = getConfiguration().getString(AmapApplibConstants.API_KEY);
        if(apiKey == null) {
            return ApplicationAdvice.DOES_NOT_APPLY;
        }

        if(!internetReachable()) {
            return ApplicationAdvice.DOES_NOT_APPLY;
        }
        
        if (!(model instanceof EntityCollectionModel)) {
            return ApplicationAdvice.DOES_NOT_APPLY;
        }

        EntityCollectionModel entityCollectionModel = (EntityCollectionModel) model;

        ObjectSpecification typeOfSpec = entityCollectionModel.getTypeOfSpecification();
        ObjectSpecification locatableSpec = getSpecificationLoader().loadSpecification(Locatable.class);
        return appliesIf(typeOfSpec.isOfType(locatableSpec));
    }

    private boolean internetReachable() {
        if(!determinedWhetherInternetReachable) {
            internetReachable = isInternetReachable();
            determinedWhetherInternetReachable = true;
        }
        return internetReachable;
    }
    
    /**
     * Tries to retrieve some content, 1 second timeout.
     */
    private static boolean isInternetReachable()
    {
        try {
            final URL url = new URL("http://www.amap.com");
            final HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();
            urlConnect.setConnectTimeout(1000);
            urlConnect.getContent();
            urlConnect.disconnect();
        } catch (UnknownHostException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
        return true;
    }

    public Component createComponent(String id, IModel<?> model) {

        final String apiKey = getConfiguration().getString(AmapApplibConstants.API_KEY);

        EntityCollectionModel collectionModel = (EntityCollectionModel) model;
        return new CollectionOfEntitiesAsLocatables(id, apiKey, collectionModel);
    }

    protected SpecificationLoader getSpecificationLoader() {
        return IsisContext.getSessionFactory().getSpecificationLoader();
    }

    protected IsisConfiguration getConfiguration() {
        return IsisContext.getSessionFactory().getConfiguration();
    }

    @Override
    public IModel<String> getTitleLabel() {
        return Model.of("Map");
    }

    @Override
    public IModel<String> getCssClass() {
        return Model.of("fa fa-map-marker");
    }

}

实现实体属性UI适配:

/*
 *  Copyright 2013~2014 Dan Haywood
 *
 *  Licensed under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package com.itisys.map.ui;

import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
import org.apache.isis.viewer.wicket.ui.components.scalars.ComponentFactoryScalarAbstract;
import org.apache.wicket.Component;

import com.itisys.map.applib.AmapApplibConstants;
import com.itisys.map.applib.Location;

public class EntityAsLocatablesFactory extends ComponentFactoryScalarAbstract {

	private static final long serialVersionUID = 1L;

	private static final String ID_MAP = "map";

	public EntityAsLocatablesFactory() {
		super(EntityAsLocatables.class, Location.class);
	}

	protected SpecificationLoader getSpecificationLoader() {
		return IsisContext.getSessionFactory().getSpecificationLoader();
	}

	protected IsisConfiguration getConfiguration() {
		return IsisContext.getSessionFactory().getConfiguration();
	}

	@Override
	protected Component createComponent(String id, ScalarModel scalarModel) {
        final String apiKey = getConfiguration().getString(AmapApplibConstants.API_KEY);
		return new EntityAsLocatables(id,apiKey, scalarModel);
	}

}

 

posted @ 2017-08-13 18:58  八爻老骥  阅读(462)  评论(0编辑  收藏  举报