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

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

一、问题

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

加载PNG图片→加载SVG图片

二、解决

1、加载PNG图片

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

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

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

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

实现代码

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里面,代码如下:

self.image = new Image();
self.image.src = self._url;
self._map.getViewport().appendChild(self.image);

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

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

/**
 * @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!!!

附上源码如下:

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];
}

三、总结

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


山重水复疑无路,柳暗花明又一村

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MixLab科技+设计实验室

自己动手做一个识别手写数字的web应用04

接着往期的3篇继续,一步步动手做: 自己动手做一个识别手写数字的web应用01 自己动手做一个识别手写数字的web应用02 自己动手做一个识别手写数字的web应...

1.2K5
来自专栏我有一个梦想

UE4新手编程之创建空白关卡和添加碰撞体

让我们接着上次继续学习UE4引擎,今天我们学习下怎样创建空白的关卡以及添加碰撞物体。 一. 创建空白关卡 1) 点击文件 -> 新建关卡(或者按快捷键Ctrl+...

2729
来自专栏李成熙heyli

React移动web极致优化

本文start kit: steamer-react PS: 要看效果得将一个QQ群组转换成家校群,可到此网址进行转换(手Q/PC都可以访问): http:/...

2768
来自专栏理论坞

“模糊”我见多了,从来没见过你这样的- -#(

衔接呢,我认为还是模糊比较好用,比如这头驴的舌头、牙齿、毛发…人家是馬(#‵′)凸

955
来自专栏walterlv - 吕毅的博客

UWP 将图片裁剪成圆形(椭圆)

2018-06-15 13:21

1131
来自专栏CDA数据分析师

教你掌握Excel中最为重要的逻辑 ——「链接」(一)

如果把Excel比作武侠小说中的“剑”,那么按照武侠小说中御“剑”能力的高低程度可以大致将剑客分为以下几个等级: Level 1(剑客):小说中常见的劫匪甲乙...

2287
来自专栏数据小魔方

think-cell chart 系列1——堆积柱形图!

今天正式开始跟大家分享之前介绍过的图表插件——think-cell chart 。 要讲的第一个图表类型是其自带图表库中的第一个图表——堆积柱形图。 在正式开始...

5976
来自专栏点滴积累

Cesium基础使用介绍

前言 最近折腾了一下三维地球,本文简单为大家介绍一款开源的三维地球软件——Cesium,以及如何快速上手Cesium。当然三维地球重要的肯定不是数据显示,这只是...

1.6K6
来自专栏数据的力量

我们来做瀑布图

1403
来自专栏理论坞

【教程】C4D样条字设计终极版 | 附源文件工程

在站酷关于C4D的样条约束文字设计教程自己注到的共有三篇, 设计文章写的都非常细致,效果也都是各有长的,有很多学习点 然后最近本人也在国外设计B站看到了几位国外...

902

扫码关注云+社区

领取腾讯云代金券