-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
5587 - make geolocation show geolocation #5629
Changes from 4 commits
02261c9
b7f0d86
b9ddfca
b010f42
83c0843
3755951
399e778
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { select as d3_select } from 'd3-selection'; | ||
|
||
import { svgPointTransform } from './helpers'; | ||
import { geoMetersToLat } from '../geo'; | ||
import { | ||
geoIdentity as d3_geoIdentity, | ||
geoPath as d3_geoPath, | ||
geoStream as d3_geoStream | ||
} from 'd3-geo'; | ||
import _throttle from 'lodash-es/throttle'; | ||
|
||
export function svgGeolocate(projection, context, dispatch) { | ||
var throttledRedraw = _throttle(function () { dispatch.call('change'); }, 1000); | ||
var minZoom = 12; | ||
var layer = d3_select(null); | ||
var _position; | ||
|
||
|
||
function init() { | ||
if (svgGeolocate.initialized) return; // run once | ||
svgGeolocate.enabled = false; | ||
svgGeolocate.initialized = true; | ||
} | ||
|
||
function showLayer() { | ||
layer.style('display', 'block'); | ||
} | ||
|
||
|
||
function hideLayer() { | ||
throttledRedraw.cancel(); | ||
layer | ||
.transition() | ||
.duration(250) | ||
.style('opacity', 0) | ||
.on('end', function () { }); | ||
} | ||
|
||
function layerOn() { | ||
layer | ||
.style('opacity', 0) | ||
.transition() | ||
.duration(250) | ||
.style('opacity', 1); | ||
|
||
} | ||
|
||
function layerOff() { | ||
layer.style('display', 'none'); | ||
} | ||
|
||
function transform(d) { | ||
return svgPointTransform(projection)(d); | ||
} | ||
|
||
function accuracy(accuracy, loc) { // converts accuracy to pixels... | ||
var degreesRadius = geoMetersToLat(accuracy), | ||
tangentLoc = [loc[0], loc[1] + degreesRadius], | ||
projectedTangent = projection(tangentLoc), | ||
projectedLoc = projection([loc[0], loc[1]]); | ||
|
||
return Math.round(projectedLoc[1] - projectedTangent[1]).toString(); // more south point will have higher pixel value... | ||
} | ||
|
||
function update() { | ||
var geolocation = { loc: [_position.coords.longitude, _position.coords.latitude] }, | ||
pixelAccuracy = accuracy(_position.coords.accuracy, geolocation.loc); | ||
|
||
var groups = layer.selectAll('.geolocations').selectAll('.geolocation') | ||
.data([geolocation]); | ||
|
||
groups.exit() | ||
.remove(); | ||
|
||
var pointsEnter = groups.enter() | ||
.append('g') | ||
.attr('class', 'geolocation'); | ||
|
||
pointsEnter | ||
.append('circle') | ||
.attr('id', 'geolocate-radius') | ||
.attr('dx', '0') | ||
.attr('dy', '0') | ||
.attr('fill', 'rgb(15,128,225)') | ||
.attr('fill-opacity', '0.3') | ||
.attr('r', '0'); | ||
|
||
pointsEnter | ||
.append('circle') | ||
.attr('dx', '0') | ||
.attr('dy', '0') | ||
.attr('fill', 'rgb(15,128,225)') | ||
.attr('stroke', 'white') | ||
.attr('stroke-width', '1.5') | ||
.attr('r', '6'); | ||
|
||
groups.merge(pointsEnter) | ||
.attr('transform', transform); | ||
|
||
d3_select('#geolocate-radius').attr('r', pixelAccuracy) | ||
} | ||
|
||
function drawLocation(selection) { | ||
var enabled = svgGeolocate.enabled; | ||
|
||
layer = selection.selectAll('.layer-geolocate') | ||
.data([0]); | ||
|
||
layer.exit() | ||
.remove(); | ||
|
||
var layerEnter = layer.enter() | ||
.append('g') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Forget what I said here.. If |
||
.attr('class', 'layer-geolocate') | ||
.style('display', enabled ? 'block' : 'none'); | ||
|
||
layerEnter | ||
.append('g') | ||
.attr('class', 'geolocations'); | ||
|
||
layer = layerEnter | ||
.merge(layer); | ||
|
||
if (enabled) { | ||
update(); | ||
} else { | ||
layerOff(); | ||
} | ||
} | ||
|
||
drawLocation.enabled = function (position, enabled) { | ||
if (!arguments.length) return svgGeolocate.enabled; | ||
_position = position; | ||
svgGeolocate.enabled = enabled; | ||
if (svgGeolocate.enabled) { | ||
showLayer(); | ||
layerOn(); | ||
} else { | ||
hideLayer(); | ||
} | ||
// dispatch.call('change'); | ||
return this; | ||
}; | ||
|
||
init(); | ||
return drawLocation; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ import { select as d3_select } from 'd3-selection'; | |
|
||
import { svgData } from './data'; | ||
import { svgDebug } from './debug'; | ||
import { svgGeolocate } from './geolocate'; | ||
import { svgStreetside } from './streetside'; | ||
import { svgMapillaryImages } from './mapillary_images'; | ||
import { svgMapillarySigns } from './mapillary_signs'; | ||
|
@@ -32,7 +33,8 @@ export function svgLayers(projection, context) { | |
{ id: 'mapillary-signs', layer: svgMapillarySigns(projection, context, dispatch) }, | ||
{ id: 'openstreetcam-images', layer: svgOpenstreetcamImages(projection, context, dispatch) }, | ||
{ id: 'debug', layer: svgDebug(projection, context, dispatch) }, | ||
{ id: 'touch', layer: svgTouch(projection, context, dispatch) } | ||
{ id: 'touch', layer: svgTouch(projection, context, dispatch) }, | ||
{ id: 'geolocate', layer: svgGeolocate(projection, context, dispatch) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh cool I see now.. Yeah geolocate should be before touch I think, so it doesn't steal the user's mouse clicks. |
||
]; | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ describe('iD.svgLayers', function () { | |
it('creates default data layers', function () { | ||
container.call(iD.svgLayers(projection, context)); | ||
var nodes = container.selectAll('svg .data-layer').nodes(); | ||
expect(nodes.length).to.eql(9); | ||
expect(nodes.length).to.eql(10); | ||
expect(d3.select(nodes[0]).classed('osm')).to.be.true; | ||
expect(d3.select(nodes[1]).classed('notes')).to.be.true; | ||
expect(d3.select(nodes[2]).classed('data')).to.be.true; | ||
|
@@ -36,6 +36,7 @@ describe('iD.svgLayers', function () { | |
expect(d3.select(nodes[6]).classed('openstreetcam-images')).to.be.true; | ||
expect(d3.select(nodes[7]).classed('debug')).to.be.true; | ||
expect(d3.select(nodes[8]).classed('touch')).to.be.true; | ||
expect(d3.select(nodes[9]).classed('geolocate')).to.be.true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here too |
||
}); | ||
|
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not 100% sure but I don't think this code should ever need to dispatch
change
.. This forces everything to redraw. Maybe this code could maintain its own timer to refresh the location circle sometimes.