Анимация трехмерного объекта случайным образом в mapbox с использованием Tween. js - PullRequest
1 голос
/ 15 марта 2020

Я начал с mapbox и пытаюсь анимировать трехмерный объект случайным образом, используя Tween. js. До сих пор мне удавалось перемещать объекты по прямым линиям только по определенным путям. Проблема в том, что эта часть: .to({ x: 300, y: 200 }, time) не работает с mapbox.

Я анимировал объекты, просто используя функцию onUpdate() Tween. js.

Я хочу перемещать объект случайным образом и в определенной области c только на медленной скорости. Кто-нибудь может мне помочь, пожалуйста?

var longitude, latitude, diff, map;

$(document).ready(function() {
  navigator.geolocation.getCurrentPosition(success, error, options);
});

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0,
  desiredAccuracy: 1
};

function success(pos) {
  var crd = pos.coords;

  console.log('Your current position is:', crd);
  console.log(`More or less ${crd.accuracy} meters.`);

  longitude = crd.longitude;
  latitude = crd.latitude;
  diff = crd.accuracy;

  console.log(`Latitude : ${latitude}`);
  console.log(`Longitude: ${longitude}`);

  model();
  showmap(maploaded);
}

function temp(pos) {
  var crd = pos.coords;

  console.log('Your current position is:', crd);
  console.log(`Latitude : ${crd.latitude}`);
  console.log(`Longitude: ${crd.longitude}`);
  console.log(`More or less ${crd.accuracy} meters.`);

  longitude = 77.034042;
  latitude = 28.450460;

  diff = crd.accuracy;
  console.log(`Latitude : ${latitude}`);
  console.log(`Longitude: ${longitude}`);
}

function error(err) {
  console.log(`ERROR(${err.code}): ${err.message}`);
}

function onProgress() {
  console.log(`Inside onProgress`);
}

function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition);
  } else {
    console.log("Geolocation is not supported by this browser.");
  }
}

function showmap(callback) {
  mapboxgl.accessToken = 'key';
  map = new mapboxgl.Map({
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [longitude, latitude],
    zoom: 17.6,
    pitch: 95,
    bearing: -17.6,
    container: 'map',
    antialias: false,
  });

  var geojson = {
    'type': 'FeatureCollection',
    'features': [{
      'type': 'Feature',
      'geometry': {
        'type': 'Point',
        'coordinates': [longitude, latitude]
      },
      'properties': {
        'title': 'Mapbox',
        'description': 'Park Centra'
      }
    }]
  };

  map.on('load', function() {
    // Insert the layer beneath any symbol layer.
    console.log("map loaded");
    document.getElementById('info').innerHTML = JSON.stringify(longitude + " : : " + latitude + " : : " + diff);
    var layers = map.getStyle().layers;
    var labelLayerId;

    for (var i = 0; i < layers.length; i++) {
      if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
        labelLayerId = layers[i].id;
        break;
      }
    }

    map.addLayer(customLayer, 'waterway-label');
    map.addLayer({
        'id': '3d-buildings',
        'source': 'composite',
        'source-layer': 'building',
        'filter': ['==', 'extrude', 'true'],
        'type': 'fill-extrusion',
        'minzoom': 15,
        'paint': {
          'fill-extrusion-color': '#aaa',
          // use an 'interpolate' expression to add a smooth transition effect to the
          // buildings as the user zooms in
          'fill-extrusion-height': [
            'interpolate', ['linear'],
            ['zoom'],
            15,
            0,
            15.05, ['get', 'height']
          ],
          'fill-extrusion-base': [
            'interpolate', ['linear'],
            ['zoom'],
            15,
            0,
            15.05, ['get', 'min_height']
          ],
          'fill-extrusion-opacity': 0.6
        }
      },
      labelLayerId
    );
  });
}

function maploaded() {
  console.log("Inside maploaded");
}

var modelOrigin;
var modelAltitude;
var modelRotate;
var modelAsMercatorCoordinate;
var modelTransform;
var THREE;
var customLayer;

