OpenLayers学习笔记(二)

OpenLayers学习笔记(二)

中级篇

地图的分辨率设置
// 添加一个显示Open Street Map地图瓦片网格的图层
new ol.layer.Tile({
    source: new ol.source.TileDebug({
        projection: 'EPSG:3857',
        tileGrid: osmSource.getTileGrid()
    })
})

OpenLayers 3提供了一个用于调试瓦片的source: ol.source.TileDebug。可以清晰的看到每一个瓦片的坐标,这是我们用来显示瓦片坐标的方法。
瓦片坐标中有3个数字,第一个数字是层级z,第二个数字是表示经度方向上的x,第三个数字是表示维度方向上的y。
OpenLayers 3的ol.Map已提供了对应的方法getCoordinateFromPixel来帮助你实现坐标转换。
计算分辨率

// 监听层级变化,输出当前层级和分辨率
map.getView().on('change:resolution', function(){
    document.getElementById('zoom').innerHTML =  this.getZoom() + ',';
    document.getElementById('resolution').innerHTML = this.getResolution();
})
document.getElementById('zoom').innerHTML = map.getView().getZoom() + ',';
document.getElementById('resolution').innerHTML = + map.getView().getResolution();

地图图标操作

OpenLayer3中添加图标有两种方式,一种是比较传统的overlay,另一种是Feature + Style的方式。

<div id="anchor"><img src="img/star.png" alt="示例五角星"/></div>
// 下面把上面的图标附加到地图上,需要一个ol.Overlay
var anchor = new ol.Overlay({
    element: document.getElementById('anchor')
});
// 关键的一点,需要设置附加到地图上的位置
anchor.setPosition([116.403598,39.917553]);
// 然后添加到map上
map.addOverlay(anchor);

方法的优缺点

缺点:

  • 当图标比较多的情况下,如果采用这种方式,那么我们会加入非常多的HTML元素,从而造成效率降低。 界面上元素的遍历在数量比较多的情况下,会变慢,基于此基础上的渲染,鼠标事件都会变慢。

优点:

  • 这种使用传统的方式显示图标可以应用传统的HTML技术,比如鼠标移动到图标上,鼠标图标变成手势。 我们可以用css来处理就可以了
<style type="text/css">
    #anchor {
        cursor:pointer;
    }
</style>

给图标添加动画效果

<style type="text/css">
      @keyframes zoom
      {
        from {top: 0; left: 0; width: 32px; height: 32px;}
        50% {top: -16px; left: -16px; width: 64px; height: 64px;}
        to {top: 0; left: 0; width: 32px; height: 32px;}
      }
/* Firefox */
      @-moz-keyframes zoom 
      {
        from {top: 0; left: 0; width: 32px; height: 32px;}
        50% {top: -16px; left: -16px; width: 64px; height: 64px;}
        to {top: 0; left: 0; width: 32px; height: 32px;}
      }
/* Safari 和 Chrome */
      @-webkit-keyframes zoom 
      {
        from {top: 0; left: 0; width: 32px; height: 32px;}
        50% {top: -16px; left: -16px; width: 64px; height: 64px;}
        to {top: 0; left: 0; width: 32px; height: 32px;}
      }
/* Opera */
      @-o-keyframes zoom 
      {
        from {top: 0; left: 0; width: 32px; height: 32px;}
        50% {top: -16px; left: -16px; width: 64px; height: 64px;}
        to {top: 0; left: 0; width: 32px; height: 32px;}
      }
 
      /* 应用css动画到图标元素上 */
      #anchorImg
      {
        display: block;
        position: absolute;
        animation: zoom 5s;
        animation-iteration-count: infinite; /* 一直重复动画 */
        -moz-animation: zoom 5s; /* Firefox */
        -moz-animation-iteration-count: infinite; /* 一直重复动画 */
        -webkit-animation: zoom 5s;  /* Safari 和 Chrome */
        -webkit-animation-iteration-count: infinite; /* 一直重复动画 */
        -o-animation: zoom 5s; /* Opera */
        -o-animation-iteration-count: infinite; /* 一直重复动画 */
      }
