Skip to content

Commit

Permalink
feature(Widgets): add a searchbar widget
Browse files Browse the repository at this point in the history
  • Loading branch information
mgermerie authored and gchoqueux committed Mar 15, 2022
1 parent 7775a04 commit 164b6ee
Show file tree
Hide file tree
Showing 7 changed files with 473 additions and 4 deletions.
3 changes: 2 additions & 1 deletion docs/config.json
Expand Up @@ -130,7 +130,8 @@
"Widgets": [
"Navigation",
"Minimap",
"Scale"
"Scale",
"Searchbar"
]
},
"tutorialSections": {
Expand Down
3 changes: 2 additions & 1 deletion examples/config.json
Expand Up @@ -81,7 +81,8 @@
"Widgets": {
"widgets_navigation": "Navigation",
"widgets_minimap": "Minimap",
"widgets_scale": "Scale"
"widgets_scale": "Scale",
"widgets_searchbar": "Searchbar"
},

"Plugins": {
Expand Down
79 changes: 79 additions & 0 deletions examples/css/widgets.css
Expand Up @@ -279,3 +279,82 @@
#widgets-scale.right-widget {
justify-content: flex-end;
}



/* ---------- SEARCHBAR WIDGET SETTINGS : --------------------------------------------------------------------------- */

#widgets-searchbar {
position: absolute;
z-index: 10;
}

#widgets-searchbar > form {
display: flex;
flex-direction: column;
margin: 0;
border-radius: 7px;
}
#widgets-searchbar.top-widget > form {
flex-direction: column;
}
#widgets-searchbar.bottom-widget > form {
flex-direction: column-reverse;
}
#widgets-searchbar > form.focus {
box-shadow: 0 0 10px #222222;
}



/* ---------- SEARCHBAR INPUT AND SUGGESTIONS : --------------------------------------------------------------------- */

#widgets-searchbar:not(.bottom-widget) form > *:last-child:not(:only-child),
#widgets-searchbar.bottom-widget form > *:first-child:not(:only-child) {
border-radius: 0 0 7px 7px;
}
#widgets-searchbar:not(.bottom-widget) form > *:first-child:not(:only-child),
#widgets-searchbar.bottom-widget form > *:last-child:not(:only-child) {
border-radius: 7px 7px 0 0;
}
#widgets-searchbar form > *:only-child {
border-radius: 7px;
}
#widgets-searchbar:not(.bottom-widget) form > *:not(:first-child):not(:last-child) {
border-bottom: none;
}
#widgets-searchbar.bottom-widget form > *:not(:first-child):not(:last-child) {
border-top: none;
}

#widgets-searchbar form > * {
box-sizing: border-box;
width: 100%;
padding: 0 10px;
background-color: #313336bb;
border: 1px solid #222222;
color: #ffffff;
font-family: Arial;
}

#widgets-searchbar form > input::placeholder {
color: #ffffff80;
}
#widgets-searchbar form > input:focus {
outline: none !important;
}

#widgets-searchbar form > div {
display: flex;
align-items: center;
}
#widgets-searchbar form > div.active {
background-color: #222222;
}
#widgets-searchbar form > div:hover {
cursor: pointer;
}

#widgets-searchbar form > div > p {
margin: 8px 0;
}
121 changes: 121 additions & 0 deletions examples/widgets_searchbar.html
@@ -0,0 +1,121 @@
<html>
<head>
<title>Itowns - Searchbar widget</title>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" type="text/css" href="css/example.css">
<link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">

<!-- Import stylesheet for itowns Widgets plugin -->
<link rel="stylesheet" type="text/css" href="css/widgets.css">

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
</head>
<body>
<!-- Create a container for itowns viewer -->
<div id="viewerDiv"></div>

<!-- Import iTowns source code -->
<script src="../dist/itowns.js"></script>
<script src="../dist/debug.js"></script>
<!-- Import iTowns Widgets plugin -->
<script src="../dist/itowns_widgets.js"></script>
<!-- Import iTowns LoadingScreen and GuiTools plugins -->
<script src="js/GUI/LoadingScreen.js"></script>
<script src="js/GUI/GuiTools.js"></script>


<script type="text/javascript">



// ---------- CREATE A GlobeView FOR SUPPORTING DATA VISUALIZATION : ----------

