在 OpenLayers 3 中为多个标记设置动画

animating multiple markers in OpenLayers 3

我正在使用 OpenLayers 创建横跨太平洋的海洋动物迁徙动画。我希望每个 "animal" 都能随着时间的推移追踪轨迹。在轨道的头部将是代表该动物的 icon/marker/overlay。我已经让它适用于一条轨道,但尽管我能够将每只动物的轨道作为逐段构造的线串来增长,但我无法为每条轨道专门分配一个 icon/marker/overlay。相反,我只能在一个轨道上为一个图标设置动画。其余的线串轨道继续进行,但在追踪时它们在轨道的头部没有图标。这是我的代码。任何帮助表示赞赏。

    // draw tracks

    function makeLineString(id, species, multipointCoords, tracksTime) {

        // layer structure and style assignment

        var trackSource = new ol.source.Vector();

        var trackLayer = new ol.layer.Vector({
            source: trackSource,
            style: BWtrackStyle
        });
        map.addLayer(trackLayer);

        var lineString = new ol.geom.LineString([
            ol.proj.fromLonLat(multipointCoords[0][0])
        ]);

        var trackFeature = new ol.Feature({
            geometry: lineString
        });

        if (species === "Blue Whale") {
            trackFeature.setStyle([BWtrackStyle, shadowStyle]);
        };

        trackSource.addFeature(trackFeature);

        // icon-marker-overlay styling

        var BW2205005icon = document.getElementById('BW2205005icon');
        var BW2205005marker = new ol.Overlay({
            positioning: 'center-center',
            offset: [0, 0],
            element: BW2205005icon,
            stopEvent: false
        });
        map.addOverlay(BW2205005marker);

        var BW2205012icon = document.getElementById('BW2205012icon');
        var BW2205012marker = new ol.Overlay({
            positioning: 'center-center',
            offset: [0, 0],
            element: BW2205012icon,
            stopEvent: false
        });
        map.addOverlay(BW2205012marker);

        var coordinate, i = 1,
            length = multipointCoords[0].length;

        var currentTime = tracksTime[0][0];
        var nextTime = tracksTime[0][1];
        speedOption = 100; // the highter this value, the faster the tracks, see next line
        var transitionTime = (nextTime - currentTime) / speedOption;
        console.log(transitionTime);

        var timer;

        timer = setInterval(function() {
            segmentConstruction(id, multipointCoords, tracksTime);
        }, transitionTime);

        function segmentConstruction(id, multipointCoords, tracksTime) {
            coordinate = ol.proj.fromLonLat(multipointCoords[0][i]);
            lineString.appendCoordinate(coordinate);
            console.log(id);

            if (id === "BW2205005") {
                BW2205005marker.setPosition(coordinate);
            } else {

                BW2205012marker.setPosition(coordinate);
            };

            if (i >= length - 1) {
                clearInterval(timer);
            } else {
                i++;
                clearInterval(timer);
                currentTime = tracksTime[0][i];
                nextTime = tracksTime[0][i + 1];
                transitionTime = (nextTime - currentTime) / speedOption;
                timer = setInterval(function() {
                    segmentConstruction(id, multipointCoords, tracksTime);
                }, transitionTime);
            };
        };
    };

我认为每一行都重复使用了您的叠加层。无论如何,使用点特征而不是叠加层可能会更简单、性能更高,如下所示:

  • 为点(圆形、图像等)向图层添加新样式
  • 添加代表每行开头的点特征
  • 必要时更新点特征的坐标

换句话说,每只动物都有一个线串和一个点特征。层上的样式将包括线的描边样式和点的图标样式。

您还可以通过为每个点特征提供自己的样式或在图层上使用样式函数来独立设置点的样式。

