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...