// Define camera initial position
const placement = {
coord: new itowns.Coordinates('EPSG:4326', 2.351323, 48.856712),
range: 6000,
tilt: 50,
}

// `viewerDiv` contains iTowns' rendering area (`<canvas>`)
const viewerDiv = document.getElementById('viewerDiv');

// Create a GlobeView
const view = new itowns.GlobeView(viewerDiv, placement);

// Setup loading screen and debug menu
setupLoadingScreen(viewerDiv, view);
const debugMenu = new GuiTools('menuDiv', view);



// ---------- DISPLAY CONTEXTUAL DATA : ----------

// Add one imagery layer to the scene. This layer's properties are defined in a json file, but it could be
// defined as a plain js object. See `Layer` documentation for more info.
itowns.Fetcher.json('layers/JSONLayers/Ortho.json').then((config) => {
config.source = new itowns.WMTSSource(config.source);
view.addLayer(
new itowns.ColorLayer(config.id, config),
).then(debugMenu.addLayerGUI.bind(debugMenu));
});

// Add two elevation layers, each with a different level of detail. Here again, each layer's properties are
// defined in a json file.
function addElevationLayerFromConfig(config) {
config.source = new itowns.WMTSSource(config.source);
view.addLayer(
new itowns.ElevationLayer(config.id, config),
).then(debugMenu.addLayerGUI.bind(debugMenu));
}
itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig);
itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig);



// ---------- ADD SEARCH BAR WIDGET : ----------

// Function that should be called when clicking a location suggestion.
function lookAtCoordinate(coordinates) {
view.controls.lookAtCoordinate({ coord: coordinates, range: 20000, tilt: 45, heading: 0 });
}

// Define options for geocoding service that should be used by the searchbar.
const geocodingOptions = {
url: new URL(
'https://wxs.ign.fr/ayxvok72rcocdyn8xyvy32og/ols/apis/completion?text=&type=StreetAddress,' +
'PositionOfInterest',
),
// As precised in the doc (http://www.itowns-project.org/itowns/docs/#api/Widgets/Searchbar), the parser
// method must parse the geocoding service response into a Map object. For each item of this Map, the
// key is a string that is displayed in the suggestions bellow the searchbar, and the value is whatever
// the user wants. The value is the parameter that is passed to the `onSelected` method when a
// suggestion is clicked. Here, we se the value as the `Coordinates` associated to the location.
parser: (response) => {
const map = new Map();
response.results.forEach(location => {
map.set(location.fulltext, new itowns.Coordinates('EPSG:4326', location.x, location.y));
});
return map;
},
onSelected: lookAtCoordinate,
}

// Create the searchbar
const searchbar = new itowns_widgets.Searchbar(view, geocodingOptions, {
// We want to display at maximum 15 location suggestions when typing the searchbar.
maxSuggestionNumber: 15,
});



// ---------- DEBUG TOOLS : ----------

debug.createTileDebugUI(debugMenu.gui, view);

</script>
</body>
</html>
1 change: 1 addition & 0 deletions utils/gui/Main.js
Expand Up @@ -2,3 +2,4 @@
export { default as Navigation } from './Navigation';
export { default as Minimap } from './Minimap';
export { default as Scale } from './Scale';
export { default as Searchbar } from './Searchbar';
5 changes: 3 additions & 2 deletions utils/gui/Minimap.js
Expand Up @@ -32,13 +32,14 @@ class Minimap extends Widget {
* @param {HTMLElement} [options.parentElement=view.domElement] The parent HTML container of the div
* which contains minimap widgets.
* @param {number} [options.size] The size of the minimap. It is a number
* that describing both width and height
* that describes both width and height
* in pixels of the minimap.
* @param {number} [options.width=150] The width in pixels of the minimap.
* @param {number} [options.height=150] The height in pixels of the minimap.
* @param {string} [options.position='bottom-left'] Defines which corner of the
* @param {string} [options.position='bottom-left'] Defines which position within the
* `parentElement` the minimap should be
* displayed to. Possible values are
* `top`, `bottom`, `left`, `right`,
* `top-left`, `top-right`, `bottom-left`
* and `bottom-right`. If the input value
* does not match one of these, it will
Expand Down

0 comments on commit 164b6ee

Please sign in to comment.