Để thực hiện mô phỏng lộ trình xe chạy trên bản đồ thì chúng ta có dùng thư viện bản đồ của google (Google Maps Platform), tuy nhiên hiện giờ google đã thu phí nên việc lấy Api Key cũng hơi phức tạp và nhất là bản đồ lại bị chế độ Development Purposes Only. Chính vì vậy tôi dùng thư viện Leafletjs để thay thế. Đây là một thư viện javascript mã nguồn mở, chả cần Api Key gì cả mà dùng vẫn ngon. 

Tôi cũng đã rất mất công làm một lộ trình cho xe để mô phỏng chạy được mượt trên bản đồ. Mã nguồn có link ở dưới nhé. 

  • Thời gian
  • Tọa độ

Như trên mô phỏng các bạn thấy, lộ trình của xe được thể hiện qua một bảng bên trái và xe di chuyển trên bản đồ. Vì vậy tôi đã khai báo một class View như sau:

var View = function ()
{
    this.vehicleTracking = null;
    this.clear = function () { };
    this.initTracking = function (tracking, previousTracking) { }; // Khởi tạo tracking.
    this.onAddVehicleTracking = function () { };
    this.viewTracking = function (tracking, focus) { }; // Hiển thị tracking 
    this.clearTracking = function (tracking) { };
};

Để xem được lộ trình như bảng bên trái tôi tạo class TableView kế thừa tới View như sau.

var TableView = function ()
{
    $.extend(this, new View());
    /* Code Code */

    this.clear = function () { tableBody.empty(); };
    this.onAddVehicleTracking = function ()
    {
        /* Code Code */

        btnPlay.click(function () { $this.vehicleTracking.start(); });
        btnPause.click(function () { $this.vehicleTracking.pause(); });
        btnReset.click(function () { $this.vehicleTracking.stop(); });
    }
    this.initTracking = function (tracking)
    {
        /* Code Code */
    };
    
    // cho dòng lộ trình màu xanh khi xe chạy tới tọa độ trong tracking
    this.viewTracking = function (tracking, focus)
    {
        if (focus)
        {
            tableBody.find("ul").removeClass("bg-success text-white");
            var parent = tableBody.parent();
            parent.scrollTop(parent.scrollTop() + tracking.row.position().top - parent.height() / 2 + tracking.row.height() / 2);
            tracking.row.addClass("bg-success text-white");
        }
    };        
};

Để xem được lộ trình của xe trên bản đồ tôi tạo class MapView kế thừa View như sau:

var MapView = function ()
{
    $.extend(this, new View());
    /* Code Code */

    this.clear = function ()
    {
        /* Code Code */
    };
    this.initTracking = function (tracking, previousTracking)
    {
        /* Code Code Khởi tạo marker xe, polyline lộ trình */
    };
    
    // show marker xe và polyline lộ trình lên bản đồ
    this.viewTracking = function (tracking, focus)
    {            
        if (tracking.polyline != null)
        {
            tracking.polyline.addTo(this.map);
            tracking.markerDirection.addTo(this.map);
        }

        if (focus)
        {
            markerVehicle.setIcon(tracking.vehicleIcon);
            markerVehicle.setLatLng(tracking.latLng).addTo(this.map);
            this.map.panTo(tracking.latLng, { animate: true });
        }
    }
    this.clearTracking = function (tracking)
    {
        if (tracking.polyline != null)
        {
            tracking.polyline.removeFrom(this.map);
            tracking.markerDirection.removeFrom(this.map);
        }
    }
};

Và cuối cùng tôi có class VehicleTracking có chứa 2 View trên và cho chạy lần lượt các tracking của xe.

var VehicleTracking = function ()
{
    var views = []; // các view cần hiển thị tracking
    this.addView = function (view)
    {
        view.vehicleTracking = this; 
        view.onAddVehicleTracking();
        views.push(view);
    }
    var withView = function (wv) { for (var i = 0; i < views.length; i++) wv.bind(this)(views[i]); }.bind(this);
    // Code Code
    
    var trackings = [];
    var currentTrackingIndex = 0;
    this.loadTrackings = function (data)
    {
        // Code Code
    }

    this.start = function ()
    {            
        if (timer != null && timer.isRunning) return;
        if (timer == null)
        {
            timer = new Core.Timer({ interval: function () { return interval; } });
            timer.onStop = function ()
            {
                withView(function (view) { view.timerStop(); });
            };
        }
        timer.setOption(function (options)
        {
            options.onTick = function ()
            {
                var nextIndex = currentTrackingIndex + 1;
                if (nextIndex >= trackings.length) { currentTrackingIndex = nextIndex; return; };
                viewTracking(nextIndex, true);
            }
            options.stopWhen = function () { return currentTrackingIndex >= trackings.length - 1; };
        });
        timer.start();
    }
    this.stop = function ()
    {            
        stopTimer();
        clear();
        viewTracking(0, true);
    }
    this.pause = function () { stopTimer(); };

    // Code Code

    this.gotoIndex = function (index)
    {
        if (timer == null || !timer.isRunning) clearForGoto(index);
        else
        {
            timer.stop();
            clearForGoto(index);
            timer.start();
        }
    }
};

Tại hàm viewTracking sẽ gửi tracking đi tới các View để thực hiện hiển thị lộ trình. Khai báo và sử dụng VehicleTracking như sau:

var vehicleTracking = new VehicleTracking();

// View tracking theo table
var tableView = new TableView();    
tableView.container = divMapId;
vehicleTracking.addView(tableView);

// View tracking trên bản đồ
var mapView = new MapView();
vehicleTracking.addView(mapView);

// Load lộ trình của xe
vehicleTracking.loadTrackings(trackings);

Để xem chi tiết mã nguồn các bạn có thể click vào đây. Để xem dữ liệu trackings demo các bạn có thể click vào đây

Nếu các bạn thấy mô phỏng này hay và bổ ích. Hãy like và share để mình có động lực làm các mô phỏng tiếp theo nhé

Sơn 20