Google 地图 API V3 在聚合物元素内部不工作

Google Map API V3 not working inside polymer-element

我创建了聚合物元素并在其中添加了 Google 地图。如果我将聚合物元素的代码直接写入我想使用它的主文件中,它可以正常工作,但是如果我将它的代码保存在单独的文件中并通过导入使用它,那么它会在控制台中给出以下错误:

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

这里是我的-map.html文件的代码:

<link rel="import" href="bower_components/polymer/polymer.html">
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<polymer-element name="my-map">
        <template>
            <style type="text/css">
            :host{
                display: block;
            }
                #mapCanvas {
            height: 100%;
            margin: 0px;
            padding: 0px;
          }
            </style>
            <div id="mapCanvas"></div>
        </template>
        <script type="text/javascript">
            Polymer({
                map:null,
                ready:function(){

                    this.map = new google.maps.Map(this.$.mapCanvas, {
                    center: new google.maps.LatLng(41, -91),
                    disableDefaultUI: true,
                    zoom: 5
                     });
                }
            });
        </script>
    </polymer-element>

这是主文件的代码 index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My Map</title>

    <script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
    <link rel="import" href="my-map.html">
</head>
<body>
<my-map style="height:500px,width:500px;"></my-map>
</body>
</html>

问题出在哪里? 如果我在 index.html 文件中编写我的-map.html 文件的代码,那么它工作完美。

粗略的文件结构:

  • 文件:index.html
  • 文件:我的-map.html
  • 目录:bower_components/
    • 目录:核心组件页面/...
    • 目录:聚合物/...
    • 目录:webcomponentsjs/...

当 google-maps 库包含在聚合物元素的定义之上时,google-maps 似乎无法在聚合物元素上构建地图,可以 one/several 原因归咎于此。但至少有两种解决方案对我有用。

第一个解

尝试从您的聚合物元素中排除 google-maps 库并将其包含到您的 index.html 文件中:

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My Map</title>
    <!-- include google maps lib into your main index.html file -->
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
    <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="my-map.html">
</head>
<body>
    <my-map width="500px" height="500px"></my-map>
</body>
</html>

聚合物元素(my-map.html):

<link rel="import" href="bower_components/polymer/polymer.html">
<polymer-element name="my-map" attributes="width height">
    <template>
        <style type="text/css">
            :host{
                display: block;
            }
            #mapCanvas {
                margin: 0px;
                padding: 0px;
            }
        </style>
        <div id="mapCanvas" style="width:{{width}};height:{{height}}"></div>
    </template>
    <script>
        Polymer({
            map:null,
            width: '100px',// default width
            height: '100px',// default height
            ready:function(){

                // map canvas lies within shadow-dom so it not accessible by ordinary *querySelector*, *querySelectorAll* or *getElementById* methods but this is a way: this.$.mapCanvas 
                this.map = new google.maps.Map(
                                this.$.mapCanvas,
                                { center: new google.maps.LatLng(41, -91),
                                  disableDefaultUI: true,
                                  zoom: 5
                                }
                );
            }
        });
    </script>
</polymer-element>

第二种解法:

尝试使用 google 地图库的回调参数(url-部分:&callback=callback)并包含 google 地图库进入聚合物元素的定义:

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My Map</title>
    <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="my-map.html">
</head>
<body>
    <!-- use default width/height -->
    <my-map></my-map>
</body>
</html>

聚合物元素(my-map.html):

<link rel="import" href="bower_components/polymer/polymer.html">
<polymer-element name="my-map" attributes="width height">
    <template>
        <style type="text/css">
            :host{
                display: block;
            }
            #mapCanvas {
                margin: 0px;
                padding: 0px;
            }
        </style>
        <div id="mapCanvas" style="width:{{width}};height:{{height}}"></div>
    </template>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&callback=callback"></script>
    <script>

        // use IIFE to encapsulate all defined variables to prevent them from being assigned to window object unintentionally
        (function(){

            var googleMapsReady = false;

            var myMapPolymer;
            var htmlCanvasMap;

            function callback(){

                googleMapsReady = true;

                if(htmlCanvasMap){
                    buildUpMap(htmlCanvasMap);
                }

            }
            // !!! unfortunately you have to assign callback function to window object
            // because this function has to be accessible globally  otherwise google maps lib will not find it and throws an error
            window.callback = callback;

            // function to show a google map on your site that takes a html element on which a map should be shown
            function buildUpMap(htmlmap){

                var map = new google.maps.Map(
                                    htmlmap,
                                    { center: new google.maps.LatLng(38, -91),
                                      disableDefaultUI: true,
                                      zoom: 8
                                    }
                );

                // at last assign google map object as property to polymer element
                myMapPolymer.map = map;

            }

            // polymer element code definition
            Polymer({
                map:null,
                width: '100px',// default width
                height: '100px',// default height
                ready:function(){

                    myMapPolymer = this;

                    // assign map canvas(div) to varible in order to use it for building up a map, 
                    htmlCanvasMap = this.$.mapCanvas;

                    if(googleMapsReady){
                        buildUpMap(htmlCanvasMap);
                    }

                }
            });

        })();

    </script>
</polymer-element>

在第二种解决方案中,仍有机会将初始化的 google 地图对象作为 属性 分配给聚合物元素:

  • 变量 googleMapsReady 在 google 地图加载并准备好使用时设置 [=42] =]Polymer.ready函数。

  • 否则,如果 Polymer.readycallback 之前调用,则变量 htmlCanvasMap 已分配,因此在 callback 函数中检查时 true

希望对您有所帮助。