OpenLayers3关于Map Export的Canvas跨域

一 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() });

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


OpenLayers3关于Map Export的Canvas跨域
跨域错误.png

二 问题排查

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

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

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

OpenLayers3关于Map Export的Canvas跨域
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!

上一篇:PostgreSQL流复制热备


下一篇:Centos7安装PostgreSQL