当你需要加载地图,或者需要使用地图的某些功能时,是不是会出现如下的报错信息?
1、跨域
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
2、画布污染
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
那么,什么是跨域呢?
浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了。具体可以参考不要再问我跨域的问题了。
我们需要加载的地图说白了也就是图片文件的切片展示,所以地图产生的跨域也不外乎是上述原因。
下面是两个我在项目中遇到的应用场景:
1、调用http://www.xxmap.cn/api/feature/query?tkey=学校&size=9999这个地图服务来获取9999条学校数据,结果出现跨域错误。
2、在对某地图进行截图的时候显示画布污染。
这种地图产生的跨域改怎么解决呢?有些文章中提到进行如下设置
img.crossOrigin = "Anonymous";
这个我试过不可行,依然会报画布污染,无法截图。经过研究解决这个问题的一个好办法就是代理。废话不说了,直接贴代码proxy.jsp
<%@ page import="java.net.*,java.util.*,java.lang.*,java.io.*"%>
<%@ page contentType="text/xml;charset=UTF-8" pageEncoding="UTF-8"%>
<%
out.clearBuffer();
String urlStr = null;
StringBuffer params = new StringBuffer();
Enumeration enu = request.getParameterNames();
int total = 0;
while (enu.hasMoreElements()) {
String paramKey = (String) enu.nextElement();
String paramValue = request.getParameter(paramKey);
// System.out.println(paramKey + "=" + paramValue);
if (paramKey.equals("url")) {
urlStr = paramValue;
}
else {
if (total != 0) {
params.append("&");
}
params.append(paramKey).append("=").append(paramValue);
total++;
}
}
InputStream inputStream = null;
ServletOutputStream outputStream = null;
if (urlStr != null) {
if (urlStr.contains("?")) {
urlStr = urlStr + "&" + params.toString();
} else {
urlStr = urlStr + "?" + params.toString();
}
// System.out.println(urlStr);
// 使用GET方式向目的服务器发送请求
try {
URL url = new URL(urlStr);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
inputStream = urlConnection.getInputStream();
outputStream = response.getOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
}
catch(Exception e) {
e.printStackTrace();
}
finally {
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
out.clear();
//out.clearBuffer();
out = pageContext.pushBody();
}
}
%>
调用方法如下:
source:new ol.source.WMTS({
url:"../proxy?url="+mapUrl,
projection: ol.proj.get(this.projection_),
style: style,
format: format,
matrixSet: tilematrixset,
layer: layerName,
version: version,
tileGrid: this.tileGrid_,
wrapX:true,
})
总算解决了一大难题: