Автор оригинала: Robert Nicely.
Давайте рассмотрим некоторые способы оживить SVG в D3 с геоданными. Я сначала решите твердые первым, анимацию пути или вдоль пути. Я буду покрывать Pre-V4 и последнюю версию, поскольку синтаксис почти тот же пост v4.
Есть два общих метода для анимации пути в D3, это ли вы анимируете линию, точку или оба. Первый под названием Interpolation HINC-DASH и второй с именованной интерполяцией точек наряду, различия являются гранулированными. Часто вы можете использовать любой метод для достижения одного типа анимации в целом. Вкратце, разница в точечном пути, вы рассчитываете общую длину пути к анимированию, а в ход-приборной панели вы анимируете в пробелах (DART), выводят из инсульта (путь линии). Итак, вы могли бы подумать об инсуль-тире, как сродни по бокам пленки, с отверстиями, проколотыми во всем, за исключением того, что вы можете варьироваться в зависимости от длины отверстий (или тире), чтобы увеличить или уменьшить точность. Вы анимируете, построенные с одной панели до следующего. Точка в пути, сосредоточена на общей длине пути, в результате, вы делаете немного больше математики. Пункт на пути всегда был больше осенью для меня, поскольку он может анимировать в нескольких ситуациях, которые ход-тире не могут, например, с градиентами. Но различия действительно минуты. Некоторые чувствуют, что он лучше на холсте, WebGL и т. Д. На практике я не видел больших исполнительных различий в любой технике. Для D3.V3 вы загружаете свои запутанные данные, (обход механизма загрузки D3 очень выполняется, но вы должны получить ваши данные в приятный формат Geo-JSON, предыдущий впрыскивание), поскольку D3 дает много преимуществ для эффективности данных, которые он признает, Отказ Вещи, которые происходят на бэкэнде, что обычно облегчает вашу жизнь проще по дороге. Я буду охватывать, как обойти загрузчик и ввести свои собственные прокатные данные в другой статье. Пока что…
var Tiles = L.tileLayer('https://{s}.mapprovider/map/{z}/{x}/{y}', { attribution: 'Terms & Feedback' }); var map = L.map('map') .addLayer(Tiles) .setView([33.215125313, -110.523415], 14); var svg = d3.select(map.getPanes().overlayPane).append("svg"); var g = svg.append("g").attr("class", "leaflet-zoom-hide");
Приведенное выше, устанавливает наш тилелайер или плитки на карте, карта добавляет слой, и SetView фокусируется на карте на области, добавленный номер, устанавливает уровень масштабирования. SVG добавляет слой D3 для рендеринга SVG на карту, а G обрабатывает теневую ошибку, если вы не включаете G, вы увидите стойкие трассы пути при увеличении или выходах. После загруженного, это обычная практика на карту, либо отфильтровать коллекцию ваших функций, какой-то метод лучше всего служить некоторому подмножению. Хорошее правило, используйте фильтр, чтобы обеспечить данные для каждой точки или точность точек (1E7 или сколько 0,000001, и т. Д.), Или, если у вас есть данные, ошибка дистанции, метод путешествия и т. Д.
d3.json("points.geojson", function(features) { //from this point forward, your entire program //should be within this function var data = features.collection.filter(function(d) { if ( d.id === points ){ return d.id; }; }) })
Мы загрузили данные и отфильтровали его. Весь следующий код расположен в функции нагрузки D3.JSON.
var transform = d3.geo.transform({ point: projectPoint }); //these are changed if using V4, to d3.geoPath, incase you're using //a newer version and wonder why yours doesn't work var path = d3.geo.path().projection(transform); function projectPoint(x, y) { var point = map.latLngToLayerPoint(new L.LatLng(y, x)); this.stream.point(point.x, point.y); } var toLine = d3.svg.line() .interpolate('linear') .x(function(d) { return applyLatLngToLayer(d).x }) .y(function(d) { return applyLatLngToLayer(d).y }); function applyLatLngToLayer(d) { var y = d.geometry.coordinates[1] var x = d.geometry.coordinates[0] return map.latLngToLayerPoint(new L.LatLng(y, x)) }
Путь и преобразование принимают регулярные координаты и превращают их в координаты SVG. Проект, применяет эти координаты обратно в слой карт листовки, используя текущий поток. Линия, интерполизирует наши координаты между точками, и последняя функция – это метод, который мы используем для применения координат геометрии к MapLayer.
//Line to animate, between coordinates var linePath = g.selectAll(".linePaths") .data([data]) .enter() .append("path") .attr("class", "linePaths"); //This is the point to animate var marker = g.append('circle') .attr('r', 6) .attr('id', 'marker') .attr('class', 'animatedMarker'); //now we add all the points, so we can animate to them var allPoints = g.selectAll('circle') .data(data) .enter() .append('circle') .attr('r', 2) .attr('class', d => "waypoints " + "c" + d.properties.time) //e6 shorthand .style('opacity', 0);
Так что многое здесь, но и много повторения. Вы заметите, что маркер не имеет пакета данных, это потому, что мы создаем маркер с нуля, поэтому нам не нужно прикрепить его к данным. Кроме того, он будет «объединяться» с другими точками данных, благодаря этому общему выбору круга. Но заметите, чтобы создать, состоит в том, чтобы добавить в этом случае, а в другом случае мы выбираем все точки, у нас нет фактической линейной патки, поэтому оно в существовании одинаковых данных, но мы создадим линии на Иди, как вы увидите.
//this just adjusts the paths and points whenever the view resets, so everything //stays in relation map.on("viewreset", reset); //this draws on the map reset(); //here is the actual reset function for user reposition of the map function reset() { var bounds = path.bounds(features), topLeft = bounds[0], bottomRight = bounds[1]; svg.attr("width", bottomRight[0] - topLeft[0] + 120) .attr("height", bottomRight[1] - topLeft[1] + 120) .style("left", topLeft[0] - 60 + "px") .style("top", topLeft[1] - 60 + "px"); linePath.attr("d", toLine) //here is where we create the linePath g.attr("transform", "translate("+(-topLeft[0] + 60) + "," + (-topLeft[1] + 60) + ")"); }
Если ваш маркер/баллы/пути не поднимаются хорошо с вашей картой, это первое место для поиска виновника. Регулировка большего количества большего количества, увеличит просмотр «коробку» вокруг анимации, в то время как меньшие числа будут перемещать центрирующую точку на MapLayer. Я нашел, что в целом хранения чисел друг другу, это хорошее общее начало. Я Добримую на 30,40,50 и т. Д. Так, соответственно, это было бы 60,80,100 и 120,160,200. И это должно получить вам достаточно близко, чтобы сделать любые незначительные корректировки, которые вам могут понадобиться.
function transition(path) { linePath.transition() .duration(d => d.dur) .attrTween("stroke-dasharray", tweenDash) //there it is, the method for stroke-dasharray interpolation } function tweenDash() { return function(t) { var l = linePath.node().getTotalLength(); //and here is the second method, getting length interpolate = d3.interpolateString("0," + l, l + "," + l); //this is the interpolate for the stroke-dash var marker = d3.select('#marker'); var p = linePath.node().getPointAtLength(t * l); //and the other measurement, to locate the point in path marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); return interpolate(t); } }
И вот и это, вы получаете как линейную анимацию, так и точечную анимацию. В ближайшее время я охвачу V4 + и выделите изменения кода. По какой причине V3 все еще широко используется. Лично у меня нет предпочтений. У них обоих есть какой-то компромисс для удаления версии или оставаясь в V3. Кстати, мы не выходили из нагрузки JSON, поэтому убедитесь, что весь ваш код, находится в этой функции. Следующий пост, я покажу, как мы можем отойти от того, чтобы все было изолировано в этом звонке.