external modules for SVG

This commit is contained in:
Kushan Joshi
2016-07-06 13:31:50 +05:30
committed by Bryan Housel
parent 9c82bba6fb
commit b3492b17a0
17 changed files with 117 additions and 85 deletions

View File

@@ -4,6 +4,7 @@ import * as geo from './geo/index';
import * as modes from './modes/index';
import * as operations from './operations/index';
import * as presets from './presets/index';
import * as svg from './svg/index';
import * as ui from './ui/index';
import * as util from './util/index';
import * as validations from './validations/index';
@@ -34,6 +35,7 @@ export {
modes,
operations,
presets,
svg,
util,
ui,
validations

View File

@@ -1,3 +1,7 @@
import { Path, TagClasses } from './index';
import { Entity } from '../core/index';
import { isSimpleMultipolygonOuterMember } from '../geo/index';
export function Areas(projection) {
// Patterns only work in Firefox when set directly on element.
// (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
@@ -28,7 +32,7 @@ export function Areas(projection) {
}
return function drawAreas(surface, graph, entities, filter) {
var path = iD.svg.Path(projection, graph, true),
var path = Path(projection, graph, true),
areas = {},
multipolygon;
@@ -36,7 +40,7 @@ export function Areas(projection) {
var entity = entities[i];
if (entity.geometry(graph) !== 'area') continue;
multipolygon = iD.geo.isSimpleMultipolygonOuterMember(entity, graph);
multipolygon = isSimpleMultipolygonOuterMember(entity, graph);
if (multipolygon) {
areas[multipolygon.id] = {
entity: multipolygon.mergeTags(entity.tags),
@@ -67,7 +71,7 @@ export function Areas(projection) {
var clipPaths = surface.selectAll('defs').selectAll('.clipPath')
.filter(filter)
.data(data.clip, iD.Entity.key);
.data(data.clip, Entity.key);
clipPaths.enter()
.append('clipPath')
@@ -93,7 +97,7 @@ export function Areas(projection) {
var paths = areagroup
.selectAll('path')
.filter(filter)
.data(function(layer) { return data[layer]; }, iD.Entity.key);
.data(function(layer) { return data[layer]; }, Entity.key);
// Remove exiting areas first, so they aren't included in the `fills`
// array used for sorting below (https://github.com/openstreetmap/iD/issues/1903).
@@ -124,7 +128,7 @@ export function Areas(projection) {
setPattern.apply(this, arguments);
}
})
.call(iD.svg.TagClasses());
.call(TagClasses());
paths
.attr('d', path);

View File

@@ -1,3 +1,5 @@
import { polygonIntersectsPolygon } from '../geo/index';
export function Debug(projection, context) {
function multipolygons(imagery) {
@@ -75,7 +77,7 @@ export function Debug(projection, context) {
availableImagery = showsImagery && multipolygons(iD.data.imagery.filter(function(source) {
if (!source.polygon) return false;
return source.polygon.some(function(polygon) {
return iD.geo.polygonIntersectsPolygon(polygon, extent, true);
return polygonIntersectsPolygon(polygon, extent, true);
});
}));

View File

@@ -1,3 +1,4 @@
import { Extent, polygonIntersectsPolygon } from '../geo/index';
import toGeoJSON from 'togeojson';
export function Gpx(projection, context, dispatch) {
@@ -5,10 +6,10 @@ export function Gpx(projection, context, dispatch) {
layer;
function init() {
if (iD.svg.Gpx.initialized) return; // run once
if (Gpx.initialized) return; // run once
iD.svg.Gpx.geojson = {};
iD.svg.Gpx.enabled = true;
Gpx.geojson = {};
Gpx.enabled = true;
function over() {
d3.event.stopPropagation();
@@ -28,13 +29,13 @@ export function Gpx(projection, context, dispatch) {
.on('dragexit.localgpx', over)
.on('dragover.localgpx', over);
iD.svg.Gpx.initialized = true;
Gpx.initialized = true;
}
function drawGpx(surface) {
var geojson = iD.svg.Gpx.geojson,
enabled = iD.svg.Gpx.enabled;
var geojson = Gpx.geojson,
enabled = Gpx.enabled;
layer = surface.selectAll('.layer-gpx')
.data(enabled ? [0] : []);
@@ -101,21 +102,21 @@ export function Gpx(projection, context, dispatch) {
};
drawGpx.enabled = function(_) {
if (!arguments.length) return iD.svg.Gpx.enabled;
iD.svg.Gpx.enabled = _;
if (!arguments.length) return Gpx.enabled;
Gpx.enabled = _;
dispatch.change();
return this;
};
drawGpx.hasGpx = function() {
var geojson = iD.svg.Gpx.geojson;
var geojson = Gpx.geojson;
return (!(_.isEmpty(geojson) || _.isEmpty(geojson.features)));
};
drawGpx.geojson = function(gj) {
if (!arguments.length) return iD.svg.Gpx.geojson;
if (!arguments.length) return Gpx.geojson;
if (_.isEmpty(gj) || _.isEmpty(gj.features)) return this;
iD.svg.Gpx.geojson = gj;
Gpx.geojson = gj;
dispatch.change();
return this;
};
@@ -144,7 +145,7 @@ export function Gpx(projection, context, dispatch) {
drawGpx.fitZoom = function() {
if (!this.hasGpx()) return this;
var geojson = iD.svg.Gpx.geojson;
var geojson = Gpx.geojson;
var map = context.map(),
viewport = map.trimmedExtent().polygon(),
@@ -153,8 +154,8 @@ export function Gpx(projection, context, dispatch) {
return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
}, []);
if (!iD.geo.polygonIntersectsPolygon(viewport, coords, true)) {
var extent = iD.geo.Extent(d3.geo.bounds(geojson));
if (!polygonIntersectsPolygon(viewport, coords, true)) {
var extent = Extent(d3.geo.bounds(geojson));
map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
}

View File

@@ -1,3 +1,6 @@
import { displayName, getStyle } from '../util/index';
import { Entity } from '../core/index';
import { pathLength } from '../geo/index';
import rbush from 'rbush';
export function Labels(projection, context) {
@@ -35,11 +38,11 @@ export function Labels(projection, context) {
var default_size = 12;
var font_sizes = label_stack.map(function(d) {
var style = iD.util.getStyle('text.' + d[0] + '.tag-' + d[1]),
var style = getStyle('text.' + d[0] + '.tag-' + d[1]),
m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
if (m) return parseInt(m[1], 10);
style = iD.util.getStyle('text.' + d[0]);
style = getStyle('text.' + d[0]);
m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
if (m) return parseInt(m[1], 10);
@@ -95,7 +98,7 @@ export function Labels(projection, context) {
function drawLineLabels(group, entities, filter, classes, labels) {
var texts = group.selectAll('text.' + classes)
.filter(filter)
.data(entities, iD.Entity.key);
.data(entities, Entity.key);
texts.enter()
.append('text')
@@ -106,12 +109,12 @@ export function Labels(projection, context) {
texts.selectAll('.textpath')
.filter(filter)
.data(entities, iD.Entity.key)
.data(entities, Entity.key)
.attr({
'startOffset': '50%',
'xlink:href': function(d) { return '#labelpath-' + d.id; }
})
.text(iD.util.displayName);
.text(displayName);
texts.exit().remove();
}
@@ -119,7 +122,7 @@ export function Labels(projection, context) {
function drawLinePaths(group, entities, filter, classes, labels) {
var halos = group.selectAll('path')
.filter(filter)
.data(entities, iD.Entity.key);
.data(entities, Entity.key);
halos.enter()
.append('path')
@@ -135,7 +138,7 @@ export function Labels(projection, context) {
function drawPointLabels(group, entities, filter, classes, labels) {
var texts = group.selectAll('text.' + classes)
.filter(filter)
.data(entities, iD.Entity.key);
.data(entities, Entity.key);
texts.enter()
.append('text')
@@ -144,8 +147,8 @@ export function Labels(projection, context) {
texts.attr('x', get(labels, 'x'))
.attr('y', get(labels, 'y'))
.style('text-anchor', get(labels, 'textAnchor'))
.text(iD.util.displayName)
.each(function(d, i) { textWidth(iD.util.displayName(d), labels[i].height, this); });
.text(displayName)
.each(function(d, i) { textWidth(displayName(d), labels[i].height, this); });
texts.exit().remove();
return texts;
@@ -164,7 +167,7 @@ export function Labels(projection, context) {
function drawAreaIcons(group, entities, filter, classes, labels) {
var icons = group.selectAll('use')
.filter(filter)
.data(entities, iD.Entity.key);
.data(entities, Entity.key);
icons.enter()
.append('use')
@@ -277,7 +280,7 @@ export function Labels(projection, context) {
var preset = geometry === 'area' && context.presets().match(entity, graph),
icon = preset && !blacklisted(preset) && preset.icon;
if (!icon && !iD.util.displayName(entity))
if (!icon && !displayName(entity))
continue;
for (k = 0; k < label_stack.length; k++) {
@@ -305,7 +308,7 @@ export function Labels(projection, context) {
var font_size = font_sizes[k];
for (i = 0; i < labelable[k].length; i++) {
entity = labelable[k][i];
var name = iD.util.displayName(entity),
var name = displayName(entity),
width = name && textWidth(name, font_size),
p;
if (entity.geometry(graph) === 'point') {
@@ -341,7 +344,7 @@ export function Labels(projection, context) {
function getLineLabel(entity, width, height) {
var nodes = _.map(graph.childNodes(entity), 'loc').map(projection),
length = iD.geo.pathLength(nodes);
length = pathLength(nodes);
if (length < width + 20) return;
for (var i = 0; i < lineOffsets.length; i++) {

View File

@@ -1,12 +1,18 @@
import { Debug } from './debug';
import { Gpx } from './gpx';
import { MapillaryImages } from './mapillary_images';
import { MapillarySigns } from './mapillary_signs';
import { Osm } from './osm';
export function Layers(projection, context) {
var dispatch = d3.dispatch('change'),
svg = d3.select(null),
layers = [
{ id: 'osm', layer: iD.svg.Osm(projection, context, dispatch) },
{ id: 'gpx', layer: iD.svg.Gpx(projection, context, dispatch) },
{ id: 'mapillary-images', layer: iD.svg.MapillaryImages(projection, context, dispatch) },
{ id: 'mapillary-signs', layer: iD.svg.MapillarySigns(projection, context, dispatch) },
{ id: 'debug', layer: iD.svg.Debug(projection, context, dispatch) }
{ id: 'osm', layer: Osm(projection, context, dispatch) },
{ id: 'gpx', layer: Gpx(projection, context, dispatch) },
{ id: 'mapillary-images', layer: MapillaryImages(projection, context, dispatch) },
{ id: 'mapillary-signs', layer: MapillarySigns(projection, context, dispatch) },
{ id: 'debug', layer: Debug(projection, context, dispatch) }
];

View File

@@ -1,3 +1,7 @@
import { OneWaySegments, Path, RelationMemberTags, TagClasses } from './index';
import { Entity } from '../core/index';
import { simpleMultipolygonOuterMember } from '../geo/index';
export function Lines(projection) {
var highway_stack = {
@@ -25,11 +29,11 @@ export function Lines(projection) {
return function drawLines(surface, graph, entities, filter) {
var ways = [], pathdata = {}, onewaydata = {},
getPath = iD.svg.Path(projection, graph);
getPath = Path(projection, graph);
for (var i = 0; i < entities.length; i++) {
var entity = entities[i],
outer = iD.geo.simpleMultipolygonOuterMember(entity, graph);
outer = simpleMultipolygonOuterMember(entity, graph);
if (outer) {
ways.push(entity.mergeTags(outer.tags));
} else if (entity.geometry(graph) === 'line') {
@@ -44,7 +48,7 @@ export function Lines(projection) {
_.forOwn(pathdata, function(v, k) {
onewaydata[k] = _(v)
.filter(function(d) { return d.isOneWay(); })
.map(iD.svg.OneWaySegments(projection, graph, 35))
.map(OneWaySegments(projection, graph, 35))
.flatten()
.valueOf();
});
@@ -73,20 +77,20 @@ export function Lines(projection) {
.filter(filter)
.data(
function() { return pathdata[this.parentNode.parentNode.__data__] || []; },
iD.Entity.key
Entity.key
);
// Optimization: call simple TagClasses only on enter selection. This
// works because iD.Entity.key is defined to include the entity v attribute.
// works because Entity.key is defined to include the entity v attribute.
lines.enter()
.append('path')
.attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
.call(iD.svg.TagClasses());
.call(TagClasses());
lines
.sort(waystack)
.attr('d', getPath)
.call(iD.svg.TagClasses().tags(iD.svg.RelationMemberTags(graph)));
.call(TagClasses().tags(RelationMemberTags(graph)));
lines.exit()
.remove();

View File

@@ -1,3 +1,5 @@
import { PointTransform } from './point_transform';
export function MapillaryImages(projection, context, dispatch) {
var debouncedRedraw = _.debounce(function () { dispatch.change(); }, 1000),
minZoom = 12,
@@ -6,9 +8,9 @@ export function MapillaryImages(projection, context, dispatch) {
function init() {
if (iD.svg.MapillaryImages.initialized) return; // run once
iD.svg.MapillaryImages.enabled = false;
iD.svg.MapillaryImages.initialized = true;
if (MapillaryImages.initialized) return; // run once
MapillaryImages.enabled = false;
MapillaryImages.initialized = true;
}
function getMapillary() {
@@ -74,7 +76,7 @@ export function MapillaryImages(projection, context, dispatch) {
}
function transform(d) {
var t = iD.svg.PointTransform(projection)(d);
var t = PointTransform(projection)(d);
if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
return t;
}
@@ -114,7 +116,7 @@ export function MapillaryImages(projection, context, dispatch) {
}
function drawImages(selection) {
var enabled = iD.svg.MapillaryImages.enabled,
var enabled = MapillaryImages.enabled,
mapillary = getMapillary();
layer = selection.selectAll('.layer-mapillary-images')
@@ -140,9 +142,9 @@ export function MapillaryImages(projection, context, dispatch) {
}
drawImages.enabled = function(_) {
if (!arguments.length) return iD.svg.MapillaryImages.enabled;
iD.svg.MapillaryImages.enabled = _;
if (iD.svg.MapillaryImages.enabled) {
if (!arguments.length) return MapillaryImages.enabled;
MapillaryImages.enabled = _;
if (MapillaryImages.enabled) {
showLayer();
} else {
hideLayer();

View File

@@ -1,3 +1,5 @@
import { PointTransform } from './point_transform';
export function MapillarySigns(projection, context, dispatch) {
var debouncedRedraw = _.debounce(function () { dispatch.change(); }, 1000),
minZoom = 12,
@@ -6,9 +8,9 @@ export function MapillarySigns(projection, context, dispatch) {
function init() {
if (iD.svg.MapillarySigns.initialized) return; // run once
iD.svg.MapillarySigns.enabled = false;
iD.svg.MapillarySigns.initialized = true;
if (MapillarySigns.initialized) return; // run once
MapillarySigns.enabled = false;
MapillarySigns.initialized = true;
}
function getMapillary() {
@@ -78,11 +80,11 @@ export function MapillarySigns(projection, context, dispatch) {
// Update
signs
.attr('transform', iD.svg.PointTransform(projection));
.attr('transform', PointTransform(projection));
}
function drawSigns(selection) {
var enabled = iD.svg.MapillarySigns.enabled,
var enabled = MapillarySigns.enabled,
mapillary = getMapillary();
layer = selection.selectAll('.layer-mapillary-signs')
@@ -109,9 +111,9 @@ export function MapillarySigns(projection, context, dispatch) {
}
drawSigns.enabled = function(_) {
if (!arguments.length) return iD.svg.MapillarySigns.enabled;
iD.svg.MapillarySigns.enabled = _;
if (iD.svg.MapillarySigns.enabled) {
if (!arguments.length) return MapillarySigns.enabled;
MapillarySigns.enabled = _;
if (MapillarySigns.enabled) {
showLayer();
} else {
hideLayer();

View File

@@ -1,3 +1,6 @@
import { PointTransform, TagClasses } from './index';
import { angle, euclideanDistance, interp, lineIntersection } from '../geo/index';
export function Midpoints(projection, context) {
return function drawMidpoints(surface, graph, entities, filter, extent) {
var poly = extent.polygon(),
@@ -23,18 +26,18 @@ export function Midpoints(projection, context) {
if (midpoints[id]) {
midpoints[id].parents.push(entity);
} else {
if (iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
var point = iD.geo.interp(a.loc, b.loc, 0.5),
if (euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
var point = interp(a.loc, b.loc, 0.5),
loc = null;
if (extent.intersects(point)) {
loc = point;
} else {
for (var k = 0; k < 4; k++) {
point = iD.geo.lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
point = lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
if (point &&
iD.geo.euclideanDistance(projection(a.loc), projection(point)) > 20 &&
iD.geo.euclideanDistance(projection(b.loc), projection(point)) > 20)
euclideanDistance(projection(a.loc), projection(point)) > 20 &&
euclideanDistance(projection(b.loc), projection(point)) > 20)
{
loc = point;
break;
@@ -85,13 +88,13 @@ export function Midpoints(projection, context) {
groups
.attr('transform', function(d) {
var translate = iD.svg.PointTransform(projection),
var translate = PointTransform(projection),
a = context.entity(d.edge[0]),
b = context.entity(d.edge[1]),
angle = Math.round(iD.geo.angle(a, b, projection) * (180 / Math.PI));
return translate(d) + ' rotate(' + angle + ')';
angleVal = Math.round(angle(a, b, projection) * (180 / Math.PI));
return translate(d) + ' rotate(' + angleVal + ')';
})
.call(iD.svg.TagClasses().tags(
.call(TagClasses().tags(
function(d) { return d.parents[0].tags; }
));

View File

@@ -1,3 +1,5 @@
import { euclideanDistance } from '../geo/index';
export function OneWaySegments(projection, graph, dt) {
return function(entity) {
var a,
@@ -24,7 +26,7 @@ export function OneWaySegments(projection, graph, dt) {
b = [x, y];
if (a) {
var span = iD.geo.euclideanDistance(a, b) - offset;
var span = euclideanDistance(a, b) - offset;
if (span >= 0) {
var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),

View File

@@ -1,3 +1,6 @@
import { PointTransform, TagClasses } from './index';
import { Entity } from '../core/index';
export function Points(projection, context) {
function markerPath(selection, klass) {
selection
@@ -20,7 +23,7 @@ export function Points(projection, context) {
var groups = surface.selectAll('.layer-hit').selectAll('g.point')
.filter(filter)
.data(points, iD.Entity.key);
.data(points, Entity.key);
var group = groups.enter()
.append('g')
@@ -39,8 +42,8 @@ export function Points(projection, context) {
.attr('width', '12px')
.attr('height', '12px');
groups.attr('transform', iD.svg.PointTransform(projection))
.call(iD.svg.TagClasses());
groups.attr('transform', PointTransform(projection))
.call(TagClasses());
// Selecting the following implicitly
// sets the data (point entity) on the element

View File

@@ -1,3 +1,5 @@
import { angle } from '../geo/index';
export function Turns(projection) {
return function drawTurns(surface, graph, turns) {
function key(turn) {
@@ -49,7 +51,7 @@ export function Turns(projection) {
.attr('transform', function (turn) {
var v = graph.entity(turn.via.node),
t = graph.entity(turn.to.node),
a = iD.geo.angle(v, t, projection),
a = angle(v, t, projection),
p = projection(v.loc),
r = turn.u ? 0 : 60;

View File

@@ -1,3 +1,6 @@
import { Entity } from '../core/index';
import { PointTransform } from './index';
export function Vertices(projection, context) {
var radiuses = {
// z16-, z17, z18+, tagged
@@ -51,7 +54,7 @@ export function Vertices(projection, context) {
z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2);
var groups = selection
.data(vertices, iD.Entity.key);
.data(vertices, Entity.key);
function icon(entity) {
if (entity.id in icons) return icons[entity.id];
@@ -121,7 +124,7 @@ export function Vertices(projection, context) {
.each(setClass('fill'));
groups
.attr('transform', iD.svg.PointTransform(projection))
.attr('transform', PointTransform(projection))
.classed('shared', function(entity) { return graph.isShared(entity); })
.call(setAttributes);