前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >当我们遇到问题的时候改如何解决

当我们遇到问题的时候改如何解决

作者头像
牛老师讲GIS
发布2018-10-23 10:59:20
1.1K0
发布2018-10-23 10:59:20
举报
文章被收录于专栏:跟牛老师一起学WEBGIS

本文不讲技术,不撸代码,只讲思路。

一、问题

在Openlayers中展示风速风向图,共分为以下两个阶段:

加载PNG图片→加载SVG图片

二、解决

1、加载PNG图片

问题 在Openlayer3中直接加载PNG图片,在API中提供了ImageStatic可以将图片展示出来,但是如何设置图片的imageExtent让图片能够在地图的正确位置展示成了问题的关键。

解决 首先,看到官方的demo里面有个加载ImageStatic的例子,于是就看了一下,官方的例子是通过proj定义了图片的坐标,这样通过坐标转换的方式将静态图片叠加到了地图上。(此过程,我的理解遥感里面做影像的纠正的原理类似。)

有了上面代码的思路,我就想如果我的输出的图片是按照地图的坐标输出的话是不是就可以直接叠加上去而不用做图片的投影了。接下来,就在Arcmap里面打开了一个tif数据,将其直接通过Export Data导出为PNG,并查看其属性获取到图象的四至。

再在代码里面根据输出的PNG和四至信息做测试,哎,思路是对的,能够完美的叠加到地图上。

实现代码

代码语言:javascript
复制
var bounds = [63.9796331669,14.7451916725, 140.181255914,55.4673388687];
var projection = new ol.proj.Projection({
    code: 'EPSG:4326',
    units: 'degrees'
});
var image = new ol.layer.Image({
  source: new ol.source.ImageStatic({
    url: "img/china.png",
    imageExtent: bounds
  })
});

有了上面的测试,终于明白了OL3中StaticImage的加载逻辑。

2、加载SVG图片

由于是PNG图片,在地图放大后会有马赛克现象,特别影像视觉效果,所以为了让展示的效果更加美观,所以就考虑将PNG图片换乘SVG图片。换完之后,首先是在Leaflet中做的测试,比PNG的效果好很多。可当我将SVGyizhi到Openlayers中的时候傻眼了,效果如下:

这个不是臣妾想要的,我想要高清,不要模糊!!!

所以,就开始了研究如何展示SVG。百度、谷歌、必应了一圈后,发现Openlayers的开发者给大家的回复是OL3的版本没法加载SVG!WHAT???没法加载,这不是逗我呢??不过呢,我想这个问题我一定可以解决的!!

后来一直在思考这个问题,有一天突然灵光一现:我可以在地图上面那直接叠加一层SVG的,类似于曾经做过的OL3和echat的结合的逻辑,再绑定地图的事件刷新不就OK了,没错,就是这个思路,哦,此时觉的我就是个天才!

可是当我写好代码,运行代码的时候,发现地图动不了了?怎么办???怎么办???可不能这样啊!!!还好我机智,瞄了一眼OL4的源码,发现地图的时间是在Map这个div上面触发的,所以我就想到了把这个img放到map div里面,代码如下:

代码语言:javascript
复制
self.image = new Image();
self.image.src = self._url;
self._map.getViewport().appendChild(self.image);

再测试,哈哈,妥了,再加点地图事件,就搞定了!此刻深深的被我的聪明才智折服。

但是,我就是这样一个perfect的人,为了更加好用所以我将此扩展成了一个类,源码如下:

代码语言:javascript
复制
/**
 * @author lzugis
 * 2017-10-20
 * @param option, 默认参数如下
   {
        map:null,
        extent:[],
        url:"",
        opacity:1,
        visible:true
    }
 */
