diff --git a/css/map.css b/css/map.css index 2a4c700e5..2336220d7 100644 --- a/css/map.css +++ b/css/map.css @@ -23,6 +23,10 @@ path { fill: none; } +use { + pointer-events: none; +} + /* points */ g.point circle { diff --git a/index.html b/index.html index 2ecdca4e2..95579b505 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ + diff --git a/index_dev.html b/index_dev.html index 0ec4e89db..00c70260c 100644 --- a/index_dev.html +++ b/index_dev.html @@ -7,6 +7,7 @@ + diff --git a/js/id/presets/collection.js b/js/id/presets/collection.js index 4e4a76684..da7f9e5c9 100644 --- a/js/id/presets/collection.js +++ b/js/id/presets/collection.js @@ -10,12 +10,14 @@ iD.presets.Collection = function(collection) { }); }, - matchType: function(entity, resolver) { - var newcollection = collection.filter(function(d) { - return d.matchType(entity, resolver); - }); + match: function(entity, resolver) { + return presets.matchType(entity, resolver).matchTags(entity); + }, - return iD.presets.Collection(newcollection); + matchType: function(entity, resolver) { + return iD.presets.Collection(collection.filter(function(d) { + return d.matchType(entity, resolver); + })); }, matchTags: function(entity) { diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 05113b4c9..89aaf4e2b 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -14,7 +14,7 @@ iD.Map = function(context) { background = iD.Background() .projection(projection), transformProp = iD.util.prefixCSSProperty('Transform'), - points = iD.svg.Points(roundedProjection), + points = iD.svg.Points(roundedProjection, context), vertices = iD.svg.Vertices(roundedProjection), lines = iD.svg.Lines(projection), areas = iD.svg.Areas(roundedProjection), diff --git a/js/id/svg/points.js b/js/id/svg/points.js index 2944b0afd..1e50cf407 100644 --- a/js/id/svg/points.js +++ b/js/id/svg/points.js @@ -1,16 +1,11 @@ -iD.svg.Points = function(projection) { - function imageHref(d) { - // TODO: optimize - for (var k in d.tags) { - var key = k + '=' + d.tags[k]; - if (iD.svg.Points.imageTable[key]) { - return 'icons/' + iD.svg.Points.imageTable[key] + '.png'; - } - } - return 'icons/unknown.png'; - } - +iD.svg.Points = function(projection, context) { return function drawPoints(surface, graph, entities, filter) { + function imageHref(entity) { + var preset = context.presets() + .match(entity, context.graph()); + return '#maki-' + preset.icon + '-12'; + } + var points = []; for (var i = 0; i < entities.length; i++) { @@ -33,16 +28,16 @@ iD.svg.Points = function(projection) { .attr('class', 'node point'); group.append('circle') - .attr('r', 13) + .attr('r', 12) .attr('class', 'shadow'); group.append('circle') .attr('class', 'stroke') - .attr('r', 9); + .attr('r', 8); - group.append('image') - .attr({ width: 16, height: 16 }) - .attr('transform', 'translate(-8, -8)'); + group.append('use') + .attr('transform', 'translate(-6, -6)') + .attr('clip-path', 'url(#clip-square-12)'); groups.attr('transform', iD.svg.PointTransform(projection)) .call(iD.svg.TagClasses()) @@ -50,7 +45,7 @@ iD.svg.Points = function(projection) { // Selecting the following implicitly // sets the data (point entity) on the element - groups.select('image') + groups.select('use') .attr('xlink:href', imageHref); groups.select('.shadow'); groups.select('.stroke'); @@ -59,570 +54,3 @@ iD.svg.Points = function(projection) { .remove(); }; }; - -// an index of tag -> point image combinations, taken from -// http://svn.openstreetmap.org/applications/rendering/mapnik/inc/layer-amenity-symbols.xml.inc -iD.svg.Points.imageIndex = [ - { - tags: { aeroway: 'helipad' }, - icon: 'helipad' - }, - { - tags: { aeroway: 'airport' }, - icon: 'airport' - }, - { - tags: { aeroway: 'aerodrome' }, - icon: 'aerodrome' - }, - { - tags: { railway: 'level_crossing' }, - icon: 'level_crossing' - }, - { - tags: { man_made: 'lighthouse' }, - icon: 'lighthouse' - }, - { - tags: { natural: 'peak' }, - icon: 'peak' - }, - { - tags: { natural: 'volcano' }, - icon: 'volcano' - }, - { - tags: { natural: 'cave_entrance' }, - icon: 'poi_cave' - }, - { - tags: { natural: 'spring' }, - icon: 'spring' - }, - { - tags: { natural: 'tree' }, - icon: 'tree' - }, - { - tags: { - power: 'generator', - 'generator:source': 'wind' - }, - icon: 'power_wind' - }, - { - tags: { - power: 'generator', - power_source: 'wind' - }, - icon: 'power_wind' - }, - { - tags: { - man_made: 'power_wind' - }, - icon: 'power_wind' - }, - { - tags: { - man_made: 'windmill' - }, - icon: 'windmill' - }, - { - tags: { - man_made: 'mast' - }, - icon: 'communications' - }, - { - tags: { - highway: 'mini_roundabout' - }, - icon: 'mini_roundabout' - }, - { - tags: { - highway: 'gate' - }, - icon: 'gate2' - }, - { - tags: { - barrier: 'gate' - }, - icon: 'gate2' - }, - { - tags: { - barrier: 'lift_gate' - }, - icon: 'liftgate' - }, - { - tags: { - barrier: 'bollard' - }, - icon: 'bollard' - }, - { - tags: { - barrier: 'block' - }, - icon: 'bollard' - }, - { - "icon": "alpinehut", - "tags": { - "tourism": "alpine_hut" - } - }, - { - "icon": "shelter2", - "tags": { - "amenity": "shelter" - } - }, - { - "icon": "atm2", - "tags": { - "amenity": "atm" - } - }, - { - "icon": "bank2", - "tags": { - "amenity": "bank" - } - }, - { - "icon": "bar", - "tags": { - "amenity": "bar" - } - }, - { - "icon": "rental_bicycle", - "tags": { - "amenity": "bicycle_rental" - } - }, - { - "icon": "bus_stop_small", - "tags": { - "amenity": "bus_stop" - } - }, - { - "icon": "bus_stop", - "tags": { - "amenity": "bus_stop" - } - }, - { - "icon": "bus_station", - "tags": { - "amenity": "bus_station" - } - }, - { - "icon": "traffic_light", - "tags": { - "highway": "traffic_signals" - } - }, - { - "icon": "cafe", - "tags": { - "amenity": "cafe" - } - }, - { - "icon": "camping", - "tags": { - "tourism": "camp_site" - } - }, - { - "icon": "transport_ford", - "tags": { - "highway": "ford" - } - }, - { - "icon": "caravan_park", - "tags": { - "tourism": "caravan_site" - } - }, - { - "icon": "car_share", - "tags": { - "amenity": "car_sharing" - } - }, - { - "icon": "chalet", - "tags": { - "tourism": "chalet" - } - }, - { - "icon": "cinema", - "tags": { - "amenity": "cinema" - } - }, - { - "icon": "firestation", - "tags": { - "amenity": "fire_station" - } - }, - { - "icon": "fuel", - "tags": { - "amenity": "fuel" - } - }, - { - "icon": "guest_house", - "tags": { - "tourism": "guest_house" - } - }, - { - "icon": "bandb", - "tags": { - "tourism": "bed_and_breakfast" - } - }, - { - "icon": "hospital", - "tags": { - "amenity": "hospital" - } - }, - { - "icon": "hostel", - "tags": { - "tourism": "hostel" - } - }, - { - "icon": "hotel2", - "tags": { - "tourism": "hotel" - } - }, - { - "icon": "motel", - "tags": { - "tourism": "motel" - } - }, - { - "icon": "information", - "tags": { - "tourism": "information" - } - }, - { - "icon": "embassy", - "tags": { - "amenity": "embassy" - } - }, - { - "icon": "library", - "tags": { - "amenity": "library" - } - }, - { - "icon": "amenity_court", - "tags": { - "amenity": "courthouse" - } - }, - { - "icon": "lock_gate", - "tags": { - "waterway": "lock" - } - }, - { - "icon": "communications", - "tags": { - "man_made": "mast" - } - }, - { - "icon": "museum", - "tags": { - "tourism": "museum" - } - }, - { - "icon": "parking", - "tags": { - "amenity": "parking" - } - }, - { - "icon": "parking_private", - "tags": { - "amenity": "parking" - } - }, - { - "icon": "pharmacy", - "tags": { - "amenity": "pharmacy" - } - }, - { - "icon": "christian3", - "tags": { - "amenity": "place_of_worship" - } - }, - { - "icon": "islamic3", - "tags": { - "amenity": "place_of_worship" - } - }, - { - "icon": "sikh3", - "tags": { - "amenity": "place_of_worship" - } - }, - { - "icon": "jewish3", - "tags": { - "amenity": "place_of_worship" - } - }, - { - "icon": "place_of_worship3", - "tags": { - "amenity": "place_of_worship" - } - }, - { - "icon": "police", - "tags": { - "amenity": "police" - } - }, - { - "icon": "post_box", - "tags": { - "amenity": "post_box" - } - }, - { - "icon": "post_office", - "tags": { - "amenity": "post_office" - } - }, - { - "icon": "pub", - "tags": { - "amenity": "pub" - } - }, - { - "icon": "biergarten", - "tags": { - "amenity": "biergarten" - } - }, - { - "icon": "recycling", - "tags": { - "amenity": "recycling" - } - }, - { - "icon": "restaurant", - "tags": { - "amenity": "restaurant" - } - }, - { - "icon": "fast_food", - "tags": { - "amenity": "fast_food" - } - }, - { - "icon": "telephone", - "tags": { - "amenity": "telephone" - } - }, - { - "icon": "sosphone", - "tags": { - "amenity": "emergency_phone" - } - }, - { - "icon": "theatre", - "tags": { - "amenity": "theatre" - } - }, - { - "icon": "toilets", - "tags": { - "amenity": "toilets" - } - }, - { - "icon": "food_drinkingtap", - "tags": { - "amenity": "drinking_water" - } - }, - { - "icon": "amenity_prison", - "tags": { - "amenity": "prison" - } - }, - { - "icon": "view_point", - "tags": { - "tourism": "viewpoint" - } - }, - { - "icon": "tower_water", - "tags": { - "man_made": "water_tower" - } - }, - { - "icon": "tourist_memorial", - "tags": { - "historic": "memorial" - } - }, - { - "icon": "tourist_archaeological2", - "tags": { - "historic": "archaeological_site" - } - }, - { - "icon": "shop_supermarket", - "tags": { - "shop": "supermarket" - } - }, - { - "icon": "shop_bakery", - "tags": { - "shop": "bakery" - } - }, - { - "icon": "shop_butcher", - "tags": { - "shop": "butcher" - } - }, - { - "icon": "shop_clothes", - "tags": { - "shop": "clothes" - } - }, - { - "icon": "shop_convenience", - "tags": { - "shop": "convenience" - } - }, - { - "icon": "department_store", - "tags": { - "shop": "department_store" - } - }, - { - "icon": "shop_diy", - "tags": { - "shop": "doityourself" - } - }, - { - "icon": "florist", - "tags": { - "shop": "florist" - } - }, - { - "icon": "shop_hairdresser", - "tags": { - "shop": "hairdresser" - } - }, - { - "icon": "shopping_car", - "tags": { - "shop": "car" - } - }, - { - "icon": "shopping_car_repair", - "tags": { - "shop": "car_repair" - } - }, - { - "icon": "shopping_bicycle", - "tags": { - "shop": "bicycle" - } - }, - { - "icon": "playground", - "tags": { - "leisure": "playground" - } - }, - { - "icon": "picnic", - "tags": { - "amenity": "picnic_site" - } - }, - { - "icon": "transport_slipway", - "tags": { - "leisure": "slipway" - } - } -]; - -// generate a fast lookup table for point styling -iD.svg.Points.imageTable = (function(points) { - var table = {}; - for (var i = 0; i < points.length; i++) { - var point = points[i]; - // single-tag matches, the easy case - if (Object.keys(point.tags).length === 1) { - for (var k in point.tags) { - var key = k + '=' + point.tags[k]; - table[key] = point.icon; - } - } - } - return table; -})(iD.svg.Points.imageIndex); diff --git a/js/id/svg/surface.js b/js/id/svg/surface.js index e6e2ae025..9f671eb11 100644 --- a/js/id/svg/surface.js +++ b/js/id/svg/surface.js @@ -1,6 +1,7 @@ iD.svg.Surface = function() { return function drawSurface(selection) { var defs = selection.append('defs'); + defs.append('marker') .attr({ id: 'oneway-marker', @@ -51,6 +52,38 @@ iD.svg.Surface = function() { }) .attr('xlink:href', function(d) { return 'img/pattern/' + d[1] + '.png'; }); + defs.append('clipPath') + .attr('id', 'clip-square-12') + .append('rect') + .attr({ + x: 0, + y: 0, + width: 12, + height: 12 + }); + + defs.append('image') + .attr({ + id: 'maki-sprite', + width: 306, + height: 294, + 'xlink:href': 'img/maki.png' + }); + + _.forEach(_.find(document.styleSheets, function(stylesheet) { + return stylesheet.href.indexOf("maki.css") > 0; + }).cssRules, function(rule) { + var klass = rule.selectorText, + match = klass.match(/^\.(maki-[a-z0-9-]+-12)$/); + if (match) { + var id = match[1]; + match = rule.style.backgroundPosition.match(/(-?\d+)px (-?\d+)px/); + defs.append('use') + .attr('id', id) + .attr('transform', "translate(" + match[1] + "," + match[2] + ")") + .attr('xlink:href', '#maki-sprite'); + } + }); var layers = selection.selectAll('.layer') .data(['fill', 'shadow', 'casing', 'stroke', 'text', 'hit', 'halo', 'label']); diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 7a00f970e..4b9c4be7c 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -30,11 +30,7 @@ iD.ui.Inspector = function(context) { inspectorbody.call(presetGrid, true); }); - if (initial) { - inspectorbody.call(presetGrid); - } else { - inspectorbody.call(tagEditor); - } + inspectorbody.call(initial ? presetGrid : tagEditor); selection.call(iD.ui.Toggle(true)); } diff --git a/js/id/ui/tag_editor.js b/js/id/ui/tag_editor.js index 8c9d1d3b7..6750685a5 100644 --- a/js/id/ui/tag_editor.js +++ b/js/id/ui/tag_editor.js @@ -26,7 +26,7 @@ iD.ui.TagEditor = function(context) { // find a preset that best fits } else if (!preset) { - preset = presets.matchType(entity, context.graph()).matchTags(entity); + preset = presets.match(entity, context.graph()); } selection.html('');