</style>

Feture+Style的方式加载图标

// 我们需要一个vector的layer来放置图标
var layer = new ol.layer.Vector({
    source: new ol.source.Vector()
})
// 创建一个Feature,并设置好在地图上的位置
var anchor = new ol.Feature({
    geometry: new ol.geom.Point([104, 30])
});
// 设置样式,在样式中就可以设置图标
anchor.setStyle(new ol.style.Style({
    image: new ol.style.Icon({
        src: 'img/star.png'
    })
}));
// 添加到之前的创建的layer中去
layer.getSource().addFeature(anchor);

流程:需要一个vector的layer来放置图标,然后我们创建一个Feature,并设置好在地图上的位置,然后设置样式Feature,在样式中就可以设置图标,最后将feature添加到之前的创建的layer中去。

overlayer和feature方式加载的异同点:

  • 首先overlay需要HTML元素img,但这种方式不需要
  • overlay是添加在map上的,但是这种方式需要一个Vector的layer,并添加在地图上
  • 我们没有办法像overlay那样使用一些HTML技术

ol.style.Icon的构造参数,会看到可以设置位置,透明度,放大缩小,旋转等

根据层级放大缩小图标

ol.style.Icon中是可以设置scale,通过它可以使图标层级放大缩小。

// 监听地图层级变化
map.getView().on('change:resolution', function(){
    var style = anchor.getStyle();
    // 重新设置图标的缩放率,基于层级20来做缩放
    style.getImage().setScale(this.getZoom() / 20);
    anchor.setStyle(style);
})

通过绘制的形式直接加载图标

OpenLayers 3提供了一个规则几何体的样式类ol.style.RegularShape

// 添加一个三角形
var shape = new ol.Feature({
    geometry: new ol.geom.Point([116.203598,39.927553])
});
shape.setStyle(new ol.style.Style({
    image: new ol.style.RegularShape({
        points: 3,    // 顶点数
        radius: 20,    // 图形大小,单位为像素
        //radius1: 20, // 外圈大小
        //radius2: 10, // 内圈大小
        stroke: new ol.style.Stroke({ // 设置边的样式
            color: 'red',
            size: 5
        }),
        fill: new ol.style.Fill({ // 设置五星填充样式
            color: 'blue'
        })
    })
}));
layer.getSource().addFeature(shape);

不规则的图标(用canvas自己绘制)

// 使用canvas绘制一个不规则几何图形
var canvas =document.createElement('canvas');
    canvas.width = 40;
    canvas.height = 40;
var context = canvas.getContext("2d");
    context.strokeStyle = "red";  
	context.lineWidth = 3;  
	context.beginPath();   
    context.moveTo(0, 0);
	context.lineTo(20, 10);
	context.lineTo(0, 20);
	context.lineTo(10, 10);
	context.lineTo(0, 0);  
	context.stroke();
// 把绘制了的canvas设置到style里面
var style = new ol.style.Style({
    image: new ol.style.Icon({
        img: canvas,
        imgSize: [canvas.width, canvas.height],
        rotation: 90 * Math.PI / 180
    })
});
// 创建一个Feature
var shape = new ol.Feature({
	geometry: new ol.geom.Point([116.403598,39.917553])
});
// 应用具有不规则几何图形的样式到Feature
shape.setStyle(style);
layer.getSource().addFeature(shape);

我们成功绘制了不规则图标并把它加入到了地图中!我们使用了ol.style.Icon样式的img属性来设置,需要注意的是,必须设置imgSize属性,因为仅仅通过img设置的图像对象,没有办法自动获取宽高。 同时,官网也提供了一个类似的例子earthquake-custom-symbol,只是使用OpenLayers3 内部提供的封装库来绘制图像到canvas上,原理一样。

根据环境条件动态修改图标样式

空心五角星,点击变红

// 添加一个空心的五星
var star = new ol.Feature({
    geometry: new ol.geom.Point([116.403598,39.917553])
  });
star.setStyle(new ol.style.Style({
    image: new ol.style.RegularShape({
        points: 5,
        radius1: 20,
        radius2: 10,
        stroke: new ol.style.Stroke({
            color: 'red',
            size: 2
        })
    })
}));
layer.getSource().addFeature(star);
// 监听地图点击事件
map.on('click', function(event){
    var feature = map.forEachFeatureAtPixel(event.pixel, function(feature){
        return feature;
    });
    if (feature) {
      	alert("我要红了")
        // 将空心五星为红色实心五星
        var style = feature.getStyle().getImage();
        feature.setStyle(new ol.style.Style({
            image: new ol.style.RegularShape({
                 points: 5,
                 radius1: 20,
                 radius2: 10,
                 stroke: style.getStroke(),
                 fill: new ol.style.Fill({
                     color: 'red'
                 })
             })
         }));
     }
});

加载文字

var anchor = new ol.Feature({
    geometry: new ol.geom.Point([116.403598,39.917553])
});
// 设置文字style
anchor.setStyle(new ol.style.Style({
    text: new ol.style.Text({
        font: '15px sans-serif',  //默认这个字体,可以修改成其他的,格式和css的字体设置一样
        text: '北京天安门',
        fill: new ol.style.Fill({
            color: 'red'
        })
    })
}));
layer.getSource().addFeature(anchor);

styleFunction的应用

// 应用style function,动态的获取样式
anchor.setStyle(function(resolution){
    return [new ol.style.Style({
        image: new ol.style.Icon({
             src: 'img/star.png',
             scale: map.getView().getZoom() / 20
        })
    })];
});

在这个例子中,我们是在feature上应用了styleFunction,通过官网API文档可以看到,其类型为ol.FeatureStyleFunction,函数仅带有一个参数resolution,在上面的代码中看到了,在函数体内this指的是当前的feature,根据文档说明,这个函数要范围一个style数组。

除了feature可以设置样式之外,layer也是可以设置样式的,同样地也支持styleFunction,但是需要注意的是,其定义和feature的不一样,类型为ol.style.StyleFunction,该函数具有两个参数,第一个参数为feature,第二个参数为resolution,同样地,该函数需要返回style数组。

// 创建layer使用的style function,根据feature的自定义type,返回不同的样式
  var layerStyleFunction = function(feature, resolution) {
    var type = feature.get('type');
    var style = null;
    // 点
    if (type === 'point') {
      style = new ol.style.Style({
        image: new ol.style.Circle({
          radius: 5,
          fill: new ol.style.Fill({
            color: 'red'
          })
        })
      });
    } else if ( type === 'circle') { // 圆形
      style = new ol.style.Style({
        image: new ol.style.Circle({
          radius: 20,
          stroke: new ol.style.Stroke({
            color: 'red',
            size: 3
          })
        })
      });
    } else { // 其他形状
      style = new ol.style.Style({
        image: new ol.style.RegularShape({
          points: 5,
          radius: 20,
          fill: new ol.style.Fill({
            color: 'blue'
          })
        })
      });
    }
 
    // 返回 style 数组
    return [style];
  };
 
  var layer2 = new ol.layer.Vector({
    source: new ol.source.Vector(),
    style: layerStyleFunction // 应用上面创建的 style function
  });
 
  var map2 = new ol.Map({
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }), 
      layer2
    ],
    target: 'map2',
    view: new ol.View({
      projection: 'EPSG:4326',
      center: [104, 30],
      zoom: 10
    })
  });
 
  // 添加三个feature,并设置自定义属性 type
  var rect = new ol.Feature({
    geometry: new ol.geom.Point([104, 30])
  });
  layer2.getSource().addFeature(rect);
 
  var circle = new ol.Feature({
    geometry: new ol.geom.Point([104, 30])
  });
  circle.set('type', 'circle');
  layer2.getSource().addFeature(circle);
 
  var point = new ol.Feature({
    geometry: new ol.geom.Point([104, 30])
  });
  point.set('type', 'point');
  layer2.getSource().addFeature(point);

参考博文:https://blog.csdn.net/MagicMHD/article/details/91360052
https://blog.csdn.net/MagicMHD/article/details/91360954

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值