JSFiddle - React, Tailwind, and code Playground
by fxi
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/nipplejs.min.js"></script>
<script src="https://app.staging.mapx.org/sdk/mxsdk.umd.js"></script>
<h1>Control the map with a joystick</h1>
<h3>( in static mode )</h3>
<div class="container">
<div class="pane-left item">
<p>Joystick</p>
<div class="ctrl" id="ctrlDirection"></div>
<!-- <p>Height & pitch</p>-->
<!--<div class="ctrl" id="ctrlHeightPitch"></div>-->
</div>
<div id="mapx" class="mapx pane-right item"></div>
</div>
CSS
.ctrl {
width: 200px;
height: 200px;
background: #ccc;
border-radius: 30px;
cursor: grab;
position: relative;
}
html,
body {
font-family: helvetica;
}
.container {
width: 100%;
min-height: 500px;
max-height: 800px;
display: flex;
}
.pane-left {
background: #eee;
font-size: 0.8em;
padding: 0 1em;
width: 200px;
display: flex;
flex-direction: column;
max-height: 100%;
overflow-y: auto;
}
#output {
display: none;
position: fixed;
bottom: 1em;
left: 0;
right: 0;
height: 200px;
border: 1px solid #ccc;
background-color: #fff;
padding: 0 1em 1.5em 1em;
}
#output .content {
max-height: 120px;
overflow: auto;
}
#output .content img {
max-width: 100%;
}
#output .close {
position: absolute;
bottom: 1em;
}
.pane-right {
flex-grow: 1;
}
#actions ul {
padding-left: 1em;
}
#actions .active {
font-weight: bold;
}
JavaScript
const conf = {
ctrlAIsUsed: false,
ctrlBIsUsed: false,
center: {lng:6.197, lat: 46.2},
offset: [0, 0],
pitch: 55,
bearing: -111.19,
zoom: 11.91,
delta: {x: 0, y: 0, z: 0, p: 0, b: 0}
};
const mapx = new mxsdk.Manager({
container: document.getElementById('mapx'),
url: {
host: 'app.staging.mapx.org',
port: 443,
protocol: 'https'
},
static: false,
verbose: false,
params: {
closePanels: true,
lat: conf.center.lat,
lng: conf.center.lng,
zoom: conf.zoom,
views: []
}
});
const elCtrlA = document.getElementById('ctrlDirection');
const ctrlA = nipplejs.create({
zone: elCtrlA,
mode: 'static',
position: {top: '50%', left: '50%'}
});
mapx.on('ready', main);
async function main() {
await mapx.ask('set_mode_3d', {action: 'show'});
await mapx.ask('set_mode_aerial', {action: 'show'});
/**
* initial rendering
*/
await mapx.ask('map', {
method: 'jumpTo',
parameters: [
{
bearing: conf.bearing,
zoom: conf.zoom,
center: conf.center,
pitch: conf.pitch
},
{duration: 0}
]
});
/**
* Directional input
*/
ctrlA.on('move', (e, d) => {
conf.delta.b = d.vector.x;
conf.delta.y = d.vector.y * 10;
});
ctrlA.on('start', () => {
conf.ctrlAIsUsed = true;
render();
});
ctrlA.on('end', () => {
conf.ctrlAIsUsed = false;
conf.delta.b = 0;
conf.delta.y = 0;
});
}
async function render(force) {
const skip = conf.rendering || (!conf.ctrlAIsUsed && !conf.ctrlBIsUsed);
if (skip && !force) {
return;
}
conf.rendering = true;
conf.bearing += conf.delta.b;
conf.offset[1] = -conf.delta.y;
await mapx.ask('map', {
method: 'jumpTo',
parameters: [
{
bearing: conf.bearing
},
{duration: 0}
]
});
await mapx.ask('map', {
method: 'panBy',
parameters: [conf.offset, {duration: 0}]
});
await nextFrame();
conf.rendering = false;
await...