近期工作需要设计交通图,故需要设计一些类似铁路,桥梁,隧道等样式,在此记录下样式的一些效果。可能有更好的实现方式,在这里 就当抛转引玉了。
参考文章:
https://www.jianshu.com/p/e68e8e1b7474
1.铁路
需要设计以下两种样式,一种再建的,一种已完工的
样式代码:
//铁路已完工
[new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#000000",width:6,lineCap:"butt"}),zIndex:20}),new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#ffffff",width:6,lineDash:[15,15],lineCap:"butt"}),zIndex:21})]
//铁路再建
[new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#000000",width:6,lineDash:[15,45],lineCap:"butt"}),zIndex:20}),new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#ffffff",width:6,lineDash:[15,45],lineDashOffset:30,lineCap:"butt"}),zIndex:21})]
效果:
2.街道
街道大致就是白色的底加上黑色的边
样式代码
[new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#000000",width:10,lineCap:"butt"}),zIndex:20}),new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#ffffff",width:6,lineCap:"butt"}),zIndex:21})]
效果
3.隧道和桥梁
大致的想法是,利用街道的样式稍微做下调整,然后取线段的最后一个点和第一个点,加上分叉的样式,分叉点准备采用图片来弄,图个便利。
图片
样式代码
//桥梁样式
//因为绘制的时候用的是MultiLineString,如果用的是LineString,请自行调整代码
function drawsty(feature){
var myStyle = [];myStyle.push(new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#000000",width:10,lineCap:"butt"}),zIndex:20}));myStyle.push(new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#FFFFFF",width:6,lineCap:"butt"}),zIndex:21}));var linearr = feature.getGeometry().getLineStrings();$.each(linearr,function(i,j){
var firstcoord = j.getFirstCoordinate().join(",");var lastcoord =j.getLastCoordinate().join(",");//因为要给图片设置角度,所以需要遍历线的每一段,然后计算出图片需要旋转的角度j.forEachSegment(function(start, end) {
if(firstcoord == start.join(",")){
var dx = end[0]- start[0];var dy = end[1] - start[1];var rotation = Math.atan2(dy, dx);myStyle.push(new ol.style.Style({
geometry: new ol.geom.Point(start),image: new ol.style.Icon({
src: "image/bridge.png",scale:0.8,rotation: -rotation-Math.PI/2//图片旋转角度,请自行调整})}));}if(lastcoord == end.join(",")){
var dx = end[0]- start[0];var dy = end[1] - start[1];var rotation = Math.atan2(dy, dx);myStyle.push(new ol.style.Style({
geometry: new ol.geom.Point(end),image: new ol.style.Icon({
src: "image/bridge.png",scale:0.8,rotation: -rotation+Math.PI/2})}));}});})return myStyle;}//隧道样式,隧道和桥梁的不同点是,隧道的黑色边框是虚线function drawsty(feature){
var myStyle = [];myStyle.push(new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#000000",width:10,lineDash:[15,1],lineCap:"butt"}),zIndex:20}));myStyle.push(new ol.style.Style({
stroke: new ol.style.Stroke({
color:"#FFFFFF",width:6,lineCap:"butt"}),zIndex:21}));var linearr = feature.getGeometry().getLineStrings();$.each(linearr,function(i,j){
var firstcoord = j.getFirstCoordinate().join(",");var lastcoord =j.getLastCoordinate().join(",");j.forEachSegment(function(start, end) {
if(firstcoord == start.join(",")){
var dx = end[0]- start[0];var dy = end[1] - start[1];var rotation = Math.atan2(dy, dx);myStyle.push(new ol.style.Style({
geometry: new ol.geom.Point(start),image: new ol.style.Icon({
src: "image/tunnel.png",scale:0.8,rotation: -rotation+Math.PI/2})}));}if(lastcoord == end.join(",")){
var dx = end[0]- start[0];var dy = end[1] - start[1];var rotation = Math.atan2(dy, dx);myStyle.push(new ol.style.Style({
geometry: new ol.geom.Point(end),image: new ol.style.Icon({
src: "image/tunnel.png",scale:0.8,rotation: -rotation-Math.PI/2})}));}});})return myStyle;}
效果:
4.高德地图导航样式
采用rbush实现该功能
箭头图片
样式代码
function styleFunction(feature,res){
//轨迹线图形 此处我自己用的是MultiLineStringvar trackLine= feature.getGeometry().getLineStrings()[0];var styles = [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#2E8B57',width: 10}),zIndex:3}),new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#000000',width: 12}),zIndex:1})];//对segments建立btree索引let tree= rbush();//路段数trackLine.forEachSegment(function(start, end) {
var dx = end[0] - start[0];var dy = end[1] - start[1];//计算每个segment的方向,即箭头旋转方向let rotation = Math.atan2(dy, dx);let geom=new ol.geom.LineString([start,end]);let extent=geom.getExtent();var item = {
minX: extent[0],minY: extent[1],maxX: extent[2],maxY: extent[3],geom: geom,rotation:rotation};tree.insert(item);});//轨迹地理长度let length=trackLine.getLength();console.log(length);//像素间隔步长let stpes=40;//像素步长间隔//将像素步长转实际地理距离步长let geo_steps=stpes*res;//箭头总数let arrowsNum=parseInt(length/geo_steps);for(let i=1;i<arrowsNum;i++){
let arraw_coor=trackLine.getCoordinateAt(i*1.0/arrowsNum);let tol=10;//查询设置的点的容差,测试地图单位是米。如果是4326坐标系单位为度的话,改成0.0001.let arraw_coor_buffer=[arraw_coor[0]-tol,arraw_coor[1]-tol,arraw_coor[0]+tol,arraw_coor[1]+tol];//进行btree查询var treeSearch = tree.search({
minX: arraw_coor_buffer[0],minY: arraw_coor_buffer[1],maxX: arraw_coor_buffer[2],maxY: arraw_coor_buffer[3]});let arrow_rotation;//只查询一个,那么肯定是它了,直接返回if(treeSearch.length==1)arrow_rotation=treeSearch[0].rotation;else if(treeSearch.length>1){
let results=treeSearch.filter(function(item){
//箭头点与segment相交,返回结果。该方法实测不是很准,可能是计算中间结果//保存到小数精度导致查询有点问题// if(item.geom.intersectsCoordinate(arraw_coor))// return true;//换一种方案,设置一个稍小的容差,消除精度问题let _tol=1;//消除精度误差的容差if(item.geom.intersectsExtent([arraw_coor[0]-_tol,arraw_coor[1]-_tol,arraw_coor[0]+_tol,arraw_coor[1]+_tol]))return true;})if(results.length>0)arrow_rotation=results[0].rotation;}styles.push(new ol.style.Style({
geometry: new ol.geom.Point(arraw_coor),image: new ol.style.Icon({
src: 'image/arrow.png',scale:0.4,rotation: -arrow_rotation+Math.PI/2}),zIndex:3}));}return styles;}
效果