Example: Train Monitoring


Step1 Prepare data and service

This sample uses the following data and service:

  • Baes map: here we use the vector cache tiles of the map "map_China4003" that is published by SuperMap Online.
  • Temporal-Spatial Data (for dynamic layer):The point dataset "Train@DynamicData" from the data-DynamicData service published by SuperMap iServer. This point dataset records the locations of the train at different times.

Step2 Pre-define the style of the vector tile map

Define layer styles, including fill pattern, color, etc.

        /*Here a number of color variables are defines, and can be reused later*/

        @waterColor:rgb(34,56,78);
        @roadColora:rgb(109,102,91);
        @roadColorb:rgb(109,102,91);
        @railwayColora:rgb(80,80,80);
        @railwayColorb:rgb(137,137,137);
        @vegetationColor:rgb(27,27,27);
        @continentColor:rgb(68,68,68);
        @provinceLineColor:rgb(180,0,0);


        #China_Railway_L___China400::a{

        /*The length for each segment is 15px, and the time interval is 15px*/
        line-color:@railwayColora;
        line-width:2.5;
        }
        #China_Railway_L___China400::b{

        /*The length for each segment is 15px, and the time interval is 15px*/
        line-dasharray:18,18;
        line-color:@railwayColorb;
        line-width:2;
        }
        /*The underlying background map layer*/

        #World_Division___China400{
        polygon-fill:@waterColor;
        }

        /*Layers for all the other countries except China*/

        #World_Continent___China400{
        polygon-fill:@continentColor;
        line-width:1;
        line-color:rgb(180,180,180);
        }

        #World_Division___China400{
        polygon-fill:@waterColor;
        }

Step3 Initialize base map

