高德地图setFitView效果前后对比视频
高德setfitVIew效果
是不是好多了,做这个东西完全是想吐槽一下高德地图的动画效果太拉了,完全跟不上现代的审美,做得好的想苹果地图、mapbox、cesium,他们的切换动画做的很好,就想着在高德上实现这种动画,让它的过度变得流畅起来,开干!
原本的代码:
// 合适的位置
map.setFitView([marker的数组], false, [UI上下左右的偏移])
首先是知道到中心点,我们只需要传进点位数组,会自动计算出中心点,这里用到turf插件,这是个特别特别好用的数学地理插件,强烈推荐:Turf.js中文网 (fenxianglu.cn) ,高德自带也有,不过turf更专业
npm install @turf/turf
//获取中心点代码,points:[ [lng,lat],[lng,lat],... ]
export function getFitCenter(points) {
let features = turf.featureCollection(points.map((point) => turf.point(point)));
let center = turf.center(features);
return [center.geometry.coordinates[0], center.geometry.coordinates[1]];
}
其次是知道合适的zoom级别,这是难点,高德似乎没有返回合适的zoom级别api,那就的自己写了,,后续会加上考虑UI的偏移,比如说右边有一个悬浮的操作界面,那么展示的时候就往左偏移一点,就像手机版高德那样
//map是好的地图实例化后的map,points是位置数据,同上
export function getFitZoom(map, points) {
const mapWidth = map.getSize().width;
const mapHeight = map.getSize().height;
const WORLD_DIM = { height: 256, width: 256 };
const ZOOM_MAX = 18;
let features = turf.featureCollection(points.map((point) => turf.point(point)));
const bounds = turf.bbox(features); // [minX, minY, maxX, maxY]
function zoom(mapPx, worldPx, fraction) {
return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
}
const latFraction = (bounds[3] - bounds[1]) / WORLD_DIM.height;
const lngFraction = (bounds[2] - bounds[0]) / WORLD_DIM.width;
const latZoom = zoom(mapHeight, WORLD_DIM.height, latFraction);
const lngZoom = zoom(mapWidth, WORLD_DIM.width, lngFraction);
return Math.min(latZoom, lngZoom, ZOOM_MAX);
}
我们现在知道的中心点和缩放级别,接下来的事就交给镜头动画了,舒服的贝塞尔曲线会让画面更高级,更自然,这里推荐一个在线编辑贝塞尔曲线:CSS3贝塞尔曲线工具 - bejson在线工具 也可以用到css的动画中,废话不多说,首先我们加载loca
AMapLoader.load({
key: AMAP_KEY,
version: AMAP_VERSION,
Loca: {
version: "2.0.0",
},
plugins: AMAP_PLUGINS.concat(["Loca"]), //这里我是继续添加进去,你可以这样写[你用到的插件、你用到的插件、"Loca"]
}).then((AMap) => {
instance = AMap;
map = new instance.Map(mapRef.value, {
...AMAP_DEFAULT_THEME,
zoom: 10,
showLabel: false,
pitch: 0,
center: [117.260355, 31.875092],
viewMode: "2D",
skyColor: "#0D121F",
});
// 创建 Loca 容器
loca = new Loca.Container({ //这里加载loca,放到全局,方便使用
map: map,
});
高德镜头动画函数:
export function setFitView(center, zoom,map, loca) {
const curZoom = map.getZoom();
const curPitch = map.getPitch();
const curRotation = map.getRotation();
const curCenter = [map.getCenter().lng, map.getCenter().lat];
const targZoom = zoom;
const targPitch = 0;
const targRotation = 0;
const targCenter = center;
const route = [
{
pitch: {
value: targPitch,
duration: 1000,
control: [
[0, curPitch],
[1, targPitch],
],
timing: [0.23, 1.0, 0.32, 1.0],
},
zoom: {
value: targZoom,
duration: 3000,
control: [
[0, curZoom],
[1, targZoom],
],
timing: [0.13, 0.31, 0.105, 1],
},
rotation: {
value: targRotation,
duration: 1000,
control: [
[0, curRotation],
[1, targRotation],
],
timing: [0.13, 0.31, 0.105, 1],
},
center: {
value: targCenter,
duration: 1500,
control: [curCenter, targCenter],
timing: [0.13, 0.31, 0.105, 1],
},
},
];
loca.viewControl.addAnimates(route, () => {});
loca.animate.start();
}
使用
// 之前的代码
// map.setFitView(currentRoute.points, false)
const points = currentRoute.points.map((item) => [item.getPosition().lng,
item.getPosition().lat]);
const fitzoom = getFitZoom(map, points);
const fitcenter = getFitCenter(points);
setFitView(fitcenter, fitzoom , map, loca);
欧克!对你有帮助记得关注一下哦