簡體   English   中英

我們如何在按鈕單擊時添加多個動畫箭頭圖標

[英]How we can add multiple animated arrow icon on button click

我們正在嘗試在單擊按鈕時在單行字符串上添加多個動畫箭頭圖標,就像當我們單擊開始按鈕然后在線字符串上添加一個動畫箭頭圖標時,當我們再次單擊開始按鈕然后在這些行字符串上添加新的動畫箭頭圖標和繼續運行上一個箭頭。

點擊此處查看圖片

import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Map from 'ol/Map';
import Point from 'ol/geom/Point';
import Polyline from 'ol/format/Polyline';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View';
import OSM from 'ol/source/OSM';
import {Icon, Stroke, Style} from 'ol/style';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {getVectorContext} from 'ol/render';

const center = [-5639523.95, -3501274.52];
const map = new Map({
  target: document.getElementById('map'),
  view: new View({
    center: center,
    zoom: 10,
    minZoom: 2,
    maxZoom: 19,
  }),
  layers: [
    new TileLayer({
      source: new OSM(), 
    }),
  ],
});

// The polyline string is read from a JSON similiar to those returned
// by directions APIs such as Openrouteservice and Mapbox.
fetch('data/polyline/route.json').then(function (response) {
  response.json().then(function (result) {
    const polyline = result.routes[0].geometry;

    const route = new Polyline({
      factor: 1e6,
    }).readGeometry(polyline, {
      dataProjection: 'EPSG:4326',
      featureProjection: 'EPSG:3857',
    });

    const routeFeature = new Feature({
      type: 'route',
      geometry: route,
    });
    const startMarker = new Feature({
      type: 'icon',
      geometry: new Point(route.getFirstCoordinate()),
    });
    const endMarker = new Feature({
      type: 'icon',
      geometry: new Point(route.getLastCoordinate()),
    });
    const position = startMarker.getGeometry().clone();
    const geoMarker = new Feature({
      type: 'geoMarker',
      geometry: position,
    });

    const styles = {
      route: new Style({
        stroke: new Stroke({
          width: 6,
          color: [237, 212, 0, 0.8],
        }),
      }),
      icon: new Style({
        image: new Icon({
          anchor: [0.5, 1],
          src: 'data/icon.png',
        }),
      }),
      geoMarker: new Style({
        image: new Icon({
          src:
            'https://cdn1.iconfinder.com/data/icons/basic-ui-elements-color-round/3/19-32.png',
          rotation: getAngleAt(route, 0) + Math.PI / 2,
        }),
      }),
    };

    const vectorLayer = new VectorLayer({
      source: new VectorSource({
        features: [routeFeature, startMarker, endMarker],
      }),
      style: function (feature) {
        return styles[feature.get('type')];
      },
    });
    map.addLayer(vectorLayer);

    const vectorLayer1 = new VectorLayer({
      source: new VectorSource({
        features: [geoMarker],
      }),
      style: function (feature) {
        return styles[feature.get('type')];
      },
    });

    const speedInput = document.getElementById('speed');
    const startButton = document.getElementById('start-animation');
    let animating = false;
    let distance = 0;
    let lastTime;

    function getAngleAt(lineString, distance) {
      const length = lineString.getLength();
      const coordinates = lineString.getCoordinates();
      for (let i = 1, len = coordinates.length; i <= len; ++i) {
        if (
          new LineString(coordinates.slice(0, i + 1)).getLength() >=
          length * distance
        ) {
          return -Math.atan2(
            coordinates[i][1] - coordinates[i - 1][1],
            coordinates[i][0] - coordinates[i - 1][0]
          );
        }
      }
    }

    function moveFeature(event) {
      const speed = Number(speedInput.value);
      const time = event.frameState.time;
      const elapsedTime = time - lastTime;
      distance = (distance + (speed * elapsedTime) / 1e6) % 2;
      lastTime = time;
      const lineDistance = distance / 2 > 1 ? (2 - distance) / 2 : distance / 2;
      const direction = distance / 2 > 1 ? -Math.PI / 2 : Math.PI / 2;
      const currentCoordinate = route.getCoordinateAt(lineDistance);
      const angle = getAngleAt(route, lineDistance) + direction;
      styles.geoMarker.getImage().setRotation(angle);
      position.setCoordinates(currentCoordinate);
      const vectorContext = getVectorContext(event);
      vectorContext.setStyle(styles.geoMarker);
      vectorContext.drawGeometry(position);
      // tell OpenLayers to continue the postrender animation
      map.render();
    }

    function startAnimation() {
      animating = true;
      lastTime = Date.now();
      vectorLayer.on('postrender', moveFeature);
      // hide geoMarker and trigger map render through change event
      geoMarker.setGeometry(null);
    }


    startButton.addEventListener('click', function () {
      if (animating) {
        startAnimation();
      } else {
        map.addLayer(vectorLayer1);
        startAnimation();
      }
    });
  });
});

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Marker Animation</title>
    <link rel="stylesheet" href="node_modules/ol/ol.css">
    <style>
      .map {
        width: 100%;
        height: 400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <label for="speed">
      speed:&nbsp;
      <input id="speed" type="range" min="10" max="999" step="10" value="60">
    </label>
    <button id="start-animation">Start Animation</button>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://unpkg.com/elm-pep@1.0.6/dist/elm-pep.js"></script>
    <script type="module" src="main.js"></script>
  </body>
</html>

我們嘗試使用此代碼在單擊按鈕時添加動畫箭頭圖標,但我們沒有獲得有關如何添加它的任何解決方案。

請查看我的圖像以了解我想要的內容。

最簡單的方法是在每次發射新箭頭時添加時間和距離數組,然后您可以循環移動每個箭頭。

const lastTimes = [];
function moveFeature(event) {
  const speed = Number(speedInput.value);
  const time = event.frameState.time;
  for (let i = 0, ii = lastTimes.length; i < ii; ++i) {
    let {lastTime, distance} = lastTimes[i];
    const elapsedTime = time - lastTime;
    distance = (distance + (speed * elapsedTime) / 1e6) % 2;
    lastTime = time;
    lastTimes[i] = {lastTime, distance};
    const lineDistance = distance > 1 ? 2 - distance : distance;
    const direction = distance > 1 ? -Math.PI / 2 : Math.PI / 2;
    const currentCoordinate = route.getCoordinateAt(lineDistance);
    const angle = getAngleAt(route, lineDistance) + direction;
    styles.geoMarker.getImage().setRotation(angle);
    position.setCoordinates(currentCoordinate);
    const vectorContext = getVectorContext(event);
    vectorContext.setStyle(styles.geoMarker);
    vectorContext.drawGeometry(position);
  }
  // tell OpenLayers to continue the postrender animation
  map.render();
}

function startAnimation() {
  lastTimes.push({lastTime: Date.now(), distance: 0});
  if (!animating) {
    animating = true;
    //startButton.textContent = 'Stop Animation';
    vectorLayer.on('postrender', moveFeature);
    // hide geoMarker and trigger map render through change event
    geoMarker.setGeometry(null);
  }
}

https://codesandbox.io/s/feature-move-animation-forked-t2e6et

您可能還想刪除已到達行尾的條目?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM