Javascript AngularJS+;阿尔吉斯

Javascript AngularJS+;阿尔吉斯,javascript,angularjs,dojo,arcgis,arcgis-js-api,Javascript,Angularjs,Dojo,Arcgis,Arcgis Js Api,我尝试在一个角度应用程序中使用。如我所见,它使用Dojo。因此,我尝试从Angular指令初始化ArcGIS,如下所示: link: function (scope, element, attrs) { dojo.require('esri.map'); var init = function () { console.log('dojo is ready'); var map = new esri.Map("map-container", {

我尝试在一个角度应用程序中使用。如我所见,它使用Dojo。因此,我尝试从Angular指令初始化ArcGIS,如下所示:

  link: function (scope, element, attrs) {
    dojo.require('esri.map');
    var init = function () {
      console.log('dojo is ready');
      var map = new esri.Map("map-container", {
        center: [-111.3797, 56.7266 ],
        zoom: 16,
        basemap: "streets"
      });
      map.enableScrollWheelZoom()

    };
    dojo.addOnLoad(init);
  }
看起来这种方式不是100%正确的,因为当我尝试通过滚动鼠标滚轮进行缩放时,会出现以下错误:

Uncaught TypeError: Cannot call method 'apply' of null 

我的问题是,如何在Angular应用程序中正确地注入ArcGIS功能?

看起来您正试图在指令元素中构建地图。这是一个合法的使用,但我会确保你使用的AMD装载机的Dojo加载你的模块,然后你的Angular应用程序后,所有的Dojo善良是准备好的

我最近写了一篇关于Angular/Esri dev的文章,可以找到一个示例项目的源代码

我实际上是从一个控制器构建映射,但是这个过程应该类似于在指令中构建它

define([
    'angular',
    'esri/map'
], function(angular, Map) {
    function mapConfigs() {
        return {
            basemap: 'streets',
            center: [-118.1704035141802,34.03597014510993],
            zoom: 15
        };
    }
    function mapGen(elem) {
        return new Map(elem, mapConfigs());
    }
    function AppController($scope) {
        $scope.map = mapGen('map');
    }
    function init(App) {
        App.controller('AppCtrl', ['$scope', AppController]);
        return AppController;
    }
    return { start: init };
});
在引导Angular应用程序之前,我使用引导模块使用Esri/Dojo位构建所有角度位

define([
    'angular',
    'controllers/AppController',
    'widgets/search/SearchBootstrap'
], function(angular, AppController, SearchBootstrap) {
    function init() {
        var App = angular.module('app', ['ui.bootstrap']);
        AppController.start(App);
        SearchBootstrap.start(App);
        // need to bootstrap angular since we wait for dojo/DOM to load
        angular.bootstrap(document.body, ['app']);
        return App;
    }
    return { start: init };
});

希望这能有所帮助。

我认为一个非常“AngularJS”风格的方法应该如下所示。(在这里拉小提琴)

我喜欢使用
angular ui路由器
,但这种方法也适用于angular的
$routeProvider
。这里的魔力在于resolve对象,它可以选择“等待”直到承诺得到解决,然后再继续

angular.module('webApp', ['ui.router'])
    // module (app) config
    .config(function ($stateProvider, $urlRouterProvider) {

        $urlRouterProvider.otherwise('/map');

        $stateProvider.state('map', {
            url: '/map',
            template: '<div id="map"></div>',
            controller: 'MapCtrl',
            resolve: {
                promiseObj: function ($q, $rootScope, wish) {
                    var deferred = $q.defer(),
                        deps = {
                            Map: 'esri/map',
                            FeatureLayer: 'esri/layers/FeatureLayer',
                            InfoTemplate: 'esri/InfoTemplate',
                            SimpleFillSymbol: 'esri/symbols/SimpleFillSymbol',
                            SimpleRenderer: 'esri/renderers/SimpleRenderer',
                            SimpleMarkerSymbol: 'esri/symbols/SimpleMarkerSymbol',
                            ScaleDependentRenderer: 'esri/renderers/ScaleDependentRenderer',
                            Color: 'dojo/_base/Color'
                        };

                    wish.loadDependencies(deps, function () {
                        deferred.resolve();
                        if (!$rootScope.$$phase) {
                            $rootScope.$apply();
                        }
                    });

                    return deferred.promise;
                }
            }
        });
    });
之后,在
MapCtrl
中,您可以直接调用所有ArcGIS/Dojo FN(正常情况下),方法是使用在app config期间构造的
deps
对象中使用的键,因为它们现在连接到
wish.get()返回的对象

下面是此处示例的修改版本()

angular.module('webApp')
//我们的地图控制器
.controller('MapCtrl',函数($rootScope,$scope,wish){
var w=wish.get(),
绿色填充=新的w颜色([133197133,0.75]),
绿色轮廓=新的w颜色([133197133,0.25]),
层,
markerSym,
渲染器1,
渲染器2,
农作物http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/USA_County_Crops_2007/FeatureServer/0';
$scope.map=new w.map('map'{
中心:[-98.579,39.828],
缩放:4,
底图:“灰色”
});
图层=新的w.FeatureLayer(作物\u URL{
外场:[“州”、“县”、“M086_07”、“地区”],
infoTemplate:new w.infoTemplate(“${country},${STATE}”,“代表农田的县面积百分比为${M086_07}%”)
});
layer.setDefinitionExpression('AREA>0.01和M086_07>0');
markerSym=新的w.SimpleMarkerSymbol();
标记符号setColor(绿色填充);
markerSym.setOutline(markerSym.outline.setColor(greenOutline));
Render1=新的w.SimpleRenderer(markerSym);
Render1.SetProgressionalSymbolInfo({
字段:“M086_07”,
minSize:1,
最大尺寸:10,
minDataValue:0,
maxDataValue:100
});
//对于第二个渲染器,增加点大小并设置backgroundFillSymbol
Render2=新的w.SimpleRenderer(markerSym);
Renderr2.SetProgressionalSymbolInfo({
字段:“M086_07”,
minSize:5,
最大尺寸:15,
minDataValue:0,
maxDataValue:100
});
layer.setRenderer(新的w.ScaledPendenderer({
渲染器信息:[{
“渲染器”:渲染器1,
“minScale”:50000000,
“最大规模”:10000000
}, {
“渲染器”:渲染器2,
“minScale”:0,
“最大规模”:5000000
}]
}));
$scope.map.addLayer(层);
});

working fiddle演示了上面的代码,可以在这里找到

我喜欢你的解决方案,但我有一个小问题。我正在使用angular translate,从“//js.arcgis.com/3.14”加载init.js需要一秒钟的时间,这导致angular translate显示为{{'something'| translate}},而不是呈现的文本,直到加载init.js才能加载'require'。你知道在wish服务中删除require依赖项的方法吗?我会通过预加载或“数据加载”标志在你的UI中处理这个问题。一个相当不错的问题解释和可能的解决方案在这里谢谢,我会试试这个。
angular.module('webApp')
     // service that deals w/ our dojo require
    .service('wish', function () {

        // it's not require... it's a wish?
        var wish = {};

        function _loadDependencies(deps, next) {
            var reqArr = _.values(deps),
                keysArr = _.keys(deps);

            // use the dojo require (required by arcgis + dojo) && save refs
            // to required obs
            require(reqArr, function () {
                var args = arguments;

                _.each(keysArr, function (name, idx) {
                    wish[name] = args[idx];
                });

                next();
            });
        }

        return {
            loadDependencies: function (deps, next) {
                _loadDependencies(deps, next);
            },

            get: function () {
                return wish;
            }
        };
    });
angular.module('webApp')
    // our map controller
    .controller('MapCtrl', function ($rootScope, $scope, wish) {

        var w = wish.get(),
            greenFill = new w.Color([133, 197, 133, 0.75]),
            greenOutline = new w.Color([133, 197, 133, 0.25]),
            layer,
            markerSym,
            renderer1,
            renderer2,

            CROPS_URL = 'http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/USA_County_Crops_2007/FeatureServer/0';

        $scope.map = new w.Map('map', {
            center: [-98.579, 39.828],
            zoom: 4,
            basemap: 'gray'
        });

        layer = new w.FeatureLayer(CROPS_URL, {
            outFields: ['STATE', 'COUNTY', 'M086_07', 'AREA'],
            infoTemplate: new w.InfoTemplate('${COUNTY}, ${STATE}', '<div style="font: 18px Segoe UI">The percentage of the area of the county that represents farmland is <b>${M086_07}%</b>.</div>')
        });
        layer.setDefinitionExpression('AREA>0.01 and M086_07>0');


        markerSym = new w.SimpleMarkerSymbol();
        markerSym.setColor(greenFill);
        markerSym.setOutline(markerSym.outline.setColor(greenOutline));
        renderer1 = new w.SimpleRenderer(markerSym);
        renderer1.setProportionalSymbolInfo({
            field: 'M086_07',
            minSize: 1,
            maxSize: 10,
            minDataValue: 0,
            maxDataValue: 100
        });

        //for the second renderer increase the dot sizes and set a backgroundFillSymbol
        renderer2 = new w.SimpleRenderer(markerSym);
        renderer2.setProportionalSymbolInfo({
            field: 'M086_07',
            minSize: 5,
            maxSize: 15,
            minDataValue: 0,
            maxDataValue: 100
        });

        layer.setRenderer(new w.ScaleDependentRenderer({
            rendererInfos: [{
                'renderer': renderer1,
                    'minScale': 50000000,
                    'maxScale': 10000000
            }, {
                'renderer': renderer2,
                    'minScale': 0,
                    'maxScale': 5000000
            }]
        }));

        $scope.map.addLayer(layer);
    });