如何扩展L.Control.Layers添加自定义过滤器,这是一个很好的方法吗?

时间:2014-01-03 11:35:46

标签: javascript user-controls leaflet

我在地图上有标记,代表工人/工人组和任务/任务组。 每个工人都有一份技能清单,每项任务都需要一项技能。

我希望能够切换所有工作人员或任务的显示(使用L.featureGroup()L.control.layers()轻松完成)但我还希望过滤当前的技能显示。< / p>

我所说的“当前显示”是指如果我决定隐藏工人并且只显示任务,当我为一种技能切换显示时,我不希望具有该技能的工人出现。< / p>

这意味着我无法使用常规featureGroup和常规controlLayer来执行此操作,因为它无法在show / hide上执行过滤/应用条件。它要么显示组中的每个标记,要么全部隐藏它们。

我很想分叉Control.Layers并为它添加一些基于回调的逻辑,但我想知道是否有更好的方法呢?

修改

// Backbone stuff
var WorkerModel = Backbone.Model.extend({});
var TaskModel = Backbone.Model.extend({});
var WorkersCollection = Backbone.Collection.extend({
    model: WorkerModel
});
var TasksCollection = Backbone.Collection.extend({
    model: TaskModel
});

var workersData = [{
    id: 1,
    name: 'Bob',
    marker: L.marker(new L.LatLng(45,3)),
    coordinates: {
        lat: 45,
        lng: 3
    },
    skills: {
        skillA: {
            name: 'Foo',
            level: 1
        },
        skillB: {
            name: 'Bar',
            level: 7
        },
    }
}, {
    id: 2,
    name: 'John',
    marker: L.marker(new L.LatLng(48,2)),
    coordinates: {
        lat: 48,
        lng: 2
    },
    skills: {
        skillA: {
            name: 'Foo',
            level: 4
        }, 
        skillD : {
        name: 'Zop',
        level: 3
        }
    }
}];

var tasksData = [{
    id: 1,
    requiredSkill: 'skillA',
    requiredLevel: 5,
    duration: '5',
    marker: L.marker(new L.LatLng(50,2)),
    coordinates: {
        lat: 50,
        lng: 2
    }
}, {
    id: 2,
    requiredSkill: 'skillB',
    requiredLeve: 2,
    duration: '1',
    marker: L.marker(new L.LatLng(47,3)),
    coordinates: {
        lat: 47,
        lng: 3
    }
}];

var workers = new WorkersCollection(workersData);
var tasks = new TasksCollection(tasksData);

// We get all the markers that relates to a workers or a tasks with the skillA
var workersMarkerWithSkillA = workers.chain().filter(worker) { 
    return worker.get('skills').has('skillA'); 
}).map(function(worker) { 
    return worker.get('marker');
}).value();

var tasksMarkerWithSkillA = tasks.chain().filter(worker) { 
    return worker.get('skills').has('skillA'); 
}).map(function(worker) {
    return worker.get('marker');
}).value();

var markersWithSkillA = _.concat(workersMarkerWithSkillA, tasksMarkerWithSkillA);


// Same thing with skillB
var workersMarkerWithSkillB = workers.chain().filter(worker) { 
    return worker.get('skills').has('skillB'); 
}).map(function(worker) { 
    return worker.get('marker');
}).value();

var tasksMarkerWithSkillB = tasks.chain().filter(worker) { 
    return worker.get('skills').has('skillB'); 
}).map(function(worker) {
    return worker.get('marker');
}).value();

var markersWithSkillB = _.concat(workersMarkerWithSkillB, tasksMarkerWithSkillB);


// Make the map
var map = L.map('map');
var tileLayer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="http://openstreetmap.org/">OpenStreetMap</a> contributors' });
map.addLayer(tileLayer);

// Make the layers
var workersLayer = new L.featureGroup(workers.pluck('marker'));
var tasksLayer = new L.featureGroup(taskLayer.pluck('marker'));
var skillALayer = new L.featureGroup(markersWithSkillA);
var skillBLayer = new L.featureGroup(markersWithSkillB);

// Then we add everything on the map
var controlLayer = L.control.layers(null, [workersLayer, tasksLayer, markersWithSkillA, markersWithSkillB]);
controlLayer.addTo(map);

1 个答案:

答案 0 :(得分:0)

我最终按计划分配了Control.Layers,但对它做了很少的改动。我只是在它生成的HTML中添加了一个占位符部分。

然后,我在Backbone Marionette应用程序中构建FilterModule。该模块的区域将是我之前定义的占位符,并且过滤机制由模块中的函数完成,这很好,因为它实际上取决于我显示的数据,而不是真正用于显示它的地图。

这并不完全令人满意,因为它意味着将App硬连接到一些Leaflet部件的分叉版本,但是fork的变化很小,这不是什么大不了的事情,另外,在Backbone方面,它实际上只是要更改DOM#id,视图会显示在其他位置。

您可能想知道为什么我不是简单地在视图中添加新元素而不是填充原始Control.Layers的HTML,这会阻止我所描述的耦合。这只是因为根据显示的数据我可能有0到20个过滤器,并且它创建的定位问题不值得。目标也是让这些过滤器靠近原生图层切换。