function model() {
  // parameters to ensure the model is georeferenced correctly on the map
  //var modelOrigin = [77.052024, 28.459822];
  modelOrigin = [longitude, latitude];
  modelAltitude = 0;
  modelRotate = [Math.PI / 2, 0, 0];

  modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
    modelOrigin,
    modelAltitude
  );

  // transformation parameters to position, rotate and scale the 3D model onto the map
  modelTransform = {
    translateX: modelAsMercatorCoordinate.x,
    translateY: modelAsMercatorCoordinate.y,
    translateZ: modelAsMercatorCoordinate.z,
    rotateX: modelRotate[0],
    rotateY: modelRotate[1],
    rotateZ: modelRotate[2],
    /* Since our 3D model is in real world meters, a scale transform needs to be
     * applied since the CustomLayerInterface expects units in MercatorCoordinates.
     */
    scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
  };

  THREE = window.THREE;

  // configuration of the custom layer for a 3D model per the CustomLayerInterface
  customLayer = {
    id: '3d-model',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function(map, gl) {
      this.camera = new THREE.Camera();
      this.scene = new THREE.Scene();

      // create two three.js lights to illuminate the model
      var directionalLight = new THREE.DirectionalLight(0xffffff);
      directionalLight.position.set(0, -70, 100).normalize();
      this.scene.add(directionalLight);

      var directionalLight2 = new THREE.DirectionalLight(0xffffff);
      directionalLight2.position.set(0, 70, 100).normalize();
      this.scene.add(directionalLight2);

      // use the three.js GLTF loader to add the 3D model to the three.js scene
      var loader = new THREE.GLTFLoader();
      loader.load('https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf', function(gltf) {
        this.scene.add(gltf.scene);
      }.bind(this));
      var pre = "0.00000000",
        post = "0000000"
      var val = 5;
      var time = 10000;

      const tween = new TWEEN.Tween(modelTransform) // Create a new tween that modifies 'coords'.
        .to({
          x: 300,
          y: 200
        }, time) // Move to (300, 200) in 1 second.
        .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
        .onUpdate(() => { // Called after tween.js updates 'coords'.
          modelTransform.translateX += parseFloat(pre + val + post);
        });

      const tween2 = new TWEEN.Tween(modelTransform) // Create a new tween that modifies 'coords'.
        .to({
          x: 300,
          y: 200
        }, time) // Move to (300, 200) in 1 second.
        .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
        .onUpdate(() => { // Called after tween.js updates 'coords'.
          modelTransform.translateX -= parseFloat(pre + val + post);
        });

      const tween3 = new TWEEN.Tween(modelTransform) // Create a new tween that modifies 'coords'.
        .to({
          x: 300,
          y: 200
        }, time) // Move to (300, 200) in 1 second.
        .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
        .onUpdate(() => { // Called after tween.js updates 'coords'.
          modelTransform.translateY -= parseFloat(pre + val + post);
        });

      const tween4 = new TWEEN.Tween(modelTransform) // Create a new tween that modifies 'coords'.
        .to({
          x: 300,
          y: 200
        }, time) // Move to (300, 200) in 1 second.
        .easing(TWEEN.Easing.Quadratic.Out) // Use an easing function to make the animation smooth.
        .onUpdate(() => { // Called after tween.js updates 'coords'.
          modelTransform.translateY += parseFloat(pre + val + post);
        });

      tween.chain(tween2);
      tween2.chain(tween3);
      tween3.chain(tween4);
      tween4.chain(tween);
      tween.start(); // Start the tween immediately.

      requestAnimationFrame(animate);

      this.map = map;

      // use the Mapbox GL JS map canvas for three.js
      this.renderer = new THREE.WebGLRenderer({
        canvas: map.getCanvas(),
        context: gl,
        antialias: true
      });

      this.renderer.autoClear = false;
    },
    render: function(gl, matrix) {
      var rotationX = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(1, 0, 0),
        modelTransform.rotateX
      );

      var rotationY = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 1, 0),
        modelTransform.rotateY
      );

      var rotationZ = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 0, 1),
        modelTransform.rotateZ
      );

      var m = new THREE.Matrix4().fromArray(matrix);
      var l = new THREE.Matrix4().makeTranslation(
        modelTransform.translateX,
        modelTransform.translateY,
        modelTransform.translateZ
      ).scale(
        new THREE.Vector3(
          modelTransform.scale * 3, -modelTransform.scale * 3,
          modelTransform.scale * 3
        )
      ).multiply(rotationX).multiply(rotationY).multiply(rotationZ);

      this.camera.projectionMatrix = m.multiply(l);
      this.renderer.state.reset();
      this.renderer.render(this.scene, this.camera);
      this.map.triggerRepaint();
      // console.log("transform ",modelTransform);
    }
  };
}

// Setup the animation loop.
function animate(time) {
  requestAnimationFrame(animate);
  TWEEN.update(time);
}
body {
  margin: 0;
  padding: 0;
}

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

.marker {
  background-image: url("img/cross.png");
  background-size: cover;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  cursor: pointer;
}

.mapboxgl-popup {
  max-width: 200px;
}

.mapboxgl-popup-content {
  text-align: center;
  font-family: 'Open Sans', sans-serif;
}

#info {
  display: block;
  position: relative;
  margin: 0px auto;
  width: 50%;
  padding: 10px;
  border: none;
  border-radius: 3px;
  font-size: 12px;
  text-align: center;
  color: #222;
  opacity: 1;
  /*background: #fff;*/
}

#new {
  display: block;
  position: relative;
  width: 5%;
  height: 4%;
  margin: 3%;
}








Новый

1 Ответ

0 голосов
/ 15 марта 2020

Я не эксперт по трем. js и Tween. js. Но я заметил, что мне обычно нужно вызывать функцию TWEEN.update(); для render() для рендеринга анимации. Извините, что я не смог запустить ваш код.

render: function(gl, matrix) {
      Tween.update(); // or tween.update();
      var rotationX = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(1, 0, 0),
        modelTransform.rotateX
      );

      var rotationY = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 1, 0),
        modelTransform.rotateY
      );

      var rotationZ = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 0, 1),
        modelTransform.rotateZ
      );

      var m = new THREE.Matrix4().fromArray(matrix);
      var l = new THREE.Matrix4().makeTranslation(
        modelTransform.translateX,
        modelTransform.translateY,
        modelTransform.translateZ
      ).scale(
        new THREE.Vector3(
          modelTransform.scale * 3, -modelTransform.scale * 3,
          modelTransform.scale * 3
        )
      ).multiply(rotationX).multiply(rotationY).multiply(rotationZ);

      this.camera.projectionMatrix = m.multiply(l);
      this.renderer.state.reset();
      this.renderer.render(this.scene, this.camera);
      this.map.triggerRepaint();
      // console.log("transform ",modelTransform);
    }
  };
...