我建议将此方法用于平滑移动的多个标记的动画,但它需要其他样式的延迟:

      var vehicles= [{ "curlon":77.654397, "curlat":12.959898, "prevlon":77.651951, "prevlat":12.951074 },{ "curlon":77.672936, "curlat":12.958100, "prevlon":77.649290, "prevlat":12.960024 }];

            function push_data_for_multimarker(map,gps_obj)
            {
             destruct=false;
               var getz = gps_obj;
               var data_arry = [];
               for (var i = 0, length = getz.length; i < length; i++)
               {
                gps_smooth_coordinates_generator(parseFloat(getz[i].prevlon),parseFloat(getz[i].prevlat),parseFloat(getz[i].curlon),parseFloat(getz[i].curlat));
               }
            }


            function gps_smooth_coordinates_generator(map,sourcelon,sourcelat,destinationlon,destinationlat)
            {
                var vehicle_data=[];

                var beginz=ol.proj.transform([sourcelon,sourcelat], 'EPSG:4326', 'EPSG:3857');

                var endz=ol.proj.transform([destinationlon,destinationlat], 'EPSG:4326', 'EPSG:3857');


                vehicle_data.push(beginz);
                vehicle_data.push(endz);
                var path= vehicle_data;
                var genrated_positions = [];
                          for(var k = 1;k<path.length;k++)
                              {
                                  var pointsNo = 1000;
                                  var startPos = {};
                                  startPos.lat = path[k-1][1];
                                  startPos.lng = path[k-1][0];
                                  var endPos = {};
                                  endPos.lat = path[k][1];
                                  endPos.lng = path[k][0];
                                  var latDelta = (endPos.lat - startPos.lat) / pointsNo;
                                  var lngDelta = (endPos.lng - startPos.lng) / pointsNo;

                                  for (var i = 0; i < pointsNo; i++) 
                                  {
                                      var curLat = startPos.lat + i * latDelta;
                                      var curLng = startPos.lng + i * lngDelta;
                                      var arr = [];
                                      arr.push(curLng);
                                      arr.push(curLat);
                                      genrated_positions.push(arr);
                                  }
                              }

                           animate_multiple_marker(genrated_positions);
            }

    function animate_multiple_marker(map,veh_croods)
      {
        var routeCoords = veh_croods;
        var routeLength = routeCoords.length;
        console.log("routeCoords"+routeCoords);
        console.log("routeLength"+routeLength);
        var geoMarker = new ol.Feature({
        type: 'geoMarker',
        geometry: new ol.geom.Point(routeCoords[0])
      });


      var off_style =new ol.style.Style({
          image: new ol.style.Circle({
            radius: 7,
            snapToPixel: false,
            fill: new ol.style.Fill({color: 'black'}),
            stroke: new ol.style.Stroke({
              color: 'white', width: 2
            })
          })
        });

            var now;
            var animating = false;
            var speed=20;

            var moveFeature = function(event) {
            var vectorContext = event.vectorContext;
            var frameState = event.frameState;

            if (animating) {
              var elapsedTime = frameState.time - now;
              var index = Math.round(speed * elapsedTime / 1000);
              if (index >= routeLength) {
                console.log("index>>"+index);
                stopAnimation();
                animating = false;
                console.log("animation ends");
              }
              if(animating)
                    {
                          var currentPoint = new ol.geom.Point(routeCoords[index]);
                          var feature = new ol.Feature(currentPoint);
                          vectorContext.drawFeature(feature,off_style);

                    }
              else
              {}

              if(destruct)
                {
                  console.log("termination initiated");
                  stopAnimation();            
                  //destruct=false;
                }
                else
                { }
            }
            else
            {
              console.log("Not amnimating!!");
            }
            // tell OL3 to continue the postcompose animation
            map.render();
          };

            triggerz_animation();


        function stopAnimation() {
        animating = false;
        caller=false;
        //remove listener
          map.un('postcompose', moveFeature);
        }

          function start_vehicles()
          {
          animating = true;
          now = new Date().getTime();
          map.on('postcompose', moveFeature);
          map.render();
          }


            if(caller)
            {

              start_vehicles();

            }
            else
            {


            }
      }

      var caller=false;
      var drive_vehicle;

      function triggerz_animation()
      {
        caller=true;
      }
      var destruct=false;
      function collapse_animation()
      {
        destruct=true;
      }

参考 http://openlayers.org/en/latest/examples/feature-move-animation.html?q=animation

让这对您有所帮助..谢谢 将数据作为 json 传递给函数: push_data_for_multimarker(地图,车辆);