mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-20 23:44:47 +02:00
Teach realigning roads by moving nodes, adding midpoints
(closes #2381)
This commit is contained in:
+7
-1
@@ -945,7 +945,13 @@ en:
|
||||
choose_preset_residential: "There are many different types of roads, but this one is a residential road. **Choose the {name} type**"
|
||||
retry_preset_residential: "You didn't select the {name} type. **Click here to choose again**"
|
||||
name_road: "**Give this road a name, then hit escape, return, or click the {button} button to close the feature editor.**"
|
||||
play: "You added a new road! Try drawing a few more lines, and see what other kinds of lines you can add to OpenStreetMap. **When you are ready to continue to the next chapter, click '{next}'.**"
|
||||
update_line: "Sometimes you will need to change the shape of an existing line. Here is a road that doesn't look quite right."
|
||||
add_node: "We can add some nodes to this line to improve its shape. One way to add a node is to double-click the line where you want to add a node. **Double-click on the line to create a new node.**"
|
||||
start_drag_endpoint: "When a line is selected, you can drag any of its nodes by clicking and holding down the left mouse button while you drag. **Drag the endpoint to the place where these roads should intersect.**"
|
||||
finish_drag_endpoint: "This spot looks good. **Finish dragging by releasing the left mouse button**"
|
||||
start_drag_midpoint: "Small triangles are drawn at the midpoints between nodes. Another way to create a new node is to drag a midpoint to a new location. **Drag the midpoint triangle to create a new node along the curve of the road.**"
|
||||
continue_drag_midpoint: "This line is looking much better! Continue to adjust this line by double-clicking or dragging midpoints until the curve matches the road shape. **When you're happy with how the line looks, click OK.**"
|
||||
play: "Great! Use the skills that you've learned in this chapter to practice editing some more lines. **When you are ready to continue to the next chapter, click '{next}'.**"
|
||||
buildings:
|
||||
title: "Buildings"
|
||||
add_building: "OpenStreetMap is the world's largest database of buildings. You can help improve this database by tracing buildings that aren't already mapped. **Click the {button} Area button to add a new area.**"
|
||||
|
||||
Vendored
+7
-1
@@ -808,7 +808,13 @@
|
||||
"choose_preset_residential": "There are many different types of roads, but this one is a residential road. **Choose the {name} type**",
|
||||
"retry_preset_residential": "You didn't select the {name} type. **Click here to choose again**",
|
||||
"name_road": "**Give this road a name, then hit escape, return, or click the {button} button to close the feature editor.**",
|
||||
"play": "You added a new road! Try drawing a few more lines, and see what other kinds of lines you can add to OpenStreetMap. **When you are ready to continue to the next chapter, click '{next}'.**"
|
||||
"update_line": "Sometimes you will need to change the shape of an existing line. Here is a road that doesn't look quite right.",
|
||||
"add_node": "We can add some nodes to this line to improve its shape. One way to add a node is to double-click the line where you want to add a node. **Double-click on the line to create a new node.**",
|
||||
"start_drag_endpoint": "When a line is selected, you can drag any of its nodes by clicking and holding down the left mouse button while you drag. **Drag the endpoint to the place where these roads should intersect.**",
|
||||
"finish_drag_endpoint": "This spot looks good. **Finish dragging by releasing the left mouse button**",
|
||||
"start_drag_midpoint": "Small triangles are drawn at the midpoints between nodes. Another way to create a new node is to drag a midpoint to a new location. **Drag the midpoint triangle to create a new node along the curve of the road.**",
|
||||
"continue_drag_midpoint": "This line is looking much better! Continue to adjust this line by double-clicking or dragging midpoints until the curve matches the road shape. **When you're happy with how the line looks, click OK.**",
|
||||
"play": "Great! Use the skills that you've learned in this chapter to practice editing some more lines. **When you are ready to continue to the next chapter, click '{next}'.**"
|
||||
},
|
||||
"buildings": {
|
||||
"title": "Buildings",
|
||||
|
||||
+240
-21
@@ -1,6 +1,8 @@
|
||||
import * as d3 from 'd3';
|
||||
import _ from 'lodash';
|
||||
import { t } from '../../util/locale';
|
||||
import { geoSphericalDistance } from '../../geo/index';
|
||||
import { modeSelect } from '../../modes/select';
|
||||
import { utilRebind } from '../../util/rebind';
|
||||
import { icon, pad } from './helper';
|
||||
|
||||
@@ -8,13 +10,18 @@ import { icon, pad } from './helper';
|
||||
export function uiIntroLine(context, reveal) {
|
||||
var dispatch = d3.dispatch('done'),
|
||||
timeouts = [],
|
||||
midpoint = [-85.62975395449628, 41.95787501510204],
|
||||
start = [-85.6297754121684, 41.95805253325314],
|
||||
intersection = [-85.62974496187628, 41.95742515554585],
|
||||
tulipRoadId = null,
|
||||
flowerRoadId = 'w646',
|
||||
tulipRoadStart = [-85.6297754121684, 41.95805253325314],
|
||||
tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204],
|
||||
tulipRoadIntersection = [-85.62974496187628, 41.95742515554585],
|
||||
woodRoadId = 'w525',
|
||||
woodRoadEndId = 'n2862',
|
||||
woodRoadAddNode = [-85.62390110349587, 41.95397111462291],
|
||||
woodRoadDragEndpoint = [-85.62383958913921, 41.9546607846611],
|
||||
woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872],
|
||||
roadCategory = context.presets().item('category-road'),
|
||||
residentialPreset = context.presets().item('highway/residential'),
|
||||
targetId = 'w646',
|
||||
lineId = null;
|
||||
residentialPreset = context.presets().item('highway/residential');
|
||||
|
||||
|
||||
var chapter = {
|
||||
@@ -60,16 +67,16 @@ export function uiIntroLine(context, reveal) {
|
||||
return chapter.restart();
|
||||
}
|
||||
|
||||
lineId = null;
|
||||
tulipRoadId = null;
|
||||
|
||||
var padding = 70 * Math.pow(2, context.map().zoom() - 18);
|
||||
var box = pad(start, padding, context);
|
||||
var box = pad(tulipRoadStart, padding, context);
|
||||
box.height = box.height + 100;
|
||||
reveal(box, t('intro.lines.start_line'));
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
padding = 70 * Math.pow(2, context.map().zoom() - 18);
|
||||
box = pad(start, padding, context);
|
||||
box = pad(tulipRoadStart, padding, context);
|
||||
box.height = box.height + 100;
|
||||
reveal(box, t('intro.lines.start_line'), { duration: 0 });
|
||||
});
|
||||
@@ -92,12 +99,12 @@ export function uiIntroLine(context, reveal) {
|
||||
return chapter.restart();
|
||||
}
|
||||
|
||||
lineId = context.mode().selectedIDs()[0];
|
||||
context.map().centerEase(midpoint);
|
||||
tulipRoadId = context.mode().selectedIDs()[0];
|
||||
context.map().centerEase(tulipRoadMidpoint);
|
||||
|
||||
timeout(function() {
|
||||
var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
|
||||
var box = pad(midpoint, padding, context);
|
||||
var box = pad(tulipRoadMidpoint, padding, context);
|
||||
box.height = box.height * 2;
|
||||
reveal(box,
|
||||
t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') })
|
||||
@@ -105,7 +112,7 @@ export function uiIntroLine(context, reveal) {
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
|
||||
box = pad(midpoint, padding, context);
|
||||
box = pad(tulipRoadMidpoint, padding, context);
|
||||
box.height = box.height * 2;
|
||||
reveal(box,
|
||||
t('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }),
|
||||
@@ -115,7 +122,7 @@ export function uiIntroLine(context, reveal) {
|
||||
}, 260); // after easing..
|
||||
|
||||
context.history().on('change.intro', function() {
|
||||
var entity = lineId && context.hasEntity(lineId);
|
||||
var entity = tulipRoadId && context.hasEntity(tulipRoadId);
|
||||
if (!entity) return chapter.restart();
|
||||
|
||||
if (isLineConnected()) {
|
||||
@@ -144,13 +151,13 @@ export function uiIntroLine(context, reveal) {
|
||||
|
||||
|
||||
function isLineConnected() {
|
||||
var entity = lineId && context.hasEntity(lineId);
|
||||
var entity = tulipRoadId && context.hasEntity(tulipRoadId);
|
||||
if (!entity) return false;
|
||||
|
||||
var drawNodes = context.graph().childNodes(entity);
|
||||
return _.some(drawNodes, function(node) {
|
||||
return _.some(context.graph().parentWays(node), function(parent) {
|
||||
return parent.id === targetId;
|
||||
return parent.id === flowerRoadId;
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -159,7 +166,7 @@ export function uiIntroLine(context, reveal) {
|
||||
function retryIntersect() {
|
||||
d3.select(window).on('mousedown.intro', eventCancel, true);
|
||||
|
||||
var box = pad(intersection, 80, context);
|
||||
var box = pad(tulipRoadIntersection, 80, context);
|
||||
reveal(box,
|
||||
t('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') })
|
||||
);
|
||||
@@ -170,10 +177,10 @@ export function uiIntroLine(context, reveal) {
|
||||
|
||||
function continueLine() {
|
||||
if (context.mode().id !== 'draw-line') return chapter.restart();
|
||||
var entity = lineId && context.hasEntity(lineId);
|
||||
var entity = tulipRoadId && context.hasEntity(tulipRoadId);
|
||||
if (!entity) return chapter.restart();
|
||||
|
||||
context.map().centerEase(intersection);
|
||||
context.map().centerEase(tulipRoadIntersection);
|
||||
|
||||
reveal('#surface', t('intro.lines.continue_line'));
|
||||
|
||||
@@ -287,7 +294,8 @@ export function uiIntroLine(context, reveal) {
|
||||
|
||||
function nameRoad() {
|
||||
context.on('exit.intro', function() {
|
||||
continueTo(play);
|
||||
context.history().checkpoint('doneAddRoad');
|
||||
continueTo(updateLine);
|
||||
});
|
||||
|
||||
timeout(function() {
|
||||
@@ -303,6 +311,217 @@ export function uiIntroLine(context, reveal) {
|
||||
}
|
||||
|
||||
|
||||
function updateLine() {
|
||||
context.history().reset('doneAddRoad');
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return chapter.restart();
|
||||
}
|
||||
|
||||
context.map().zoom(19).centerEase(woodRoadDragMidpoint, 500);
|
||||
|
||||
timeout(function() {
|
||||
var padding = 250 * Math.pow(2, context.map().zoom() - 19);
|
||||
var box = pad(woodRoadDragMidpoint, padding, context);
|
||||
var advance = function() { continueTo(addNode); };
|
||||
|
||||
reveal(box, t('intro.lines.update_line'),
|
||||
{ buttonText: t('intro.ok'), buttonCallback: advance }
|
||||
);
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
var box = pad(woodRoadDragMidpoint, padding, context);
|
||||
reveal(box, t('intro.lines.update_line'),
|
||||
{ duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
|
||||
);
|
||||
});
|
||||
}, 550);
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addNode() {
|
||||
context.history().reset('doneAddRoad');
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return chapter.restart();
|
||||
}
|
||||
|
||||
var padding = 40 * Math.pow(2, context.map().zoom() - 19);
|
||||
|
||||
var box = pad(woodRoadAddNode, padding, context);
|
||||
reveal(box, t('intro.lines.add_node'));
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
var box = pad(woodRoadAddNode, padding, context);
|
||||
reveal(box, t('intro.lines.add_node'), { duration: 0 });
|
||||
});
|
||||
|
||||
context.history().on('change.intro', function(changed) {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
if (changed.created().length === 1) {
|
||||
timeout(function() { continueTo(startDragEndpoint); }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
context.on('enter.intro', function(mode) {
|
||||
if (mode.id !== 'select') {
|
||||
continueTo(updateLine);
|
||||
}
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
context.history().on('change.intro', null);
|
||||
context.on('enter.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function startDragEndpoint() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
|
||||
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
|
||||
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
reveal(box, t('intro.lines.start_drag_endpoint'));
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
reveal(box, t('intro.lines.start_drag_endpoint'), { duration: 0 });
|
||||
|
||||
var entity = context.entity(woodRoadEndId);
|
||||
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 2) {
|
||||
continueTo(finishDragEndpoint);
|
||||
}
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function finishDragEndpoint() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
|
||||
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
|
||||
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
reveal(box, t('intro.lines.finish_drag_endpoint'));
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
reveal(box, t('intro.lines.finish_drag_endpoint'), { duration: 0 });
|
||||
|
||||
var entity = context.entity(woodRoadEndId);
|
||||
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 2.5) {
|
||||
continueTo(startDragEndpoint);
|
||||
}
|
||||
});
|
||||
|
||||
context.on('enter.intro', function() {
|
||||
continueTo(startDragMidpoint);
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
context.on('enter.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function startDragMidpoint() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
|
||||
var padding = 80 * Math.pow(2, context.map().zoom() - 19);
|
||||
|
||||
var box = pad(woodRoadDragMidpoint, padding, context);
|
||||
reveal(box, t('intro.lines.start_drag_midpoint'));
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
var box = pad(woodRoadDragMidpoint, padding, context);
|
||||
reveal(box, t('intro.lines.start_drag_midpoint'), { duration: 0 });
|
||||
});
|
||||
|
||||
context.history().on('change.intro', function(changed) {
|
||||
if (changed.created().length === 1) {
|
||||
continueTo(continueDragMidpoint);
|
||||
}
|
||||
});
|
||||
|
||||
context.on('enter.intro', function(mode) {
|
||||
if (mode.id !== 'select') {
|
||||
// keep Wood Road selected so midpoint triangles are drawn..
|
||||
context.enter(modeSelect(context, [woodRoadId]));
|
||||
}
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
context.history().on('change.intro', null);
|
||||
context.on('enter.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function continueDragMidpoint() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
|
||||
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
|
||||
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
box.height += 400;
|
||||
var advance = function() { continueTo(play); };
|
||||
|
||||
reveal(box, t('intro.lines.continue_drag_midpoint'),
|
||||
{ buttonText: t('intro.ok'), buttonCallback: advance }
|
||||
);
|
||||
|
||||
context.map().on('move.intro drawn.intro', function() {
|
||||
if (!context.hasEntity(woodRoadId) || !context.hasEntity(woodRoadEndId)) {
|
||||
return continueTo(updateLine);
|
||||
}
|
||||
var box = pad(woodRoadDragEndpoint, padding, context);
|
||||
box.height += 400;
|
||||
reveal(box, t('intro.lines.continue_drag_midpoint'),
|
||||
{ duration: 0, buttonText: t('intro.ok'), buttonCallback: advance }
|
||||
);
|
||||
});
|
||||
|
||||
function continueTo(nextStep) {
|
||||
context.map().on('move.intro drawn.intro', null);
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function play() {
|
||||
dispatch.call('done');
|
||||
reveal('.intro-nav-wrap .chapter-building',
|
||||
@@ -316,7 +535,7 @@ export function uiIntroLine(context, reveal) {
|
||||
|
||||
chapter.enter = function() {
|
||||
context.history().reset('initial');
|
||||
context.map().zoom(18.5).centerEase(start);
|
||||
context.map().zoom(18.5).centerEase(tulipRoadStart);
|
||||
addLine();
|
||||
};
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ import { icon, pointBox } from './helper';
|
||||
|
||||
export function uiIntroNavigation(context, reveal) {
|
||||
var dispatch = d3.dispatch('done'),
|
||||
timeouts = [],
|
||||
hallId = 'n2061',
|
||||
timeouts = [];
|
||||
springSt = [-85.63585099140167, 41.942506848938926];
|
||||
|
||||
|
||||
var chapter = {
|
||||
@@ -174,7 +175,6 @@ export function uiIntroNavigation(context, reveal) {
|
||||
|
||||
|
||||
function selectedStreet() {
|
||||
var springSt = [-85.63585099140167, 41.942506848938926];
|
||||
context.map().centerEase(springSt);
|
||||
|
||||
timeout(function() {
|
||||
|
||||
Reference in New Issue
Block a user