mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
Snap to nope line targets too, also remove svgBlocker, not needed
(it's easier to just class the surface, and won't interfere with snapping)
This commit is contained in:
+1
-2
@@ -16,7 +16,6 @@
|
||||
|
||||
/* `.target` objects are interactive */
|
||||
/* They can be picked up, clicked, hovered, or things can connect to them */
|
||||
.layer-blocker.target,
|
||||
.node.target {
|
||||
pointer-events: fill;
|
||||
fill-opacity: 0.8;
|
||||
@@ -35,12 +34,12 @@
|
||||
}
|
||||
|
||||
/* `.target-nope` objects are explicitly forbidden to join to */
|
||||
.layer-blocker.target.target-nope,
|
||||
.node.target.target-nope,
|
||||
.way.target.target-nope {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
/* `.active` objects (currently being drawn or dragged) are not interactive */
|
||||
/* This is important to allow the events to drop through to whatever is */
|
||||
/* below them on the map, so you can still hover and connect to other things. */
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
/* Cursors */
|
||||
|
||||
.nope {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
.map-in-map,
|
||||
#map {
|
||||
cursor: auto; /* Opera */
|
||||
|
||||
+30
-23
@@ -28,7 +28,6 @@ import {
|
||||
|
||||
import { modeBrowse, modeSelect } from './index';
|
||||
import { osmNode } from '../osm';
|
||||
import { svgBlocker } from '../svg';
|
||||
import { uiFlash } from '../ui';
|
||||
|
||||
|
||||
@@ -40,7 +39,6 @@ export function modeDragNode(context) {
|
||||
var hover = behaviorHover(context).altDisables(true)
|
||||
.on('hover', context.ui().sidebar.hover);
|
||||
var edit = behaviorEdit(context);
|
||||
var blocker = svgBlocker(context.projection, context);
|
||||
|
||||
var _nudgeInterval;
|
||||
var _restoreSelectedIDs = [];
|
||||
@@ -135,6 +133,7 @@ export function modeDragNode(context) {
|
||||
var currPoint = (d3_event && d3_event.point) || context.projection(_lastLoc);
|
||||
var currMouse = geoVecSubtract(currPoint, nudge);
|
||||
var loc = context.projection.invert(currMouse);
|
||||
var didSnap = false;
|
||||
|
||||
if (!_nudgeInterval) { // If not nudging at the edge of the viewport, try to snap..
|
||||
// related code
|
||||
@@ -142,16 +141,22 @@ export function modeDragNode(context) {
|
||||
// - `behavior/draw.js` `click()`
|
||||
// - `behavior/draw_way.js` `move()`
|
||||
var d = datum();
|
||||
var target = d && d.id && context.hasEntity(d.id);
|
||||
var nodegroups = d && d.properties && d.properties.nodes;
|
||||
|
||||
if (d.loc) { // snap to node/vertex - a real entity or a nope target with a `loc`
|
||||
loc = d.loc;
|
||||
} else if (target && target.type === 'way') { // snap to way
|
||||
var choice = geoChooseEdge(
|
||||
context.childNodes(target), context.mouse(), context.projection, entity.id
|
||||
);
|
||||
if (choice) {
|
||||
loc = choice.loc;
|
||||
didSnap = true;
|
||||
|
||||
} else if (nodegroups) { // snap to way - a line touch target or nope target with nodes
|
||||
var best = Infinity;
|
||||
for (var i = 0; i < nodegroups.length; i++) {
|
||||
var childNodes = nodegroups[i].map(function(id) { return context.entity(id); });
|
||||
var choice = geoChooseEdge(childNodes, context.mouse(), context.projection, entity.id);
|
||||
if (choice && choice.distance < best) {
|
||||
best = choice.distance;
|
||||
loc = choice.loc;
|
||||
didSnap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,17 +167,23 @@ export function modeDragNode(context) {
|
||||
);
|
||||
|
||||
|
||||
checkGeometry(entity);
|
||||
// check if this movement causes the geometry to break
|
||||
var doBlock = false;
|
||||
if (!didSnap) {
|
||||
doBlock = invalidGeometry(entity, context.graph());
|
||||
}
|
||||
|
||||
context.surface()
|
||||
.classed('nope', doBlock);
|
||||
|
||||
_lastLoc = loc;
|
||||
}
|
||||
|
||||
|
||||
function checkGeometry(entity) {
|
||||
var doBlock = false;
|
||||
var graph = context.graph();
|
||||
function invalidGeometry(entity, graph) {
|
||||
var parents = graph.parentWays(entity);
|
||||
|
||||
function checkSelfIntersections(way, activeID) {
|
||||
function hasSelfIntersections(way, activeID) {
|
||||
// check active (dragged) segments against inactive segments
|
||||
var actives = [];
|
||||
var inactives = [];
|
||||
@@ -206,15 +217,13 @@ export function modeDragNode(context) {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
if (parent.isClosed()) { // check for self intersections
|
||||
if (checkSelfIntersections(parent, entity.id)) {
|
||||
doBlock = true;
|
||||
break;
|
||||
if (hasSelfIntersections(parent, entity.id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d3_select('.data-layer-osm')
|
||||
.call(doBlock ? blocker : blocker.off);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +247,7 @@ export function modeDragNode(context) {
|
||||
if (_isCancelled) return;
|
||||
|
||||
var d = datum();
|
||||
var nope = d && d.id && /-nope$/.test(d.id); // can't drag here
|
||||
var nope = (d && d.id && /-nope$/.test(d.id)) || context.surface().classed('nope');
|
||||
var target = d && d.id && context.hasEntity(d.id); // entity to snap to
|
||||
|
||||
if (nope) { // bounce back
|
||||
@@ -337,10 +346,8 @@ export function modeDragNode(context) {
|
||||
|
||||
_activeEntity = null;
|
||||
|
||||
d3_select('.data-layer-osm')
|
||||
.call(blocker.off);
|
||||
|
||||
context.surface()
|
||||
.classed('nope', false)
|
||||
.selectAll('.active')
|
||||
.classed('active', false);
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
export function svgBlocker(projection, context) {
|
||||
|
||||
function blocker(selection) {
|
||||
var dimensions = projection.clipExtent()[1];
|
||||
var fillClass = context.getDebug('target') ? 'red ' : 'nocolor ';
|
||||
|
||||
var blocker = selection.selectAll('.layer-blocker')
|
||||
.data([{id: 'target-nope'}]);
|
||||
|
||||
blocker.enter()
|
||||
.append('rect')
|
||||
.attr('class', 'layer-blocker target target-nope ' + fillClass)
|
||||
.attr('x', 0)
|
||||
.attr('y', 0)
|
||||
.merge(blocker)
|
||||
.attr('width', dimensions[0])
|
||||
.attr('height', dimensions[1]);
|
||||
}
|
||||
|
||||
blocker.off = function(selection) {
|
||||
selection.selectAll('.layer-blocker')
|
||||
.remove();
|
||||
};
|
||||
|
||||
return blocker;
|
||||
}
|
||||
+30
-14
@@ -180,14 +180,17 @@ export function svgRelationMemberTags(graph) {
|
||||
export function svgSegmentWay(way, graph, activeID) {
|
||||
var features = { passive: [], active: [] };
|
||||
var coordGroups = { passive: [], active: [] };
|
||||
var segment = [];
|
||||
var nodeGroups = { passive: [], active: [] };
|
||||
var coords = [];
|
||||
var nodes = [];
|
||||
var startType = null; // 0 = active, 1 = passive, 2 = adjacent
|
||||
var currType = null;
|
||||
var node;
|
||||
|
||||
for (var i = 0; i < way.nodes.length; i++) {
|
||||
if (way.nodes[i] === activeID) { // vertex is the activeID
|
||||
segment = []; // draw no segment here
|
||||
coords = []; // draw no segment here
|
||||
nodes = [];
|
||||
startType = null;
|
||||
continue;
|
||||
}
|
||||
@@ -201,32 +204,41 @@ export function svgSegmentWay(way, graph, activeID) {
|
||||
|
||||
if (currType !== startType) { // line changes here - try to save a segment
|
||||
|
||||
if (segment.length > 0) { // finish previous segment
|
||||
segment.push(node.loc);
|
||||
if (coords.length > 0) { // finish previous segment
|
||||
coords.push(node.loc);
|
||||
nodes.push(node.id);
|
||||
if (startType === 2 || currType === 2) { // one adjacent vertex
|
||||
coordGroups.active.push(segment);
|
||||
coordGroups.active.push(coords);
|
||||
nodeGroups.active.push(nodes);
|
||||
} else if (startType === 0 && currType === 0) { // both active vertices
|
||||
coordGroups.active.push(segment);
|
||||
coordGroups.active.push(coords);
|
||||
nodeGroups.active.push(nodes);
|
||||
} else {
|
||||
coordGroups.passive.push(segment);
|
||||
coordGroups.passive.push(coords);
|
||||
nodeGroups.passive.push(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
segment = [];
|
||||
coords = [];
|
||||
nodes = [];
|
||||
startType = currType;
|
||||
}
|
||||
|
||||
segment.push(node.loc);
|
||||
coords.push(node.loc);
|
||||
nodes.push(node.id);
|
||||
}
|
||||
|
||||
// complete whatever segment we ended on
|
||||
if (segment.length > 1) {
|
||||
if (coords.length > 1) {
|
||||
if (startType === 2 || currType === 2) { // one adjacent vertex
|
||||
coordGroups.active.push(segment);
|
||||
coordGroups.active.push(coords);
|
||||
nodeGroups.active.push(nodes);
|
||||
} else if (startType === 0 && currType === 0) { // both active vertices
|
||||
coordGroups.active.push(segment);
|
||||
coordGroups.active.push(coords);
|
||||
nodeGroups.active.push(nodes);
|
||||
} else {
|
||||
coordGroups.passive.push(segment);
|
||||
coordGroups.passive.push(coords);
|
||||
nodeGroups.passive.push(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +246,9 @@ export function svgSegmentWay(way, graph, activeID) {
|
||||
features.passive.push({
|
||||
'type': 'Feature',
|
||||
'id': way.id,
|
||||
'properties': {
|
||||
'nodes': nodeGroups.passive
|
||||
},
|
||||
'geometry': {
|
||||
'type': 'MultiLineString',
|
||||
'coordinates': coordGroups.passive
|
||||
@@ -246,7 +261,8 @@ export function svgSegmentWay(way, graph, activeID) {
|
||||
'type': 'Feature',
|
||||
'id': way.id + '-nope', // break the ids on purpose
|
||||
'properties': {
|
||||
'originalID': way.id
|
||||
'originalID': way.id,
|
||||
'nodes': nodeGroups.active
|
||||
},
|
||||
'geometry': {
|
||||
'type': 'MultiLineString',
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export { svgAreas } from './areas.js';
|
||||
export { svgBlocker } from './blocker.js';
|
||||
export { svgDebug } from './debug.js';
|
||||
export { svgDefs } from './defs.js';
|
||||
export { svgGpx } from './gpx.js';
|
||||
|
||||
Reference in New Issue
Block a user