一、原理
实现鹰眼图的主要搭配方法是Cesium原生、Cesium-Leaflet、Cesium-OpenLayer三种方法。
本文以Cesium作为三维地球框架,以Leaflet作为二维地图框架,来实现鹰眼图的效果。
二、代码
分别引入Cesium和Leaflet的JS和CSS。
$(function () {
initWork();
})
function initWork () {
overMap.init(viewer);
}
var overMap = {
init: function (viewer) {
this.viewer = viewer,
this.mapEle = window.document.createElement("div"),
this.mapEle.setAttribute("id", "map2d"),
this.mapEle.style.height = "250px",
this.mapEle.style.width = "300px",
this.mapEle.style.position = "absolute",
this.mapEle.style.bottom = "30px",
this.mapEle.style.right = "10px",
document.body.appendChild(this.mapEle),
this.showStyle = {
color: "#ff7800", weight: 1, fill: !0, stroke: !0, opacity: 1
},
this.hideStyle = { fill: !1, opacity: 0 },
this.map = L.map('map2d', {
center: [31.827107, 117.240601],
zoom: 13,
zoomControl: false,
attributionControl: false
})
var mapUrl = "http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}";
L.tileLayer(mapUrl, {
maxZoom: 18,
tileSize: 256,
}).addTo(this.map),
// L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
// }).addTo(this.map),
this.viewer.scene.postRender.addEventListener(
this.sceneRenderHandler, this);
},
sceneRenderHandler: function (e) {
var ext = getExtent(this.viewer),
i = L.latLng(ext.ymin, ext.xmin),
s = L.latLng(ext.ymax, ext.xmax),
bounds = L.latLngBounds(i, s);
if (this.rectangle ? this.rectangle.setBounds(bounds) : this.rectangle = L.rectangle(bounds, this.showStyle).addTo(this.map), -180 == ext.xmin && 180 == ext.xmax && 90 == ext.ymax && -90 == ext.ymin) {
var center = getCenter(this.viewer);
this.map.setView([center.y, center.x], 0),
this.rectangle.setStyle(this.hideStyle)
}
else {
var oBounds = bounds.pad(.5);
this.map.fitBounds(oBounds),
this.rectangle.setStyle(this.showStyle)
}
},
hide: function () {
this.mapEle && (this.mapEle.style.display = "none")
},
show: function () {
this.map && this.mapEle && (this.mapEle.style.display = "block")
},
setStyle: function (e) {
e && (this.showStyle = e)
},
destroy: function () {
this.mapEle && document.getElementsByTagName("body").removeChild(this.mapEle), this.viewer.scene.postRender.removeEventListener(this.sceneRenderHandler, this)
}
}
function getExtent (viewer) {
var rectangle = viewer.camera.computeViewRectangle(),
result = getMinMax(rectangle);
if (result.xmax < result.xmin) {
var s = result.xmax;
result.xmax = result.xmin,
result.xmin = s
}
if (result.ymax < result.ymin) {
var s = result.ymax;
result.ymax = result.ymin,
result.ymin = s
}
return result
}
function getMinMax (rectangle) {
var t = Number(Cesium.Math.toDegrees(rectangle.west)).toFixed(6),
i = Number(Cesium.Math.toDegrees(rectangle.east)).toFixed(6),
n = Number(Cesium.Math.toDegrees(rectangle.north)).toFixed(6);
return {
xmin: t,
xmax: i,
ymin: Number(Cesium.Math.toDegrees(rectangle.south)).toFixed(6),
ymax: n
}
}
function getCenter (viewer) {
var scene = viewer.scene,
pos = getPos(scene),
position = pos;
if (!position) {
var globe = scene.globe,
cartographic = scene.camera.positionCartographic.clone(),
height = globe.getHeight(cartographic);
cartographic.height = height || 0,
cartesian = Cesium.Ellipsoid.WGS84.cartographicToCartesian(cartographic)
}
var result = toCartographic(position);
var d = Cesium.Cartesian3.distance(position, viewer.scene.camera.positionWC);
return result.cameraZ = d,
result
}
function getPos (scene) {
var canvas = scene.canvas,
center = new Cesium.Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2),
ray = scene.camera.getPickRay(center);
return scene.globe.pick(ray, scene) || scene.camera.pickEllipsoid(center)
}
function toCartographic (cartesian) {
var cartographic = Cesium.Cartographic.fromCartesian(cartesian),
result = {};
return result.y = Number(Cesium.Math.toDegrees(cartographic.latitude)).toFixed(6),
result.x = Number(Cesium.Math.toDegrees(cartographic.longitude)).toFixed(6),
result.z = Number(cartographic.height).toFixed(2),
result
}
三、效果图