Route Player plugin for maptalks.js.
- support 2d/3d Layer.
 - high-performance
 - customizable
 - Supports any map engine
 
- This plugin focuses on the management, control, and scheduling of trajectory data. To ensure absolute low coupling(该插件专注于轨迹数据的管理、控制和调度。确保绝对低耦合)
 - The source of trajectory data is not within the design scope. The data can come from GPS trajectories, mathematical equations, physical simulations, such as ABS(轨迹数据来源不在设计范围内。数据可以来自GPS轨迹、数学方程、物理模拟,如ABS)
 - The display and consumption of data are fully entrusted to users. You can use any map engine, which can be 2D layers, 3D layers, 2D images, 3D models, etc. It's entirely up to you to decide(数据的展示消费完全委托给用户。您可以使用任何地图引擎,可以是二维图层、三维图层、二维图像、三维模型等。完全由您决定)
 
- Basic demo.
 - Marker rotate.
 - with GLTFLayer.
 - with ThreeLayer.
 - map animation.
 - simple road.
 - simulated traffic.
 - drive road.
 - test perf by VectorLayer.
 - test perf by GLTFLayer.
 - test perf 800000 coordinate points.
 - coordinate stop.
 - realtime-line.
 - brige.
 - spring.
 - update data.
 - UIMarker.
 - UIMarker test dom events.
 - with terrain.
 - identity(Cartesian coordinate system).
 - leaflet demo.
 
- Install with npm:
 
npm install maptalks 
npm install maptalks.routeplayer- Use unpkg CDN:
 
<script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/maptalks.routeplayer/dist/maptalks.routeplayer.js"></script>As a plugin, maptalks.routeplayer must be loaded after maptalks.js in browsers.
<script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/maptalks.routeplayer/dist/maptalks.routeplayer.js"></script>
<script>
    const route = [{
            coordinate: [120, 31, 0],
            time: 301000
        },
        {
            coordinate: [122, 32, 0],
            time: 541000
        },
        //other coordinates
    ];
    const data = maptalks.formatRouteData(route, {});
    const player = new maptalks.RoutePlayer(data, {
        speed: 4,
        debug: false
    });
    console.log(player);
    player.play();
</script>import {
    RoutePlayer,
    formatRouteData
} from 'maptalks.routeplayer';
const route = [{
        coordinate: [120, 31, 0],
        time: 301000
    },
    {
        coordinate: [122, 32, 0],
        time: 541000
    },
    //other coordinates
];
const data = formatRouteData(route, {});
const player = new RoutePlayer(data, {
    speed: 4,
    debug: false
});
console.log(player);
player.play();format route data util for RoutePlayer
route: path dataArray<object>options:objectoptions.duration: Route duration, if necessaryoptions.coordinateKey: Name of the coordinate pointoptions.timeKey: Name of the time fieldoptions.unitTime: Time unit, default 1, internal time is in milliseconds. If your data time unit is not milliseconds, you need to configure this parameteroptions.isCartesian: It's Cartesian coordinates?
const route = [{
        coordinate: [120, 31, 0],
        time: 301000
    },
    {
        coordinate: [122, 32, 0],
        time: 541000
    },
    //other coordinates
];
const data = formatRouteData(route, {});- support custom coordinateKey and timeKey
 
const route = [{
        coord: [120, 31, 0],
        t: 301000
    },
    {
        coord: [122, 32, 0],
        t: 541000
    },
    //other coordinates
];
const data = formatRouteData(route, {
    coordinateKey: 'coord',
    timeKey: 't'
});- support Automatically generate timestamps if your data no time, you can:
 
