---
metadata:
  - name: generator
    content: Diplodoc Platform v5.39.1
alternate:
  - https://yandex.com/dev/jsapi-v2-1/doc/ru/v2-1/examples/cases/polyline_animation.md
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.com/dev/jsapi-v2-1/doc/ru/llms.txt

# Анимация линии

<iframe id="LIVE-EXAMPLE" style="width:100%;height: 400px;border-radius: 8px;border: 1px solid rgba(92, 94, 102, 0.14);" frameBorder="0" src="https://yastatic.net/s3/front-maps-static/maps-front-jsapi-v2-1/examples/2/out/s3-cases/ru/polyline_animation/index.html" allow="fullscreen"></iframe>

<a target="_blank" rel="noopener noreferrer" style="display: inline-block;margin-top: 10px;cursor: pointer;border-radius: 4px;padding: 9px 12px;background: #151515;color: white;text-decoration: none;font-weight: 500" href="https://codesandbox.io/p/sandbox/28kvwy?file=index.html">Open in CodeSandbox</a>

<div id="references">
    <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/ready">ready</a>,
    <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/Map">Map</a>,
    <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/Polyline">Polyline</a>,
    <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/Placemark">Placemark</a>,
    <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/map.GeoObjects">map.GeoObjects</a>
</div>
<p>
    Анимировать путь между точками можно с помощью изменения длины линии. Для этого необходимо добавлять новые точки, не меняя всю линию целиком.
</p>
<p>
    Чтобы добавить новые точки в <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/geometry.LineString-docpage/">геометрию ломаной линии</a>, будем использовать метод <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/ILineStringGeometryAccess-docpage/#set">set</a>.
    На вход методу будем передавать индекс новой точки и ее координаты.
</p>
<p>
    Также геометрию ломаной линии можно поменять целиком с помощью метода <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/ILineStringGeometryAccess-docpage/#setCoordinates">setCoordinates</a>.
</p>
<p>
    В примере показано, как на основе класса линии <a href="https://yandex.ru/dev/jsapi-v2-1/doc/ru/v2-1/ref/reference/Polyline">Polyline</a> создать модуль для анимирования линии на карте. Для этого достаточно создать экземпляр класса AnimatedLine и задать длительность анимации через опцию animationTime.
</p>

{% list tabs %}

-   index.html

    ```html
    <!DOCTYPE html>
    <html>
        <head>
            <title>Анимация линии</title>
            <meta
                http-equiv="Content-Type"
                content="text/html; charset=utf-8"
            />
            <!--
            Укажите свой API-ключ. Тестовый ключ НЕ БУДЕТ работать на других сайтах.
            Получить ключ можно в Кабинете разработчика: https://developer.tech.yandex.ru/keys/
        -->
            
            
            
            
        </head>
        <body>
            <div id="map"></div>
        </body>
    </html>
    ```

-   animated_line.js

    ```js
    ymaps.modules.define(
        "AnimatedLine",
        ["util.defineClass", "Polyline", "vow"],
        function (provide, defineClass, Polyline, vow) {
            /**
             * @fileOverview Анимированная линия.
             */
            /**
             * Создает экземпляр анимированной линии.
             * @class AnimatedLine. Представляет собой геообъект с геометрией geometry.LineString.
             * @param {Boolean} [options.animationTime = 4000] Длительность анимации.
             **/
            function AnimatedLine(geometry, properties, options) {
                AnimatedLine.superclass.constructor.call(
                    this,
                    geometry,
                    properties,
                    options
                );
                this._loopTime = 50;
                this._animationTime = this.options.get("animationTime", 4000);
                // Вычислим длину переданной линии.
                var distance = 0;
                var previousElem = geometry[0];
                this.geometry.getCoordinates().forEach(function (elem) {
                    distance += getDistance(elem, previousElem);
                    previousElem = elem;
                });
                // Вычислим минимальный интервал отрисовки.
                this._animationInterval =
                    (distance / this._animationTime) * this._loopTime;
                // Создадим массив с более частым расположением промежуточных точек.
                this._smoothCoords = generateSmoothCoords(
                    geometry,
                    this._animationInterval
                );
            }
            defineClass(AnimatedLine, Polyline, {
                // Анимировать линию.
                start: function () {
                    var value = 0;
                    var coords = this._smoothCoords;
                    var line = this;
                    var loopTime = this._loopTime;
                    // Будем добавлять по одной точке каждые 50 мс.
                    function loop(value, currentTime, previousTime) {
                        if (value < coords.length) {
                            if (
                                !currentTime ||
                                currentTime - previousTime > loopTime
                            ) {
                                line.geometry.set(value, coords[value]);
                                value++;
                                previousTime = currentTime;
                            }
                            requestAnimationFrame(function (time) {
                                loop(value, time, previousTime || time);
                            });
                        } else {
                            // Бросаем событие окончания отрисовки линии.
                            line.events.fire("animationfinished");
                        }
                    }

                    loop(value);
                },
                // Убрать отрисованную линию.
                reset: function () {
                    this.geometry.setCoordinates([]);
                },
                // Запустить полный цикл анимации.
                animate: function () {
                    this.reset();
                    this.start();
                    var deferred = vow.defer();
                    this.events.once("animationfinished", function () {
                        deferred.resolve();
                    });
                    return deferred.promise();
                },
            });
            // Функция генерации частых координат по заданной линии.
            function generateSmoothCoords(coords, interval) {
                var smoothCoords = [];
                smoothCoords.push(coords[0]);
                for (var i = 1; i < coords.length; i++) {
                    var difference = [
                        coords[i][0] - coords[i - 1][0],
                        coords[i][1] - coords[i - 1][1],
                    ];
                    var maxAmount = Math.max(
                        Math.abs(difference[0] / interval),
                        Math.abs(difference[1] / interval)
                    );
                    var minDifference = [
                        difference[0] / maxAmount,
                        difference[1] / maxAmount,
                    ];
                    var lastCoord = coords[i - 1];
                    while (maxAmount > 1) {
                        lastCoord = [
                            lastCoord[0] + minDifference[0],
                            lastCoord[1] + minDifference[1],
                        ];
                        smoothCoords.push(lastCoord);
                        maxAmount--;
                    }
                    smoothCoords.push(coords[i]);
                }
                return smoothCoords;
            }
            // Функция нахождения расстояния между двумя точками на плоскости.
            function getDistance(point1, point2) {
                return Math.sqrt(
                    Math.pow(point2[0] - point1[0], 2) +
                        Math.pow(point2[1] - point1[1], 2)
                );
            }
            provide(AnimatedLine);
        }
    );
    ```

