2016-09-13 2 views
2

У меня есть веб-сайт, который должен отображать различные данные на карте. Карта всегда будет одинаковой - некоторые области с эффектом «onhover» и всплывающей подсказкой.AngularJS - Огромная директива

Существует около 10 различных наборов данных.

Я создал директиву для отображения карты

Директиву (только нарисовать карту)

angular.module('PluvioradApp.controllers') 
    .directive('map', function() { 
     return { 
      restrict: 'E', 
      link: function(scope, element, attrs) { 
       var svg = d3.select(element[0]) 
        .append("div") 
        .classed("svg-container", true) //container class to make it responsive 
        .append("svg") 
        //responsive SVG needs these 2 attributes and no width and height attr 
        .attr("preserveAspectRatio", "xMinYMin meet") 
        .attr("viewBox", "0 0 1000 500") 
        //class to make it responsive 
        .classed("svg-content-responsive", true); 

       var g = svg.append("g"); 

       //Scale/translate/... 
       var lineFunction = d3.svg.line() 
        .x(function(d) { return (d[0]+50000)/500; }) 
        .y(function(d) { return (-d[1]+170000)/500; }) 
        .interpolate("linear"); 

       //Draw map 
       var path = g.selectAll('path') 
        .data(data.areas) 
        .enter().append("path") 
        .attr("d", function(d){ return lineFunction(d.borders)}) 
        .attr("fill", "#D5708B") 
        .on('mouseover', function(d) { 
         d3.select(this).style('fill', 'orange'); 
         d3.select(this).text(function(d){return "yeah";}) 
        }) 
        .on('mouseout', function(d) { 
         g.selectAll('path').style('fill', '#D5708B'); 
        });    


       // zoom and pan 
       var zoom = d3.behavior.zoom() 
        .on("zoom", function() { 
         g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
         g.selectAll("path") 
          .attr("d", function(d){ return lineFunction(d.borders)}); 
        }); 

       svg.call(zoom); 

      } 
     } 
    }); 

Моя идея состояла в том, чтобы получить данные для отображения из контроллера (это происходит от API) и отправить его в директиву. Внутри указанной директивы я добавлю большой switch или несколько if, чтобы отобразить правильные данные с правильными цветами, размером, ...

Я уверен, что есть другой способ разделить работу.

Например:

  • первая директива для отображения карты. Можно повторно использовать несколько часовых
  • 2-й директивы, чтобы отобразить набор 1
  • третья директива, чтобы отобразить набор 2

Если это правильный путь, как я могу добиться этого?

Дополнительная информация

У меня есть меню с выпадающего меню, чтобы выбрать, какие данные будут отображаться. На данный момент, пункты перенаправления на страницу, содержащую директиву карты выше

+0

Можете ли вы привести несколько примеров ваших наборов данных? – LkPark

+0

Например, одним из наборов данных будет список координат, каждый из которых содержит разные значения. Это будут маркеры на карте с ярлыками, показывающими значения. Другой набор данных также представляет собой список координат со значениями, которые будут отображаться как цветные пиксели на карте (например, облако) – Weedoze

ответ

1
  1. Имейте папку, в которой вы будете иметь кучу услуг, где каждая служба будет один из набора данных. Set1Service, Set2Service. и т. д. Каждый из них будет иметь собственную логику.

  2. Имейте заводское обслуживание, которое вернет вам одно из ваших услуг. например:

    (новый FactoryService()) -> get ('dataSetItem'); // это вернет одну из услуг из пункта 1.

  3. Inject FactoryService в вас директива его использует.

  4. В фабрике вы будете иметь логику как разобрать свой набор данных, чтобы определить, какие DataSetService вам придется вернуться

Это расширяемый простой в использовании.

Все, что я описал, больше связано с шаблоном стратегии и фабрики, вы можете узнать больше об этом, и это поможет вам получить более абстрактную реализацию.

angular.module('PluvioradApp.controllers') 
 
    .directive('map', function(factoryService) { 
 
     return { 
 
      restrict: 'E', 
 
      scope: { 
 
       dataSet: '=' 
 
      } 
 
      link: function(scope, element, attrs) { 
 
       //all your code 
 
       var dataSetService = factoryService.get(scope.dataset); 
 
      
 
       var result = dataSetService.seed(d3); 
 

 
      } 
 
    }).service('factoryService', function() { 
 
     
 
     this.get = function(name) { 
 
      var service = null; 
 
      switch (name) { 
 
       case 'set1' 
 
       service = new DataSet1(); 
 
       break; 
 
       case 'set2' 
 
       service = new DataSet2(); 
 
       break; 
 
      } 
 
      return service; 
 
     } 
 
    }); 
 
      
 
     
 
       
 
    function DataSet1() { 
 
      
 
    }   
 
    DataSet1.prototype.seed = function(d3) { 
 
     //d3 logic you have access here; 
 
    } 
 
       
 
    function DataSet2() { 
 
      
 
    } 
 
       
 
    DataSet2.prototype.seed = function(d3) { 
 
     //d3 logic you have access here; 
 
    } 
 
      

+0

Но все мои наборы данных должны отображаться по-разному, и я не могу использовать D3.js внутри Service. Мне нужна директива для этого – Weedoze

+0

Все эти Службы используются только для подготовки данных, вы можете ввести свой D3 и использовать его. Вы можете делать то, что хотите. Это просто абстрактное представление о вашей проблеме, конкретная реализация зависит от вас, какие данные вы будете передавать и какая зависимость у вас будет. – LkPark

+0

Обновить ответ - абстрактный пример. – LkPark

Смежные вопросы