const route = [{
        coordinate: [120, 31, 0],
    },
    {
        coordinate: [122, 32, 0]
    },
    //other coordinates
];
const data = formatRouteData(route, {
    duration: 1000 * 60 * 10
});The automatically generated time is milliseconds, by new Date().getTime()
duration unit is milliseconds
- support custom 
unitTime 
// the time unit is second
const route = [{
        coord: [120, 31, 0],
        t: 301
    },
    {
        coord: [122, 32, 0],
        t: 541
    },
    //other coordinates
];
const data = formatRouteData(route, {
    coordinateKey: 'coord',
    timeKey: 't',
    unitTime: 1000 //to millisecond,Automatically convert seconds to milliseconds
});- Support Cartesian coordinate system 
isCartesian 
// the time unit is second
const route = [{
        coord: [10000, -10000, 0], //Cartesian coordinate points
        t: 301
    },
    {
        coord: [20000, 0, 0],
        t: 541
    },
    //other coordinates
];
const data = formatRouteData(route, {
    coordinateKey: 'coord',
    timeKey: 't',
    unitTime: 1000, //to millisecond,
    isCartesian: true
});new RoutePlayer(routeData, options)routeDataArray an object array containing routes data, fromformatRouteDatafunction run resultoptionsObjectoptions.unitTimeNumber unit time, default is 1 ,Internally used milliseconds as a unit, if the time unit of your data is not milliseconds, please set its value,For example, if your data time unit is seconds, we can set it to 1000(内部使用毫秒作为单位,如果您的数据的时间单位不是毫秒,请设置其值。例如,如果您数据的时间单元是秒,我们可以将其设置为1000)options.speedNumber Play at double speed. Note that this is the speed of time playback, not the speed in physics. As for the speed of the path, it is determined by the time data in your path, which can be understood as the playback speed doubling function in video playback(注意这个是时间播放的速度,不是物理里的速度,至于路径的速度是有你的路径里时间数据决定,可以理解成视屏播放里的播放倍速功能)options.debugBooleanoptions.autoPlayBoolean Whether auto playoptions.repeatBoolean Whether repeat playoptions.isCartesianBoolean Is it Cartesian coordinate system
import {
    RoutePlayer,
    formatRouteData
} from 'maptalks.routeplayer';
const route = [{
        coordinate: [120, 31, 0],
        time: 301000
    },
    {
        coordinate: [122, 32, 0],
        time: 541000
    },
    //other coordinates
];
const data = formatRouteData(route, {});
const player = new RoutePlayer(data, {
    speed: 4,
    debug: false,
    autoPlay: true
});
console.log(player);
player.play();remove()add()play()pause()reset()Restore all states to their original state
function replay() {
    player.reset();
    player.play();
}cancel()Equivalent toresetisPlaying()isPlayend()finish()getSpeed()setSpeed(speed)It can be analogized to the speed of a video
player.setSpeed(10);setIndex(index)Set the current playback position to a coordinate node
player.setIndex(10);setTime(time)Set the current playback position to a certain time
     const t = player.getStartTime() / 2 + player.getEndTime() / 2;
     player.setTime(t);setPercent(percent)Set the current playback position as a percentage of distance
player.setPercent(0.3);setData(data)reset route data
const newData = formatRouteData(route, {});
player.setData(data);getCurrentTime()getStartCoordinate()Get the coordinates of the first nodegetStartInfo()Obtain information about the starting point, including coordinates, rotation information, etc
   const info = player.getStartInfo();
   console.log(info.coordinate);
   //for 3d model rotation
   console.log(info.rotationZ);
   console.log(info.rotationX);
   function updateModelPosition(e) {
       const {
           coordinate,
           rotationZ,
           rotationX
       } = e;
       if (!currentModel) {
           return;
       }
       // if (Math.abs(rotationX) > 40) {
       //     console.log(rotationX);
       // }
       currentModel.setCoordinates(coordinate);
       currentModel.setRotation(rotationX, 0, rotationZ + modelOffsetAngle);
   }
   currentModel = new maptalks.GLTFMarker(info.coordinate, {
       symbol,
   });
   gltfLayer.addGeometry(currentModel);
   updateModelPosition(info)getData()getStartTime()getEndTime()getUnitTime()setUnitTime(t)
//if your data time unit is second,1 second= 1000 ms
player.setUnitTime(1000);getCurrentCoordinate()Get the coordinates of the current playback pointgetCurrentVertex()getCoordinates()
      player.on('playstart playing playend pause', e => {
          console.log(e.type);
      })addremoveplaystartplaying
function updateModelPosition(e) {
    const {
        coordinate,
        rotationZ,
        rotationX
    } = e;
    if (!currentModel) {
        return;
    }
    // if (Math.abs(rotationX) > 40) {
    //     console.log(rotationX);
    // }
    currentModel.setCoordinates(coordinate);
    currentModel.setRotation(rotationX, 0, rotationZ + modelOffsetAngle);
}
player.on('playing', e => {
    if (autoUpdateMapCenter) {
        map.setCenter(e.coordinate);
    }
    updateModelPosition(e);
    // point.setCoordinates(e.coordinate);
});playendvertexPassing through coordinate nodes during playback
function showVertex(e, vertexs, layer) {
    const data = e.data;
    const index = e.index;
    console.log(index);
    if (!vertexs[index]) {
        const coordinate = data.coordinate;
        const point = new maptalks.Marker(coordinate, {
            symbol: {
                markerType: 'ellipse',
                markerWidth: 5,
                markerHeight: 5,
                textSize: 12,
                textName: index,
                textFill: '#fff'
            }
        });
        vertexs[index] = point;
    }
    const point = vertexs[index];
    if (!point.getLayer()) {
        point.addTo(layer);
    }
    const needRemoves = vertexs.slice(index + 1, Infinity);
    if (needRemoves.length) {
        layer.removeGeometry(needRemoves);
    }
}
let vertexs = [];
player.on('vertex', e => {
    showVertex(e, vertexs, debugLayer);
});settimeit will when you setTime/setIndex/setPercentresetcancelpausefinish
We welcome any kind of contributions including issue reportings, pull requests, documentation corrections, feature requests and any other helps.
- 
1.0.0-alpha.5
- formatRouteData support 
unitTime - fix 
unitTimeerror when playing - Supports any map engine
 
 - formatRouteData support 
 - 
1.0.0-alpha.3
- Optimize getDistance performance
 - add 
getCoordinates()method 
 - 
1.0.0-alpha.2
- add 
getCurrentVertex()method 
 - add 
 - 
1.0.0-alpha.1
- refactor details
 
 
