Hoje vamos falar sobre o plugin Polylines Offset que adiciona a habilidade de você desenhar uma linha com um offset (deslocamento) de pixel relativo, sem modificar seus LatLongs reais. O valor do desse offset (deslocamento) pode ser negativo ou positivo, para o deslocamento do lado esquerdo ou do lado direito, e permanece constante nos níveis de zoom.
A ideia do plugin é desenhar uma linha paralela a uma existente, a uma distância fixa. Não é uma simples tradução (x, y) de toda a forma, pois não deve se sobrepor. Ele pode ser usado para enfatizar visualmente diferentes propriedades do mesmo recurso linear ou obter um estilo composto complexo.
1. Instalando o plugin
Caso você esteja utilizando o Node.js você pode instalar o plugin da seguinte forma:
npm install leaflet-polylineoffset
Caso não esteja utilizando o Node.js, pode referenciar diretamente a URL no seu HTML apontando para o GitHub:
<script src="http://bbecquet.github.io/Leaflet.PolylineOffset/leaflet.polylineoffset.js"></script>
2. Dados
Para representar as linhas de ônibus, iremos utilizar um arquivo no formato GeoJSON, conforme demonstrado abaixo:
"features": [ { "type": "Feature", "properties": { "features": [ { "type": "Feature", "properties": { "lines": [0, 1] }, "geometry": { "type": "LineString", "coordinates": [ [ 2.357919216156006, 48.87621773324153 ], [ 2.357339859008789, 48.874834693731664 ], [ 2.362983226776123, 48.86855408432749 ], [ 2.362382411956787, 48.86796126699168 ], [ 2.3633265495300293, 48.86735432768131 ] ] } }
É importante ressaltar a propriedade lines, indica a quais linhas de ônibus o trecho (Feature) representa, podendo representar uma ou mais linhas de ônibus. Ou seja, nesse GeoJSON temos as informações geográficas de todas as nossas linhas de ônibus, que no nosso caso são 4.
3. Adicionando os pontos de parada
Como em toda rede de ônibus, precisamos ter alguns pontos de parada, para o nosso mapa iremos defini-los dinamicamente, como demonstra o código abaixo:
// Adicionando os pontos de parada var ends = []; function addStop(ll) { for(var i=0, found=false; i<ends.length && !found; i++) { found = (ends[i].lat == ll.lat && ends[i].lng == ll.lng); } if(!found) { ends.push(ll); } }
4. Gerando os segmentos das linhas de ônibus
Agora que nossos pontos de parada já estão criados, nós vamos pegar os dados vindos do GeoJSON e organizar as linhas por segmentos, definindo suas propriedades e também criar o offset que visualmente não deixa de ser um buffer ao redor das linhas. Para isso, faremos da seguinte maneira:
// Gera os segmentos de linha var lineSegment, linesOnSegment, segmentCoords, segmentWidth; geoJson.features.forEach(function(lineSegment) { segmentCoords = L.GeoJSON.coordsToLatLngs(lineSegment.geometry.coordinates, 0); linesOnSegment = lineSegment.properties.lines; segmentWidth = linesOnSegment.length * (lineWeight + 1); // Gera o linha ao redor do buffer L.polyline(segmentCoords, { color: '#000', weight: segmentWidth + 5, opacity: 1 }).addTo(outlines); // Gera Buffer ao redor das linhas L.polyline(segmentCoords, { color: '#fff', weight: segmentWidth + 3, opacity: 1 }).addTo(lineBg); // Organiza as linhas por segmento, definindo cor, largura, opacidade e offset for(var j=0;j<linesOnSegment.length;j++) { alert(lineColors[linesOnSegment[j]]); L.polyline(segmentCoords, { color: lineColors[linesOnSegment[j]], weight: lineWeight, opacity: 1, offset: j * (lineWeight + 1) - (segmentWidth / 2) + ((lineWeight + 1) / 2) }).addTo(busLines); } addStop(segmentCoords[0]); addStop(segmentCoords[segmentCoords.length - 1]); });
Por último, vamos adicionar os pontos de ônibus e as camadas ao mapa:
// Adicionando os pontos de ônibus ends.forEach(function(endCoords) { L.circleMarker(endCoords, { color: '#000', fillColor: '#ccc', fillOpacity: 1, radius: 10, weight: 4, opacity: 1 }).addTo(busStops); }); // Adiciona as linhas ao mapa outlines.addTo(map); lineBg.addTo(map); busLines.addTo(map); busStops.addTo(map);
5. Resultado
Após executar os passos acima, o resultado obtido deve ser o seguinte:
6. O Código
Para baixar o código completo, clique aqui.