效果展示
代码实现
- 公共方法代码
import { Tile as TileLayer } from "ol/layer";
//高德瓦片图层
const gaodeMapLayer = new TileLayer({
source: new XYZ({
url: "http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
}),
name: "高德地图",
});
//地图定位动画
function bounce(t) {
const s = 7.5625;
const p = 2.75;
let l;
if (t < 1 / p) {
l = s * t * t;
} else {
if (t < 2 / p) {
t -= 1.5 / p;
l = s * t * t + 0.75;
} else {
if (t < 2.5 / p) {
t -= 2.25 / p;
l = s * t * t + 0.9375;
} else {
t -= 2.625 / p;
l = s * t * t + 0.984375;
}
}
}
return l;
}
- 两个地图初始化
mounted() {
//用同一个View实例,实现地图同步联动
let commonView = new View({
center: transform([104.065759, 30.657416], "EPSG:4326", "EPSG:3857"),
zoom: 11,
minZoom: 1,
maxZoom: 21,
projection: "EPSG:4326",
rotation: 0,
}),
commoninteractions = defaultInteractions({
doubleClickZoom: false, // 取消双击放大功能交互
// dragPan: false,
//mouseWheelZoom: false, // 取消滚动鼠标中间的滑轮交互
// shiftDragZoom: false, // 取消shift+wheel左键拖动交互
});
let map = new Map({
// 设置地图图层
layers: [],
// 设置显示地图的视图
view: commonView,
// 让id为map的div作为地图的容器
target: "areas",
interactions: commoninteractions,
});
let godeMap = new Map({
// 设置地图图层
layers: [gaodeMapLayer],
// 设置显示地图的视图
view: commonView,
// 让id为map的div作为地图的容器
target: "map_",
interactions: commoninteractions,
});
},
- 行政区数据拉取
mounted() {
this.getF(
"https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full",
map,
godeMap
);
},
methods:{
async getF(url, map, godeMap) {
let res = await axios.get(url),
geojsonData = res.data,
commonGeom = new GeoJSON().readFeatures(geojsonData),
layer = layer_(commonGeom, true, {}, 1, stylFn),
mask = layer_(commonGeom, true, {}, 1, maskStyle);
map.addLayer(layer);
godeMap.addLayer(mask);
godeMap.getView().fit(mask.getSource().getExtent());
this.addEventListenerMAP(map, godeMap);
}
}
- 地图ponitmove、singleclick事件监听
addEventListenerMAP(map, godeMap) {
let _this = this;
map.on("pointermove", (evt) => {
let _this = this,
MapLayers = map.getLayers().getArray();
if (MapLayers.length <= 0) {
return;
}
let _showLayer = MapLayers.filter((_layer) => _layer.getVisible())[0],
_curreutFeatures = _showLayer.getSource().getFeatures(),
pixel = map.getEventPixel(evt.originalEvent),
hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? "pointer" : "";
map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
let properties = feature.getProperties();
_curreutFeatures.forEach((_feature) => {
let _properties = _feature.getProperties();
if (properties.adcode === _properties.adcode) {
_feature.setStyle(() => {
return new Style({
stroke: null,
fill: new Fill({ color: 'rgba(103, 194, 58,0.3)' }),
text: new Text({
text: properties.name,
textAlign: "center",
font: "bolder 14px PingFangSC ",
padding: [0, 0, 0, 0],
overflow: true,
fill: new Fill({
color: "#000",
}),
backgroundFill: null,
}),
});
});
} else {
_feature.setStyle(null);
}
});
});
});
map.on("singleclick", (evt) => {
map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
let properties = feature.getProperties(),
{ adcode, level } = properties;
console.log(properties);
if (level !== "district") {
_this.getNex(adcode, map, godeMap);
}
});
});
},
- layer显示和隐藏动画
methods:{
async getNex(adcode, map, godeMap) {
let res = await axios.get(
`https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${adcode}_full`
),
geoData = res.data,
Geom = new GeoJSON().readFeatures(geoData),
layer = layer_(Geom, true, {}, 0, stylFn),
mask = layer_(Geom, true, {}, 0, maskStyle),
_this = this;
//获取suoce
this.HideLayer(map, godeMap, () => {
_this.showLayer(map, godeMap, layer, mask);
});
},
HideLayer(map, godeMap, callBack) {
let n = 1,
timeID,
layer = map.getLayers().getArray()[0],
mask = godeMap.getLayers().getArray()[1];
console.log(mask);
timeID = setInterval(() => {
n = n - 0.1;
layer.setOpacity(n);
mask.setOpacity(n);
if (n <= 0) {
clearInterval(timeID);
map.removeLayer(layer);
godeMap.removeLayer(mask);
callBack && callBack();
}
}, 100);
},
showLayer(map, godeMap, layer, mask, callBack) {
map.addLayer(layer);
godeMap.addLayer(mask);
map.getView().fit(layer.getSource().getExtent(), {
easing: bounce,
duration: 1000,
});
let n = 0,
timeID;
timeID = setInterval(() => {
n = n + 0.1;
layer.setOpacity(n);
mask.setOpacity(n);
if (n >= 1) {
clearInterval(timeID);
callBack && callBack();
}
}, 100);
},
}
性能及优化思考
- map.addLayer/map.removeLayer 每次都要去删除和创建layer 可以优化的方案?
- pointermove 监听都在循环当前layer的Features和当前feature进行对比,可以否不循环对比,减少循环对比次数
有优化建议希望大家共同探讨