├── car ├── car.css ├── index.html └── car.js └── README.md /car/car.css: -------------------------------------------------------------------------------- 1 | .b-car { width: 54px; height: 54px; margin-left:-27px; margin-top:-27px; } 2 | .b-car.b-car_blue { background: url(http://ymlib.narod.ru/1.1/src/i/cars-blue.png) no-repeat 0 0; } 3 | .b-car.b-car-direction-e {background-position:-324px 0} 4 | .b-car.b-car-direction-ne {background-position:-378px 0} 5 | .b-car.b-car-direction-n {background-position:0 0} 6 | .b-car.b-car-direction-nw {background-position:-54px 0} 7 | .b-car.b-car-direction-w {background-position:-108px 0} 8 | .b-car.b-car-direction-sw {background-position:-162px 0} 9 | .b-car.b-car-direction-s {background-position:-216px 0} 10 | .b-car.b-car-direction-se {background-position:-270px 0} 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ymaps 2 | ===== 3 | 4 | ymaps related things 5 | 6 | Examples: http://zxqfox.github.io/ymaps/examples/ 7 | 8 | Published under MIT License 9 | 10 | Car 11 | --- 12 | 13 | Simple javascript object for animating some route on yandex.maps (http://api.yandex.ru/maps/doc/jsapi/2.x/ref/) 14 | 15 | Examples: http://zxqfox.github.io/ymaps/examples/car/ 16 | 17 | ### Simple example usage 18 | ```js 19 | $.getScript('car.js', function () { 20 | car = new Car(); 21 | ymaps.route([ 22 | 'Москва, метро Смоленская', // from Smolenskaya subway station 23 | [55.740532, 37.625693] // to Tretyakovkaya subway station 24 | ]).then(function (route) { 25 | car.moveTo(route.getWayPoints().getPaths().get(0).getSegments()); 26 | }); 27 | }); 28 | ``` 29 | 30 | ### More complex 31 | ```js 32 | $.getScript('car.js', function () { 33 | car = new Car({ 34 | // geoObject options 35 | iconLayout: ymaps.templateLayoutFactory.createClass( 36 | '
' 37 | ) 38 | }); 39 | ymaps.route([ 40 | 'Москва, метро Смоленская', // from Smolenskaya subway station 41 | { 42 | type: 'viaPoint', // via Tretyakovskaya gallery 43 | point: 'Россия, Москва, Лаврушинский переулок, 10' 44 | }, 45 | [55.740532, 37.625693] // to Tretyakovkaya subway station 46 | ], { 47 | // Router options 48 | mapStateAutoApply: true 49 | }).then(function (route) { 50 | // Setting custom label for routing points 51 | var points = route.getWayPoints(); 52 | points.get(0).properties.set("iconContent", "A"); 53 | points.get(1).properties.set("iconContent", "B"); 54 | 55 | // Add route and car to map 56 | map.geoObjects.add(route); 57 | map.geoObjects.add(car); 58 | 59 | // Send car with specific move speed and directions count 60 | car.moveTo(route.getPaths().get(0).getSegments(), { 61 | speed: 10, 62 | directions: 8 63 | }, function (geoObject, coords, direction) { // тик движения 64 | // перемещаем машинку 65 | geoObject.geometry.setCoordinates(coords); 66 | // ставим машинке правильное направление - в данном случае меняем ей текст 67 | geoObject.properties.set('direction', direction.t); 68 | 69 | }, function (geoObject) { // приехали 70 | geoObject.properties.set('balloonContent', "Приехали!"); 71 | geoObject.balloon.open(); 72 | }); 73 | }); 74 | }); 75 | ``` 76 | -------------------------------------------------------------------------------- /car/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Пример анимации иконки автомобиля по маршруту 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 82 | 83 |
84 |
85 |

Пример анимации иконки автомобиля по маршруту

86 |
87 |
88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /car/car.js: -------------------------------------------------------------------------------- 1 | /** 2 | * fileOverview Класс анимированной машинки 3 | * @see http://ymlib.narod.ru/1.1/demos/animate.html 4 | * Версия для АПИ 2.0 5 | * @author Alex Yaroshevich 6 | */ 7 | 8 | var Car = (function () { 9 | "use strict"; 10 | 11 | // делаем заготовку для кол-ва направлений. 4, 8 или 16 (+, x, *) 12 | var directionsVariants = { 13 | classes: { 14 | 16: ['w', 'sww', 'sw', 'ssw', 's', 'sse', 'se', 'see', 'e', 'nee', 'ne', 'nne', 'n', 'nnw', 'nw', 'nww'], 15 | 8: ['w', 'sw', 's', 'se', 'e', 'ne', 'n', 'nw'], 16 | 4: ['w', 's', 'e', 'n'] 17 | }, 18 | n: function (x,y,n) { 19 | n = n || 8; 20 | var n2 = n>>1; // half of n 21 | var number = (Math.floor(Math.atan2(x,y)/Math.PI*n2+1/n)+n2) % n; // seems like there is a little bug here 22 | return {n: number, t: directionsVariants.classes[n][ number ]}; 23 | }, 24 | 16: function (x,y) { // -> values in range [0, 16] 25 | return directionsVariants.n(x,y,16); 26 | }, 27 | 8: function (x,y) { // -> values in range [0, 8] 28 | return directionsVariants.n(x,y,8); 29 | }, 30 | 4: function (x,y) { // -> values in range [0, 4] 31 | return directionsVariants.n(x,y,4); 32 | } 33 | }; 34 | 35 | var defaultMovingCallback = function (geoObject, coords, direction) { // действие по умолчанию 36 | // перемещаем машинку 37 | geoObject.geometry.setCoordinates(coords); 38 | // ставим машинке правильное направление - в данном случае меняем ей текст 39 | geoObject.properties.set('iconContent', direction.t); 40 | }, 41 | defaultCompleteCallback = function (geoObject) { // действие по умолчанию 42 | // приехали 43 | geoObject.properties.set('iconContent', "Приехали!"); 44 | }; 45 | 46 | // нормализуем в один массив точек сегметны из ymaps 47 | var makeWayPointsFromSegments = function (segments, options) { 48 | options = options || {}; 49 | options.directions = [4, 8, 16].indexOf(options.directions) >= 0 ? options.directions : 8; // must be 4, 8, or 16 50 | options.speed = options.speed || 6; 51 | 52 | var points, street, 53 | wayList = [], 54 | // вспомогательные 55 | i, j, k, l, prev, cur, direction, 56 | getDirection = directionsVariants[options.directions], 57 | coordSystem = options.coordSystem; 58 | 59 | // открываю массив с точками 60 | points = []; 61 | // выполняю операцию для всех сегментов 62 | for (i = 0, l = segments.length; i < l; i++) { 63 | // беру координаты начала и конца сегмента 64 | street = segments[i].getCoordinates(); 65 | // и добавляю КАЖДУЮ ИЗ НИХ в массив, чтобы получить полный список точек 66 | for (j = 0, k = street.length; j < k; j++) { 67 | cur = street[j]; 68 | // пропускаем дубли 69 | if (prev && prev[0].toPrecision(10) === cur[0].toPrecision(10) && prev[1].toPrecision(10) === cur[1].toPrecision(10)) { 70 | continue; 71 | } 72 | points.push(cur); 73 | prev = cur; 74 | } 75 | } 76 | 77 | // строим путь. берем 1 единицу расстояния, возвращаемого distance, за пройденный путь в единицу времени. в 1 единица времени - будет 1 смещение геоточки. ни разу не оптимальный, но наглядный алгоритм 78 | for (i = 0, l = points.length - 1; l; --l, ++i) { 79 | var from = points[i], to = points[i+1], diff = [to[0]-from[0], to[1]-from[1]]; 80 | direction = getDirection(diff[0], diff[1]); 81 | // каждую шестую, а то слишком медленно двигается. чрезмерно большая точность 82 | for (j = 0, k = Math.round(coordSystem.distance(from, to)); j < k; j += options.speed) { 83 | wayList.push({coords: [from[0]+(diff[0]*j/k), from[1]+(diff[1]*j/k)], direction: direction, vector: diff}); 84 | } 85 | } 86 | 87 | return wayList; 88 | }; 89 | 90 | /** 91 | * Класс машинки. 92 | * TODO: make it a geoObject with right interface. 93 | * @class 94 | * @name Car 95 | * @param {Object} [options] Опции машики. 96 | */ 97 | var Car = function (options) { 98 | var properties = { 99 | // Описываем геометрию типа "Точка". 100 | geometry: { 101 | type: "Point", 102 | coordinates: [55.75062, 37.62561] 103 | } 104 | }; 105 | options = options || {}; 106 | options.preset = options.preset || 'twirl#greenStretchyIcon'; 107 | var result = new ymaps.GeoObject(properties, options); 108 | result.coordSystem = options.coordSystem; 109 | result.waypoints = []; 110 | 111 | result.stop = function () { 112 | // чистим старый маршрут 113 | this.waypoints.length = 0; 114 | }; 115 | /** 116 | * Метод анимации движения машики по марщруту. 117 | * @function 118 | * @name Car.moveTo 119 | * @param {Array} segments Массив сегментов маршрута. 120 | * @param {Object} [options] Опции анимации. 121 | * @param {Function} movingCallback Функция обратного вызова по-сегментам маршрута. 122 | * @param {Function} completeCallback Функция обратного вызова завершения анимации. 123 | */ 124 | result.moveTo = function (segments, options, movingCallback, completeCallback) { 125 | if (!segments) return; 126 | options = options || {}; 127 | // ищем систему координат 128 | options.coordSystem = options.coordSystem || this.coordSystem || this.getMap().options.get('projection').getCoordSystem(); 129 | // считаем скорость базируясь на текущем зуме: very dirty but works pretty cute 130 | options.speed = options.speed || Math.round(80 / this.getMap().getZoom()); 131 | // Получаем точечки 132 | this.waypoints = makeWayPointsFromSegments(segments, options); 133 | // Запуск анимации 134 | var that = this, 135 | timer = setInterval(function () { 136 | // если точек больше нет - значит приехали 137 | if (that.waypoints.length === 0) { 138 | (completeCallback || defaultCompleteCallback)(that); 139 | return clearTimeout(timer); 140 | } 141 | // берем следующую точку 142 | var nextPoint = that.waypoints.shift(); 143 | // и отправляем в пользовательский callback 144 | (movingCallback || defaultMovingCallback)(that, nextPoint.coords, nextPoint.direction); 145 | }, 42); 146 | }; 147 | 148 | return result; 149 | }; 150 | 151 | return Car; 152 | }()); 153 | 154 | --------------------------------------------------------------------------------