Initialize the map and add basic controls. In this sample, we use the map published by SuperMap Online and predefine two coloring styles for the railway.

    var map, layer, animatorVector, lineVector1, lineVector2, 
        url = "http://www.supermapol.com/iserver/services/map_China4003/rest/maps/China",
        url2 = "http://localhost:8090/iserver/services/data-DynamicData/rest/data";
    var value="IbooSg6gIBmhIRaesVgjSED0",
        name = "key";
    SuperMap.Credential.CREDENTIAL = new SuperMap.Credential(value, "key");

    var style1=
    {
        fillColor: "#ffff00",
        fillOpacity: 0.8,
        strokeOpacity: 0,
        pointRadius: 5
    };
    var style2=
    {
        fillColor: "#c165f6",
        fillOpacity: 1,
        strokeOpacity: 0,
        pointRadius: 5
    };
    function init() {
        if(!document.createElement('canvas').getContext) {
            alert(' Your browser doesn't support canvas, please upgrade');
            return;
        }
        // Initialize base map
        map = new SuperMap.Map("map",{controls: [
            new SuperMap.Control.ScaleLine(),
            new SuperMap.Control.Zoom(),
            new SuperMap.Control.Navigation({
                dragPanOptions: {
                    enableKinetic: true
                }
            })],
            projection: "EPSG:3857"
        });


    }

Step4 Initialize base map and dynamic layer

In this sample, we use the tiled vector layer "TiledVectorLayer" as the base map, and use the CartoCSS style predefined in Step1.

        // Initialize map layer
        var cartoCssStr=document.getElementById("cartocssStr");
        var cartoCss=cartoCssStr.text;
        var layerNames=["World_Division@China400","World_Continent@China400",
            "China_Province_R@China400","China_island_R@China400",
            "China_Provinces_L@China400","China_Capital_P@China400",
            "China_BeiJing@China400"].join(",");
        layerNames="["+layerNames+"]";
        layer = new SuperMap.Layer.TiledVectorLayer("China", url,{cacheEnabled:true,layerNames:layerNames},{useLocalStorage:true,cartoCss:cartoCss});
        layer.events.on({"layerInitialized": addLayer});

Step5 Initialize train routes and dynamic layer, and add them to the map

Create the dynamic training monitoring layer:

  • Initialize the animation vector layer "Train", and set the moving speed, start and end time of the point.
  • Initialize the two vector layers of train routes with different styles: lineVector1 and lineVector2. One layer is in dark color and the other layer is light. We overlay them to symbolize a railway.

    Add the above layer to map

    function addLayer() {
        //Initialize the dynamic layer
        animatorVector = new SuperMap.Layer.AnimatorVector("Train", {rendererType:"TadpolePoint"},{
            // Set the animation speed to display the data of 0.02 hour with 1 frame
            speed:0.02,
            // Set the start time as 0 o' clock
            startTime:0,
            // Set the end time as the end time of the last train 
            endTime:39
        });
        lineVector1 = new SuperMap.Layer.Vector("Line1");
        lineVector2 = new SuperMap.Layer.Vector("Line2");
        map.addLayers([layer,lineVector1,lineVector2,animatorVector]);

        map.setCenter(new SuperMap.LonLat(12009634.286396, 4258716.5813769), 4);
        //Add data
        addTrain();

    }

Step6 Get the train data, create the train route and implement the dynamic effect.

First, get the vector points (train locations) and time information from the Train@DynamicData dataset of the data-DynamicData service.

    //Add train data and return the point features (2240) from the layer "Train@DynamicData"
    function addTrain()
    {
        var getFeatureParam, getFeatureBySQLService, getFeatureBySQLParams;

        getFeatureParam = new SuperMap.REST.FilterParameter({
            name: "Train@DynamicData",
            attributeFilter: "SmID < 2240"
        });
        getFeatureBySQLParams = new SuperMap.REST.GetFeaturesBySQLParameters({
            queryParameter: getFeatureParam,
            datasetNames:["DynamicData:Train"]
        });
        //Return the number of points
        getFeatureBySQLParams.toIndex  = 2240;
        getFeatureBySQLService = new SuperMap.REST.GetFeaturesBySQLService(url2, {
            eventListeners: {"processCompleted": processCompleted, "processFailed": processFailed}});

        getFeatureBySQLService.processAsync(getFeatureBySQLParams);

    }

Then, according to the point features returned: *Create the train routes with two different colors. One layer is in dark color and the other layer is light. We overlay them to symbolize a railway.

  • Set the style of points to represent different types of trains. We use two types to represent short-trip and long-trip trains.
    //According to the point features returned, create the train routes and set the style of points (trains)
    function processCompleted(getFeaturesEventArgs){
        var features,result = getFeaturesEventArgs.result;
        if (result && result.features) {
            features = result.features;
        }
        console.log(features);

        //Use data
        var pointFeatures = [];
        var lines1 = [];
        var lines2 = [];
        var points = [];
        var id = 0;
        for(var i = 0,len = features.length;i<len;i++)
        {
            var point = features[i].geometry;
            var po = features[i].geometry;
            //Create train routes and set train representation style.
            if(id == features[i].data.FEATUREID)
            {
                points.push(po);
            }
            else
            {
                id = features[i].data.FEATUREID;
                lines1.push(
                        new SuperMap.Feature.Vector(
                                new SuperMap.Geometry.LineString(points),
                                {},
                                {
                                    stroke:true,
                                    strokeColor:"#dddddd",
                                    strokeWidth:3,
                                    strokeDashstyle:"solid"

                                }
                        )
                );
                lines2.push(
                        new SuperMap.Feature.Vector(
                                new SuperMap.Geometry.LineString(points),
                                {},
                                {
                                    stroke:true,
                                    strokeColor:"#41403f",
                                    strokeWidth:2,
                                    strokeDashstyle:"dash"
                                }
                        )
                );

                points = [];
            }

                //Use two style of points to represent different types of trains: short-trip and long-trip trains. 
                if(id == features[i].data.FEATUREID)
                {
                    var pointFeature = new SuperMap.Feature.Vector(point,{
                        FEATUREID:features[i].data.FEATUREID,
                        TIME:features[i].data.TIME
                    },style1);
                }
                else
                {
                    var pointFeature = new SuperMap.Feature.Vector(point,{
                        FEATUREID:features[i].data.FEATUREID,
                        TIME:features[i].data.TIME
                    },style2);
                }

                pointFeatures.push(pointFeature);
        }
        animatorVector.addFeatures(pointFeatures);
        lineVector1.addFeatures(lines1);
        lineVector2.addFeatures(lines2);

    }

Step7 Enable animation controls

animatorVector provides a number of methods to control the animation.

    function processFailed(e){
        alert(e.error.errorMsg);
    }
    //Start animation play
    function startAnimator(){
        animatorVector.animator.start();
    }
    //Suspend animation play
    function pauseAnimator(){
        animatorVector.animator.pause();
    }
    //Stop animation play
    function stopAnimator(){
        animatorVector.animator.stop();
    }
    //Slow animation play
    function decreaseSpeed(){
        animatorVector.animator.setSpeed(animatorVector.animator.getSpeed()*0.7);
    }

    //Forward and backward play
    function setReverseAnimator(){
        animatorVector.animator.setReverse(!animatorVector.animator.getReverse());
    }
    //Accelerate animation play
    function increaseSpeed(){
        animatorVector.animator.setSpeed(animatorVector.animator.getSpeed()*1.5);
    }
    //Flickering effect of the switch
    function setGlint(){
        animatorVector.renderer.glint = !animatorVector.renderer.glint;
    }
    //The tail of the switch
    function setTailr(){
        animatorVector.renderer.tail = !animatorVector.renderer.tail;
    }
    function show(){
        lineVector1.setVisibility(!lineVector1.getVisibility());
        lineVector2.setVisibility(!lineVector2.getVisibility());
    }

Online Demo and Code Editing

You can access the online source code and visualize the demo. You can also edit the source code and change the demo.