Skip to content

Commit 14a9ed3

Browse files
committed
jump to location functionality
1 parent c40669d commit 14a9ed3

File tree

9 files changed

+207
-84
lines changed

9 files changed

+207
-84
lines changed

src/App.css

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ label .badge{position:relative;top:2px;}
107107
.drop-menu{position:absolute;background-color:#FFF;color:#273237;
108108
padding:0.25rem;border-radius:0.25rem;z-index:999;border:1px solid #8FA3AE;
109109
left:0;right:0;}
110+
.drop-menu-locations{top:6px;right:45px;left:auto;width:140px;position:fixed;z-index:10000;}
110111

111112
.content-title-options .drop-menu{top:20px;right:0;}
112113
.drop-item{color:#273237;white-space:nowrap;font-size:0.8rem;padding:0.25rem 0.5rem;cursor:pointer;}
@@ -115,11 +116,6 @@ label .badge{position:relative;top:2px;}
115116

116117
.dropdown-cover{position:fixed;top:0;bottom:0;left:0;right:0;background-color:transparent;}
117118

118-
.dropdown-menu{padding:0;}
119-
.dropdown-menu a{padding:0.25rem 0.5rem;font-size:0.8rem;}
120-
.dropdown-menu a.active{background-color:#EEEEEE;color:#273237;}
121-
.dropdown-divider{margin:0.15rem 0;}
122-
123119
.exp-ml{margin-left:12px;}
124120
.exp-arrow{left:-16px;top:10px;border-radius:4px;width:14px;height:14px;
125121
position:relative;color:#FFFFFF;background-color:#273237;cursor:pointer;}
@@ -228,7 +224,7 @@ label .badge{position:relative;top:2px;}
228224

229225
.mapboxgl-ctrl-icon.active{background-color:#00ACC1;color:#FFF;}
230226
.mapboxgl-ctrl-icon.active:hover{background-color:#0197A7!important;color:#FFF;}
231-
.mapboxgl-ctrl-icon i{position:relative;top:-1px;}
227+
.mapboxgl-ctrl-icon i{position:relative;top:1px;font-size:1rem;}
232228

233229
.mapboxgl-popup-close-button{color:#AEAEAE;}
234230
.mapboxgl-popup-close-button:hover{color:#747474;}
@@ -312,6 +308,7 @@ label .badge{position:relative;top:2px;}
312308

313309
.tooltip{font-size:0.7rem;}
314310
.tooltip-source{position:absolute;bottom:0;left:0;right:0;text-align:center;height:0;}
311+
.tooltip-source.tooltip-origin-left{bottom:0;left:0;top:0;text-align:center;width:0;}
315312
.tooltip-point{display:inline-block;position:relative;}
316313

317314
.tooltip-bubble{position:absolute;right:-11px;z-index:1000;top:-4px;
@@ -330,6 +327,10 @@ label .badge{position:relative;top:2px;}
330327
.tooltip-trigger:hover .tooltip-source:hover .tooltip-bubble{display:none;}
331328
.tooltip-trigger{position:relative;}
332329

330+
.tooltip-source.tooltip-origin-left .tooltip-bubble {right:11px;top:-15px;}
331+
.tooltip-source.tooltip-origin-left .tooltip-bubble span:after{right:-8px;top:11px;width:6px;height:8px;
332+
border-left:4px solid #1B2124;border-bottom:4px solid transparent;border-top:4px solid transparent;}
333+
333334
.w-max-500{max-width:500px;}
334335

335336
#map{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;}

src/component/Field/FieldAC.jsx

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -159,39 +159,39 @@ class FieldAC extends React.Component {
159159
<div className="form-group mb-2 position-relative">
160160
{label && <label className="mb-0">{label}</label>}
161161
<div className="position-relative">
162-
<Dropdown handleClose={()=>this.handleBlur(false)} open={focused}>
163-
<input type="text" className={inputClass? inputClass: 'form-control'} placeholder={placeholder}
164-
onChange={this.handleInputChange}
165-
onFocus={this.handleFocus}
166-
onKeyUp={this.handleKeyUp}
167-
autoFocus={autoFocus}
168-
value={inputValue}
169-
/>
170-
{focused && (
171-
<div className="drop-menu" data-boundary="window">
172-
{options.map((exp,i)=>{
173-
174-
if (exp.value.indexOf(inputValue) === -1) return null
175-
count++
176-
if (count > maxDropdowns) return null
177-
178-
let className = 'drop-item'
179-
if (selected === exp.value) className += ' active'
180-
181-
return (
182-
<div
183-
className={className}
184-
onClick={(e)=>{this.handleSelect(exp.value)}}
185-
key={exp.value}>
186-
187-
{exp.value}
188-
</div>
189-
)
190-
})}
191-
</div>
192-
)}
193-
194-
</Dropdown>
162+
<Dropdown handleClose={()=>this.handleBlur(false)} open={focused}>
163+
<input type="text" className={inputClass? inputClass: 'form-control'} placeholder={placeholder}
164+
onChange={this.handleInputChange}
165+
onFocus={this.handleFocus}
166+
onKeyUp={this.handleKeyUp}
167+
autoFocus={autoFocus}
168+
value={inputValue}
169+
/>
170+
{focused && (
171+
<div className="drop-menu" data-boundary="window">
172+
{options.map((exp,i)=>{
173+
174+
if (exp.value.indexOf(inputValue) === -1) return null
175+
count++
176+
if (count > maxDropdowns) return null
177+
178+
let className = 'drop-item'
179+
if (selected === exp.value) className += ' active'
180+
181+
return (
182+
<div
183+
className={className}
184+
onClick={(e)=>{this.handleSelect(exp.value)}}
185+
key={exp.value}>
186+
187+
{exp.value}
188+
</div>
189+
)
190+
})}
191+
</div>
192+
)}
193+
194+
</Dropdown>
195195

196196
</div>
197197
</div>

src/component/Icon/constants.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ const icons = {
3030
'layer-line': 'fa-pen-nib',
3131
'layer-raster': 'fa-satellite',
3232
'layer-symbol': 'fa-text',
33-
'layer-fill-extrusion': 'fa-text',
33+
location: 'fa-location',
34+
3435
'map-focus': 'fa-map-marker',
3536
refresh: 'fa-redo',
3637
remove: 'fa-trash',

src/component/Map/MapMapbox.jsx

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ import modelStyle from '../../model/style'
1010
import MapboxGl from 'mapbox-gl'
1111
import 'mapbox-gl/dist/mapbox-gl.css'
1212

13+
import constants from './constants'
1314
import utilUrl from '../../utility/utilUrl'
1415

16+
import Dropdown from '../Dropdown'
1517
import MapMapboxControls from './MapMapboxControls'
1618

1719
class CustomControls {
20+
handleLocationToggle = null
1821
onAdd(map) {
1922
this._container = document.createElement('div')
20-
ReactDOM.render(<MapMapboxControls map={map}/>,this._container)
23+
ReactDOM.render(<MapMapboxControls handleLocationToggle={this.handleLocationToggle} map={map}/>,this._container)
2124
return this._container
2225
}
2326
onRemove() {
@@ -110,8 +113,10 @@ class MapMapbox extends React.Component {
110113
hash:true
111114
})
112115

116+
const Controls = new CustomControls({})
117+
Controls.handleLocationToggle = this.handleLocationToggle
113118

114-
map.addControl(new CustomControls({}))
119+
map.addControl(Controls)
115120

116121
map.addControl(new MapboxGl.AttributionControl({
117122
compact: true
@@ -221,6 +226,7 @@ class MapMapbox extends React.Component {
221226
this.state = {
222227
debugLines: null,
223228
mapLoaded: false,
229+
locationShow: false,
224230
}
225231

226232
this.container = null // node to put map in
@@ -238,6 +244,29 @@ class MapMapbox extends React.Component {
238244
modelMap.actions.setFocus({point})
239245
}
240246

247+
handleLocationSelect = (location)=>{
248+
this.map.flyTo({
249+
center: [location.lng, location.lat],
250+
zoom: location.zoom
251+
})
252+
}
253+
254+
handleLocationClose = ()=>{
255+
this.setState({
256+
locationShow:false
257+
})
258+
}
259+
260+
handleLocationToggle = (show)=>{
261+
const {locationShow} = this.state
262+
263+
if (locationShow){
264+
this.setState({locationShow:false})
265+
} else {
266+
this.setState({locationShow:true})
267+
}
268+
}
269+
241270
handleMapError = (error)=>{
242271
const {style} = this.props
243272

@@ -288,8 +317,31 @@ class MapMapbox extends React.Component {
288317
}
289318

290319
render (){
320+
const {locationShow} = this.state
321+
291322
return (
292-
<div id="map" ref={el => this.container = el}></div>
323+
<React.Fragment>
324+
<div id="map" ref={el => this.container = el}></div>
325+
<Dropdown handleClose={()=>this.handleLocationClose()} open={locationShow}>
326+
{locationShow && (
327+
<div className="drop-menu drop-menu-locations">
328+
{constants.locations.map((loc,i)=>{
329+
330+
const className = 'drop-item interactive'
331+
return (
332+
<div
333+
className={className}
334+
onClick={(e)=>{this.handleLocationSelect(loc)}}
335+
key={i}>
336+
337+
{loc.label}
338+
</div>
339+
)
340+
})}
341+
</div>
342+
)}
343+
</Dropdown>
344+
</React.Fragment>
293345
)
294346
}
295347

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,58 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33
import Icon from '../Icon'
4+
import Tooltip from '../Tooltip'
45

5-
export default class MapMapboxControls extends React.Component {
6-
static propTypes = {
7-
map:PropTypes.object
8-
}
6+
class MapMapboxControls extends React.Component {
97

108
constructor (props){
119
super(props)
12-
const {map} = props
1310

1411
this.state = {
15-
debugLines:false
16-
}
17-
18-
this.handle = {
19-
debugLinesToggle:()=>{
20-
if (this.state.debugLines){
21-
this.setState({debugLines:false})
22-
map.showTileBoundaries = false
23-
} else {
24-
this.setState({debugLines:true})
25-
map.showTileBoundaries = true
26-
}
27-
}
28-
}
29-
30-
for (let i in this.handle){
31-
this.handle[i] = this.handle[i].bind(this)
12+
debugLines:false,
3213
}
3314
}
3415

35-
componentDidMount(){
36-
this.tooltip()
37-
}
16+
handleDebugLinesToggle = ()=>{
17+
const {map} = this.props,
18+
{debugLines} = this.state
3819

39-
tooltip(){
40-
//console.log('ref:',)
41-
//window.$(this.tooltipsRef).children().tooltip()
20+
if (debugLines){
21+
this.setState({debugLines:false})
22+
map.showTileBoundaries = false
23+
} else {
24+
this.setState({debugLines:true})
25+
map.showTileBoundaries = true
26+
}
4227
}
4328

4429
render (){
45-
46-
const className = 'mapboxgl-ctrl-icon'+(this.state.debugLines? ' active': '')
47-
48-
return <div className="mapboxgl-ctrl mapboxgl-ctrl-group" ref={ref => this.tooltipsRef = ref}>
49-
<button className={className} onClick={this.handle.debugLinesToggle} title="debug lines">
50-
<Icon icon={'debug-lines'}/>
51-
</button>
52-
</div>
30+
const {handleLocationToggle} = this.props,
31+
{debugLines} = this.state
32+
33+
return (
34+
<React.Fragment>
35+
<div className="mapboxgl-ctrl mapboxgl-ctrl-group tooltip-trigger">
36+
<button className={`mapboxgl-ctrl-icon`} onClick={handleLocationToggle}>
37+
<Icon icon={'location'}/>
38+
</button>
39+
<Tooltip direction={'left'} message={'jump to location'} origin={'left'}/>
40+
</div>
41+
<div className="mapboxgl-ctrl mapboxgl-ctrl-group tooltip-trigger">
42+
<button className={`mapboxgl-ctrl-icon ${debugLines? 'active': ''}`} onClick={this.handleDebugLinesToggle}>
43+
<Icon icon={'debug-lines'}/>
44+
</button>
45+
<Tooltip direction={'left'} message={`debug lines ${debugLines? 'off': 'on'}`} origin={'left'}/>
46+
</div>
47+
</React.Fragment>
48+
)
5349
}
5450

5551
}
52+
53+
MapMapboxControls.propTypes = {
54+
handleLocationToggle: PropTypes.func,
55+
map:PropTypes.object,
56+
}
57+
58+
export default MapMapboxControls

src/component/Map/constants.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const locations = [{
2+
"key":"sd",
3+
"label":"San Diego",
4+
"lat":32.72,
5+
"lng":-117.15,
6+
"zoom":11
7+
},{
8+
"key":"la",
9+
"label":"Los Angeles",
10+
"lat":34.04,
11+
"lng":-118.31,
12+
"zoom":11
13+
},{
14+
"key":"sf",
15+
"label":"San Francisco",
16+
"lat":37.77,
17+
"lng":-122.40,
18+
"zoom":11
19+
},{
20+
"key":"ny",
21+
"label":"New York",
22+
"lat":40.74,
23+
"lng":-74.0,
24+
"zoom":11
25+
},{
26+
"key":"dc",
27+
"label":"Washington, DC",
28+
"lat":38.88,
29+
"lng":-77.04,
30+
"zoom":11
31+
},{
32+
"key":"bs",
33+
"label":"Boston",
34+
"lat":42.36,
35+
"lng":-71.05,
36+
"zoom":11
37+
},{
38+
"key":"br",
39+
"label":"Berlin",
40+
"lat":52.51,
41+
"lng":13.36,
42+
"zoom":11
43+
},{
44+
"key":"tk",
45+
"label":"Tokyo",
46+
"lat":35.69,
47+
"lng":139.73,
48+
"zoom":11
49+
}]
50+
51+
export default {
52+
locations,
53+
}

src/component/Map/index.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ class Map extends React.Component {
1010
render (){
1111
const {focus, style} = this.props
1212

13-
return <MapMapbox focus={focus} style={style}/>
13+
return (
14+
<MapMapbox focus={focus} style={style}/>
15+
)
1416
}
1517
}
1618

0 commit comments

Comments
 (0)