-   polyline_animation.js

    ```js
    ymaps.ready(["AnimatedLine"]).then(init);

    function init(ymaps) {
        // Создаем карту.
        var myMap = new ymaps.Map(
            "map",
            {
                center: [55.762, 37.57835813659775],
                zoom: 16,
            },
            {
                searchControlProvider: "yandex#search",
            }
        );
        // Создаем ломаные линии.
        var firstAnimatedLine = new ymaps.AnimatedLine(
            [
                [55.76028460519329, 37.57704491961252],
                [55.76068242105497, 37.57704760182153],
                [55.76070813128414, 37.57682497847331],
                [55.76074594041378, 37.57683302510035],
                [55.76070753602857, 37.5772156971609],
                [55.76099639684956, 37.577322985521505],
                [55.760916500352934, 37.578192870439906],
                [55.76091952506843, 37.5785147355217],
                [55.76098304403938, 37.57876954537813],
                [55.76109495816394, 37.57893852454606],
                [55.76122432960969, 37.578535038979666],
            ],
            {},
            {
                // Задаем цвет.
                strokeColor: "#ED4543",
                // Задаем ширину линии.
                strokeWidth: 5,
                // Задаем длительность анимации.
                animationTime: 4000,
            }
        );
        var secondAnimatedLine = new ymaps.AnimatedLine(
            [
                [55.761223661714205, 37.57854299428123],
                [55.76129474190374, 37.57836060406823],
                [55.76149285834102, 37.57855640532632],
                [55.76173267134118, 37.57864573959325],
                [55.761782872763874, 37.578559582240004],
                [55.7622647306412, 37.57857741008619],
                [55.76247342821094, 37.57840038429122],
                [55.762818964832924, 37.57765342764373],
                [55.76292179998886, 37.57748713068481],
                [55.762890042102114, 37.577167947812036],
                [55.76292179998886, 37.576878269238435],
                [55.763076052212064, 37.57669587902541],
                [55.76309672830313, 37.57723949881904],
            ],
            {},
            {
                strokeColor: "#1E98FF",
                strokeWidth: 5,
                animationTime: 4000,
            }
        );
        // Добавляем линии на карту.
        myMap.geoObjects.add(firstAnimatedLine);
        myMap.geoObjects.add(secondAnimatedLine);
        // Создаем метки.
        var firstPoint = new ymaps.Placemark(
            [55.7602953585417, 37.57705113964169],
            {},
            {
                preset: "islands#redRapidTransitCircleIcon",
            }
        );
        var secondPoint = new ymaps.Placemark(
            [55.76127880650197, 37.57839413202077],
            {},
            {
                preset: "islands#blueMoneyCircleIcon",
            }
        );
        var thirdPoint = new ymaps.Placemark(
            [55.763105418792314, 37.57724573612205],
            {},
            {
                preset: "islands#blackZooIcon",
            }
        );
        // Функция анимации пути.
        function playAnimation() {
            // Убираем вторую линию.
            secondAnimatedLine.reset();
            // Добавляем первую метку на карту.
            myMap.geoObjects.add(firstPoint);
            // Анимируем первую линию.
            firstAnimatedLine
                .animate()
                // После окончания анимации первой линии добавляем вторую метку на карту и анимируем вторую линию.
                .then(function () {
                    myMap.geoObjects.add(secondPoint);
                    return secondAnimatedLine.animate();
                })
                // После окончания анимации второй линии добавляем третью метку на карту.
                .then(function () {
                    myMap.geoObjects.add(thirdPoint);
                    // Добавляем паузу после анимации.
                    return ymaps.vow.delay(null, 2000);
                })
                // После паузы перезапускаем анимацию.
                .then(function () {
                    // Удаляем метки с карты.
                    myMap.geoObjects.remove(firstPoint);
                    myMap.geoObjects.remove(secondPoint);
                    myMap.geoObjects.remove(thirdPoint);
                    // Убираем вторую линию.
                    secondAnimatedLine.reset();
                    // Перезапускаем анимацию.
                    playAnimation();
                });
        }
        // Запускаем анимацию пути.
        playAnimation();
    }
    ```

{% endlist %}
