Durandal Google地图无法正常显示

时间:2014-05-26 12:36:01

标签: javascript google-maps knockout.js durandal

尝试使用Durandal显示Google地图。我现在只是简单地使用Durandal HTML Starter Kit,因此其他模块和所有引擎都能正常工作。问题是,当我添加谷歌地图时,它不适合div大小(div的大部分只是灰色)。据我了解,问题是由于谷歌地图在页面完全加载之前添加了。但我无法弄清楚如何挂钩页面加载事件。这是模块代码:

define(['knockout', 'gmaps'], function (ko, gmaps) {

    return {
        displayName: 'Google Maps',
        myMap: ko.observable({
            lat: ko.observable(32),
            lng: ko.observable(10)}),

        activate: function () {
            console.log('activate');
            ko.bindingHandlers.map = {

                init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                    console.log('init');
                    var mapObj = ko.utils.unwrapObservable(valueAccessor());

                    var latLng = new gmaps.LatLng(
                        ko.utils.unwrapObservable(mapObj.lat),
                        ko.utils.unwrapObservable(mapObj.lng));

                    var mapOptions = { center: latLng,
                        zoom: 5,
                        mapTypeId: gmaps.MapTypeId.ROADMAP};

                    mapObj.googleMap = new gmaps.Map(element, mapOptions);
                }
            }
        },

        attached: function() {
            console.log('attached');

        },

        compositionComplete: function()
        {
            console.log('compositionComplete');


        }

    };


});

一个非常简单的HTML代码:

<section>
    <div id="gmap-canvas" data-bind="map:myMap"></div>
</section>

我在我的shell.js中使用异步插件加载Google地图。它工作正常。 屏幕截图有问题 - 已移除违规链接

P.S。 div大小在.CSS文件中定义。

P.S。我尝试使用here提供的getElementById方法,如果置于 compositionComplete 块中,它的工作效果很好。但是当我试图将我的绑定移动到这个块时,根本没有任何事情发生。

谢谢!

5 个答案:

答案 0 :(得分:0)

我们使用谷歌地图,它的工作正常。

执行以下操作:

  • 将绑定移动到bindings.js文件,并将绑定放在init()函数中,确保在对象文字中返回init; bindings.js只包含一个单独的模块,我们称之为“绑定”(你可以随意调用它)
  • 确保您的要求路径中有asyncpropertyParsergoog
  • 在main.js中,调用bindings.init()初始化绑定

关于asyncpropertyParsergoog,它们应该与此类似:

requirejs.config({
     paths: {        
        'async': '../Scripts/plugins/async',
        'propertyParser': '../Scripts/plugins/propertyParser',
        'goog': '../Scripts/plugins/goog',
    }
});

注意:可以找到三个插件 - asyncpropertyParsergoog - here

在main.js中启动应用程序的功能之前,您还应该在配置路径之后或多或少地拥有此功能(如上所示):

define('gmaps', ['async!http://maps.google.com/maps/api/js?sensor=false'],
function () {
    // return the gmaps namespace for brevity
    return window.google.maps;
});

那应该让你离开。

附加说明:无论您使用地图做什么,都不应该在Durandal viewModel中至少attached处理程序之前执行此操作。

[编辑]对代码审核的回应

让我们一点一点地解决这个问题:

  1. 在RequireJS propertyParser对象上颠倒googconfig 路径定义的顺序;
  2. 路径定义中删除knockout并将其放在main.js中的gmaps定义之前,并为jQuery执行相同操作
  3. 删除“v = 3&amp;”来自您的gmaps define;
  4. 我怀疑你的viewModel上myMap的可观察定义。我不明白为什么myMap本身需要被观察到。但是,我显然,它的两个属性是可观察的。删除myMap;
  5. 上的外部可观察对象

    在上面的#2上,您应该在gmaps之前的main.js中定义以下内容:

    define('jquery', function() { return jQuery; });
    define('knockout', ko);
    

    我认为这是你闯入Durandal框架的地方。

答案 1 :(得分:0)

当映射绑定的div隐藏在viewmodel激活时,我遇到了这个问题。快速解决方法是通过api调用来调整地图大小:

  

当div更改时,开发人员应在地图上触发此事件   尺寸:google.maps.event.trigger(地图,&#39;调整大小&#39;)

来自https://developers.google.com/maps/documentation/javascript/reference?csw=1

您可以在KO自定义绑定中执行此调用,以便在div可见时调用更新时的api。

希望这有帮助。

答案 2 :(得分:0)

   map = new google.maps.Map(document.getElementById(element.getAttribute('id')), mapOptions);

         function googleMap() {
         google.maps.event.trigger(map, 'resize');
         map.setCenter(new google.maps.LatLng(value.centerLat, value.centerLon));
  }

然后你可以拨打googleMap

答案 3 :(得分:0)

这里的快速解决方法是等待页面完全加载,然后启动Google Map div或其他任何内容。要快速测试,只需将初始化地图的所有逻辑移动到compositionComplete回调 -

compositionComplete: function()
{
    // Initialize your stuff here
}

如果(何时)符合您的目的,请仔细查看您的绑定处理程序正在做什么,并决定实际应该去哪里。我不认为它应该在当前位置注册,因为bindingHandlers一旦注册就可以通过ko.在全球范围内使用。一旦实例化ViewModel,您就不希望每次重新注册它。

答案 4 :(得分:0)

我明白了。我不会争辩说问题出在我在durandal的小经验中,但解决方案如下: 使用composition.addBindingHandler进行延迟绑定。我想澄清一下 - 地图调整大小的方法对我不起作用。这是我的gmap.js:

define(['knockout', 'gmaps', 'durandal/composition'], function (ko, gmaps, composition) {
    composition.addBindingHandler('googleMap', {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var mapObj = ko.utils.unwrapObservable(valueAccessor());

            var latLng = new gmaps.LatLng(37.774107,-122.420853);
            //  ko.utils.unwrapObservable(mapObj.lat),
            //  ko.utils.unwrapObservable(mapObj.lng));

            var mapOptions = {
                center:latLng,
                zoom: 5,
                mapTypeId: gmaps.MapTypeId.ROADMAP};

            mapObj.googleMap = new gmaps.Map(element, mapOptions);

        }
    });

    return {
        displayName: 'Map',
        map:ko.observable({}),
        activate: function()
        {
            console.log('activate');
        }
    }

});

这是我的gmap.html:

<section>
    <h2 data-bind="html: displayName"></h2>
    <div id="gmap-canvas" data-bind="googleMap:map"></div>
</section>

以下是我在main.js中加载Google地图的方式:

requirejs.config({
    paths: {
        'text':          '../lib/require/text',
        'async':         '../lib/require/plugins/async',
        'propertyParser':'../lib/require/plugins/propertyParser',
        'goog':         '../lib/require/plugins/goog',
        'durandal':      '../lib/durandal/js',
        'plugins' :      '../lib/durandal/js/plugins',
        'transitions' :  '../lib/durandal/js/transitions',
        'bootstrap':     '../lib/bootstrap/js/bootstrap',
        'knockout':      '../lib/knockout/knockout-2.3.0'
    }
});

define('jquery', ['../lib/jquery/jquery-1.9.1'], function() { return jQuery; });

define('gmaps', ['async!http://maps.google.com/maps/api/js?sensor=false'],
    function(){
        console.log('Google maps loaded');
        return window.google.maps;
    });

define(['durandal/system', 'durandal/app', 'durandal/viewLocator'],  function (system, app, viewLocator) {
    //>>excludeStart("build", true);
    system.debug(true);
    //>>excludeEnd("build");
...

谢谢大家的帮助!