OpenLayers3关于Map Export的Canvas跨域

简介: 一 Canvas跨域现象地图导出是地图中常用的功能,并且OpenLayers3中也提供了两个地图导出的例子:http://openlayers.org/en/latest/examples/export-map.html http://openlayers.org/en/latest/examples/export-pdf.html。

一 Canvas跨域现象

地图导出是地图中常用的功能,并且OpenLayers3中也提供了两个地图导出的例子:
http://openlayers.org/en/latest/examples/export-map.html http://openlayers.org/en/latest/examples/export-pdf.html
看到这两个例子我们都很兴奋,直接copy过来不就实现导出地图了吗?so easy,妈妈再也不用担心我导出不了地图图片啦!
但当我们抄好代码执行时,现实就是这么赤裸裸的打脸:
我的代码如下:

 //街道图
    Layer.streetLayer=new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965'
        })
    });

例子的图层代码如下:

 layer=new ol.layer.Tile({ source: new ol.source.OSM() });

没多写一行代码的飘逸,抄过来直接运行,报错如下:


img_ed7d20d595caaff9e6784bb51d9e2a74.png
跨域错误.png

二 问题排查

检查案例源码发现和我抄袭的代码几乎一模一样,唯一区别是我使用的是谷歌底图,例子使用的是osm的source。

 new ol.layer.Tile({ source: new ol.source.OSM() }),

为了一看究竟,我们查看osm的source源码如下:

img_14ff4412e1667915e1f7c7ce881c9ace.png
osm souce源码

恍然大悟,原来只需要添加这 crossOrigin:'anonymous'就可以了。

于是改写重置自己的谷歌图层代码如下:

//街道图
Layer.streetLayer=new ol.layer.Tile({    
       source: new ol.source.XYZ({        
                  crossOrigin: 'anonymous',        
                  url: 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965'    
        })
});

这下打印正常了。

三 加载自己的wms底图还是跨域错误

我们上面通过对谷歌地图加crossOrigin: 'anonymous'实现了地图输出了,解决canvas跨域问题了,但一般我们地图是底图+业务底图(如wms)的,这时候打印发现还是报错。

Layer.streetLayer=new ol.layer.Tile({
        source: new ol.source.XYZ({
            crossOrigin: 'anonymous',
            url: 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965'
        })
    });
Layer.wmsship = new ol.layer.Tile({
        source: new ol.source.TileWMS({
            url: geoserverhost+'/gwc/service/wms',
            params: {'FORMAT': 'image/png',
                'VERSION': '1.1.1',
                tiled: true,
                STYLES: '',
                LAYERS: 'ships:ta_pos_latest'
            }
        })
    });

这个例子我们使用了谷歌底图叠加自己的wms/gwc等瓦片图,发现export还是报跨域错误,理所当让的,我给Layer.wmsship设置crossOrigin: 'anonymous',以为就可以了,但不幸的是仍然报跨域错误,一点没反应。

四 设置服务器cors彻底解决

我们发现,谷歌,osm设置crossOrigin就可以,我们自己wms设置的crossOrigin还是不行。问题出在哪里咧?查阅资料可知,osm,google的服务器一定设置了cors,所以客户端设置crossOrigin才会起作用,而我们自己的wms或者瓦片所在的服务器没有设置cors,所以客户端设置或者不设置crossOrigin,都是无效的。也就是说,只有自己的服务器设置了cors,crossOrigin才会起到作用。
我们地图是geoserver发布的wms或者gwc,对geoserver设置cors,参考之前的博客:http://blog.csdn.net/freeland1/article/details/41204485 ,根据第三节的cors设置下自己的服务器。

服务器设置完毕后,代码改为如下

Layer.streetLayer=new ol.layer.Tile({
        visible: true,
        source: new ol.source.XYZ({
            crossOrigin: 'anonymous',
            url: 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965'
        })
    });
Layer.wmsship = new ol.layer.Tile({
        source: new ol.source.TileWMS({
            crossOrigin: 'anonymous',
            url: geoserverhost+'/gwc/service/wms',
            params: {'FORMAT': 'image/png',
                'VERSION': '1.1.1',
                tiled: true,
                STYLES: '',
                LAYERS: 'ships:ta_pos_latest'
            }
        })
    });

地图输出终于不报错了,perfect!

相关文章
|
Web App开发 JSON JavaScript
前端技术ES6新特性解构字符串扩展表达式箭头函数对象拓展运算符map 和 reduce Promise 模块化export import及Node.js
ECMAScript 6.0(以下简称 ES6,ECMAScript 是一种由 Ecma 国际(前身为欧洲计算机制造商协会,英文名称是 European Computer Manufacturers Association)通过 ECMA-262标准化的脚本程序设计语言)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了,并且从 ECMAScript 6 开始,开始采用年号来做版本。即 ECMAScript 2015,就是 ECMAScript6。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
68 0
|
3月前
|
Dart
Dart之集合详解(List、Set、Map)
Dart之集合详解(List、Set、Map)
|
3月前
|
存储 JavaScript 前端开发
JavaScript进阶-Map与Set集合
【6月更文挑战第20天】JavaScript的ES6引入了`Map`和`Set`,它们是高效处理集合数据的工具。`Map`允许任何类型的键,提供唯一键值对;`Set`存储唯一值。使用`Map`时,注意键可以非字符串,用`has`检查键存在。`Set`常用于数组去重,如`[...new Set(array)]`。了解它们的高级应用,如结构转换和高效查询,能提升代码质量。别忘了`WeakMap`用于弱引用键,防止内存泄漏。实践使用以加深理解。
58 3
|
29天前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
22天前
|
Java
【Java集合类面试二十二】、Map和Set有什么区别?
该CSDN博客文章讨论了Map和Set的区别,但提供的内容摘要并未直接解释这两种集合类型的差异。通常,Map是一种键值对集合,提供通过键快速检索值的能力,而Set是一个不允许重复元素的集合。
|
22天前
|
算法 Java 索引
【Java集合类面试四】、 描述一下Map put的过程
这篇文章详细描述了HashMap中put操作的过程,包括首次扩容、计算索引、插入数据以及链表转红黑树和可能的再次扩容。
【Java集合类面试四】、 描述一下Map put的过程
|
1月前
|
存储
|
22天前
|
安全 Java
【Java集合类面试五】、 如何得到一个线程安全的Map?
如何得到一个线程安全的Map的方法包括:使用Collections工具类将Map包装为线程安全,使用java.util.concurrent包下的ConcurrentHashMap,以及不推荐使用性能较差的Hashtable。
|
22天前
|
安全 Java
【Java集合类面试三】、Map接口有哪些实现类?
这篇文章介绍了Java中Map接口的几种常用实现类:HashMap、LinkedHashMap、TreeMap和ConcurrentHashMap,以及它们适用的不同场景和线程安全性。
|
2月前
|
存储 安全 Java
Java基础之集合Map
【7月更文挑战第8天】Java中的Map集合以键值对方式存储数据,如`Map<"name", "张三">`。Map接口定义了存取、判断、移除等操作,包括`put`、`get`、`containsKey`等方法。HashMap是最常用的实现,基于哈希表,允许null键值,但不保证顺序。其他实现包括同步的Hashtable、处理属性文件的Properties、保持插入顺序的LinkedHashMap、基于红黑树的TreeMap、弱引用的WeakHashMap、并发安全的ConcurrentHashMap和针对枚举优化的EnumMap。
30 4