如何在谷歌地图上放置标记

26

我使用来自primefaces的谷歌地图工具。 我希望我的用户能够在地图上只放置一个标记。 坐标值应存储在托管的bean变量中。

我该如何做到这一点? 以下是我迄今为止所做的:

我创建了地图:

    <f:view contentType="text/html">
            <p:gmap id="gmap" center="36.890257,30.707417" zoom="13" type="HYBRID"   
    style="width:600px;height:400px"  
    model="#{mapBean.emptyModel}"   
    onPointClick="handlePointClick(event);"   
    widgetVar="map" />  </f:view>

<p:dialog widgetVar="dlg" effect="FADE" effectDuration="0.5" close="false" fixedCenter="true">  
    <h:form prependId="false">  
        <h:panelGrid columns="2">  
            <h:outputLabel for="title" value="Title:" />  
            <p:inputText id="title" value="#{mapBean.title}" />  

            <f:facet name="footer">  
                <p:commandButton value="Add"   
                        actionListener="#{mapBean.addMarker}"   
                        update="messages"   
                        oncomplete="markerAddComplete()"/>  
                <p:commandButton value="Cancel" onclick="return cancel()"/>  
            </f:facet>  
        </h:panelGrid>  

        <h:inputHidden id="lat" value="#{newOfferSupportController.mapLocationX}" />  
        <h:inputHidden id="lng" value="#{newOfferSupportController.mapLocationY}" />  
    </h:form>  
</p:dialog>  

<script type="text/javascript">  
    var currentMarker = null;  

    function handlePointClick(event) {  
        if(currentMarker == null) {  
            document.getElementById('lat').value = event.latLng.lat();  
            document.getElementById('lng').value = event.latLng.lng();  

            currentMarker = new google.maps.Marker({  
                position:new google.maps.LatLng(event.latLng.lat(), event.latLng.lng())  
            });  

            map.addOverlay(currentMarker);  

            dlg.show();  
        }     
    }  

    function markerAddComplete() {  
        var title = document.getElementById('title');  
        currentMarker.setTitle(title.value);  
        title.value = "";  

        currentMarker = null;  
        dlg.hide();  
    }  

    function cancel() {  
        dlg.hide();  
        currentMarker.setMap(null);  
        currentMarker = null;  

        return false;  
    }  
</script>

我还创建了将保存坐标的变量:

@ManagedBean
@RequestScoped
public class NewOfferSupportController {

private float mapLocationX;
private float mapLocationY;

//Get & set methods

我做的所有事情都跟primefaces官方网站上这个页面一样,但是我遇到了两个问题:

问题1:放置标记后,就不能再次放置。

问题2:在同一个表单中有一些其他元素,比如文本框。当我点击位于地图所在表单中的提交按钮时,我注意到验证不会发生,实际上表单根本没有被提交(在添加地图之前没有出现过这种情况)。为什么地图会干扰验证? enter image description here


2
似乎 document.getElementById('lat') 返回了 null,你能在 HTML 源代码中看到是否有这个 ID 的元素吗? - jmj
是的,保持两个名称不同,我也不理解嵌套对话框的必要性。 - jmj
我想把地图做成一个弹出式对话框。我刚下定决心,就移除了弹出式对话框,现在它正常工作。但是一旦我放置了标记,我就不能再次放置它。我该怎么做? - javing
可能的问题是由于这些丢失的 .js 文件,你可以把它提供给页面吗? - jmj
是的,我认为那就是我使用的。 - javing
显示剩余17条评论
1个回答

6

问题 1:一旦标记放置,就无法再次放置。

这个问题的原因如下:

  1. You've bound latitude and longitude to a different bean (NewOfferSupportController) than the bean which holds the map model (MapBean). You should be using MapBean example in the PrimeFaces showcase as design starting point for NewOfferSupportController bean. It namely stores the markers set. The hidden inputs must point to that bean because in the addMarker() method those values will be added. From the showcase example you just have to rename the MapBean class name and rename #{mapBean} references in the view by #{newOfferSupportController}.

  2. Your NewOfferSupportController bean is request scoped while it should be view scoped.

    @ManagedBean
    @ViewScoped
    public class NewOfferSupportController implements Serializable {}
    

    View scoped beans live as long as you're interacting with the same form by Ajax. But request scoped beans get recreated on every request (and thus also on every Ajax request!), hereby trashing the markers which are placed before in the map and inputs which are entered before adding markers.


问题2:在同一个表单中,除了地图外还有其他元素,例如文本字段。实际上,该表单根本没有被提交(在添加地图之前没有发生过这种情况),为什么地图会破坏验证?

这对我有效。这可能是由于您的NewOfferSupportController被放置在请求范围而不是视图范围所致。

简而言之,以下是我在测试中使用的代码:

视图:

<p:growl id="messages" showDetail="true" />  

<h:form>
    <p:gmap id="gmap" center="36.890257,30.707417" zoom="13" type="HYBRID" style="width:600px;height:400px"  
        model="#{mapBean.mapModel}" onPointClick="handlePointClick(event);" widgetVar="map" />
    <h:inputText value="#{mapBean.input}" required="true" />
    <p:commandButton value="submit" action="#{mapBean.submit}" update="messages" />
</h:form>

<p:dialog widgetVar="dlg" effect="FADE" effectDuration="0.5" close="false" fixedCenter="true">  
    <h:form prependId="false">  
        <h:panelGrid columns="2">  
            <h:outputLabel for="title" value="Title:" />  
            <p:inputText id="title" value="#{mapBean.title}" />  

            <f:facet name="footer">  
                <p:commandButton value="Add" actionListener="#{mapBean.addMarker}"   
                    update="messages" oncomplete="markerAddComplete()"/>  
                <p:commandButton value="Cancel" onclick="return cancel()"/>  
            </f:facet>
        </h:panelGrid>

        <h:inputHidden id="lat" value="#{mapBean.lat}" />  
        <h:inputHidden id="lng" value="#{mapBean.lng}" />
    </h:form>  
</p:dialog>  

(在展示示例中,我没有更改<script>代码,只是未经修改地添加了它)

Bean:

@ManagedBean
@ViewScoped
public class MapBean implements Serializable {  

    private MapModel mapModel;  
    private String title;  
    private double lat;  
    private double lng;  
    private String input;

    public MapBean() {  
        mapModel = new DefaultMapModel();  
    }  

    public void addMarker(ActionEvent actionEvent) {  
        mapModel.addOverlay(new Marker(new LatLng(lat, lng), title));  
        addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO, "Marker Added", "Lat:" + lat + ", Lng:" + lng));  
    }  

    public void submit() {
        addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO, "Form submitted", "Amount markers: " + mapModel.getMarkers().size() + ", Input: " + input));
    }

    public void addMessage(FacesMessage message) {  
        FacesContext.getCurrentInstance().addMessage(null, message);  
    }  

    // Getters+setters.
}

我明白了。我现在会尝试修复它。 - javing
我刚刚修好了。现在它很好。跟着你的指示解决了问题1和2,并重构了页面中不需要的内容。一个多月以来,我一直不知道如何修复它。非常感谢你 :) - javing
不用谢。感谢悬赏。我一开始没有回答是因为我以前从未使用过<p:gmap>(所以我无法立即回答),而且我也觉得自己测试它不值得花费精力。 - BalusC
感谢那位为我的问题提供赏金的人 :) 这也是我第一次使用 p:gmap,之前一直在考虑寻找替代方案,但它确实很好用,问题也得以解决。我很高兴终于让这个 primefaces 工具按照我期望的方式工作了 :) - javing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接