ol.layer.SvgImageLayer = function(option){
    this._option = {
        map:null,
        extent:[],
        url:"",
        opacity:1,
        visible:true
    };
    this._init(option);
};
ol.layer.SvgImageLayer.prototype = {
    image:null,
    _init:function(option){
        //将option合并
        for(var opt in option){
            this._option[opt] = option[opt];
        }
        this._map = this._option.map;
        this._extent = this._option.extent;
        this._url = this._option.url;
        this._opacity = this._option.opacity;
        this._visible = this._option.visible;
    },
    addToMap:function(){
        if(this._map) {
            var self = this;
            self.image = new Image();
            self.image.src = self._url;
            self._map.getViewport().appendChild(self.image);
            self._updateImgStyle();
            self._addMapEvent();
        }
        else{
            alert("map参数定义不正确!");
        }
    },
    updateImage: function(option){
        this._init(option);
        if(option.url)this.image.src = this._url;
        this._updateImgStyle();
    },
    hide: function(){
        this.image.style.display = "none";
    },
    show: function(){
        this.image.style.display = "";
    },
    destroy: function(){
        this.image.remove();
    },
    _updateImgStyle: function(){
        var self = this;
        var _min = [self._extent[0], self._extent[1]],
            _max = [self._extent[2], self._extent[3]],
            _topLeft = [self._extent[0], self._extent[3]];
        var _scrMin = self._toScreenPoint(_min),
            _scrMax = self._toScreenPoint(_max),
            _scrTopLeft = self._toScreenPoint(_topLeft);
        var _w = Math.round(_scrMax[0] - _scrMin[0]),
            _h = Math.round(_scrMin[1] - _scrMax[1]),
            _left = _scrTopLeft[0],
            _top = _scrTopLeft[1];
        var cssText = "";
        var styles = {
            "opacity": self._opacity,
            "z-index": 0,
            "position":"absolute",
            "width":_w+"px",
            "height":_h+"px",
            "top":_top+"px",
            "left":_left+"px"
        };
        for(var style in styles){
            cssText+=style+":"+styles[style]+";"
        }
        self.image.style.cssText = cssText;
        self._visible?self.show():self.hide();
    },
    _addMapEvent:function(){
        var self = this;
        self._map.on("precompose",function(evt){
            evt.stopPropagation();
            self._updateImgStyle();
        });
    },
    _toScreenPoint: function(mapPoint){
        var srcPoint = this._map.getPixelFromCoordinate(mapPoint);
        return srcPoint;
    }
};

ol.inherits(ol.layer.SvgImageLayer, ol.layer.base);

实现后,效果如下,心理满满的成就感。。。

正当我沉溺在满满的成就感的时候,有一天,突然发现,我的WMS图层怎么被盖住了???Oh, NO!!!!Kill me!!OL4中map所有的图层都是绘制在一个canvas画布里面的,我叠上去一个图层势必会挡住的,肿么办?what can I do for you??不行,我不能坐以待毙,要是让客户发现这个问题就惨了,客户是我们的衣食父母,这个时候就必须体现我们的专业性和我的钻研性了。

于是乎,上git,扒源码,看了好一阵,都没找到头绪,怎么办,我可不是就此放手的人。恩,先看看API再说,突然,看到了imageSize,凭我的直觉,他应该就是我要找的,这个时候就又不得不发挥我的主观能动性了,计算了一个大小就贴上去,wonderful!!!

附上源码如下:

代码语言:javascript
复制
var bounds = [12836027.844390793, 4745190.4650304755, 13098185.245208949, 5069741.1276835548];
var source = new ol.source.ImageStatic({
    url: "bjoutput/wind.svg",
    imageExtent: bounds,
        imageSize:getImageSize(bounds)
});
image.setSource(source);
//获取图片大小
function getImageSize(bounds){
    var _min = [bounds[0], bounds[1]],
            _max = [bounds[2], bounds[3]],
            _topLeft = [bounds[0], bounds[3]];
    var _scrMin = map.getPixelFromCoordinate(_min),
            _scrMax = map.getPixelFromCoordinate(_max);
    var _w = Math.round(_scrMax[0] - _scrMin[0]),
            _h = Math.round(_scrMin[1] - _scrMax[1]);
    return [_w, _h];
}

三、总结

写此篇的目的是为了告诉大家姿势的正确解锁方式,要善于思考,勤于动手,问题才会解决。


山重水复疑无路,柳暗花明又一村
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年10月26日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题
  • 二、解决
    • 1、加载PNG图片
      • 2、加载SVG图片
      • 三、总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档