Mapbox相机动画整理(1)示例解析

Examples 解析

此处记录较复杂的示例,简单的会在后面整理的相关API中提及。

Animate a point along a route

在这里插入图片描述
1 线段插点

// Calculate the distance in kilometers between route start/end point.
var lineDistance = turf.length(route.features[0]);
 
var arc = [];
 
// Number of steps to use in the arc and animation, more steps means
// a smoother arc and animation, but too many steps will result in a
// low frame rate
var steps = 500;
 
// Draw an arc between the `origin` & `destination` of the two points
for (var i = 0; i < lineDistance; i += lineDistance / steps) {
	var segment = turf.along(route.features[0], i);
	arc.push(segment.geometry.coordinates);
}
 
// Update the route with calculated arc coordinates
route.features[0].geometry.coordinates = arc;

turf.length 计算线段长度
turf.along 计算一定距离在线段上的位置

2 icon角度的计算

var start = route.features[0].geometry.coordinates[
counter >= steps ? counter - 1 : counter
];
var end = route.features[0].geometry.coordinates[
counter >= steps ? counter : counter + 1
];
if (!start || !end) return;
point.features[0].properties.bearing = turf.bearing(
	turf.point(start),
	turf.point(end)
);

turf.bearing 计算两点之间的方向角

3 动画刷新

var counter = 0;
function animate() { 
	point.features[0].geometry.coordinates =
	route.features[0].geometry.coordinates[counter];
 
	// Update the source with this new data
	map.getSource('point').setData(point);
	 
	// Request the next frame of animation as long as the end has not been reached
	if (counter < steps) {
		requestAnimationFrame(animate);
	}
 
	counter = counter + 1;
}
// Start the animation
animate(counter);

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

Animate map camera around a point (3D)

在这里插入图片描述
旋转相机方法

function rotateCamera(timestamp) {
	// clamp the rotation between 0 -360 degrees
	// Divide timestamp by 100 to slow rotation to ~10 degrees / sec
	map.rotateTo((timestamp / 100) % 360, { duration: 0 });
	// Request the next frame of the animation.
	requestAnimationFrame(rotateCamera);
}
// Start the animation.
rotateCamera(0);

map.rotateTo(bearing, options?, eventData?)
用动画过渡将地图旋转到指定的方位角。方向角为0时,指向正北方向,90度的方位朝东。 支持AnimationOptions属性(后续再整理)。

Animate the camera along a path(3D)

在这里插入图片描述
实现思路:
(1)分别准备行走的路线数据和Camera观察的路线数据
(2)设置总的动画持续时间,根据当前时间与开始时间的间隔算出当前所处的阶段
(3)根据当前的阶段获取行走线段的当前点坐标和Camera观察的当前点坐标,从而通过FreeCamera API设置当前Camera的位置,并看向当前的行走坐标

function frame(time) {
	if (!start) start = time;
	// phase determines how far through the animation we are
	var phase = (time - start) / animationDuration;
	 
	// phase is normalized between 0 and 1
	// when the animation is finished, reset start to loop the animation
	if (phase > 1) {
	// wait 1.5 seconds before looping
		setTimeout(function () {
			start = 0.0;
		}, 1500);
	}
 
	// use the phase to get a point that is the appropriate distance along the route
	// this approach syncs the camera and route positions ensuring they move
	// at roughly equal rates even if they don't contain the same number of points
	var alongRoute = turf.along(
		turf.lineString(targetRoute),
		routeDistance * phase
	).geometry.coordinates;
	 
	var alongCamera = turf.along(
		turf.lineString(cameraRoute),
		cameraRouteDistance * phase
	).geometry.coordinates;
	 
	var camera = map.getFreeCameraOptions();
	 
	// set the position and altitude of the camera
	camera.position = mapboxgl.MercatorCoordinate.fromLngLat(
		{
			lng: alongCamera[0],
			lat: alongCamera[1]
		},
		cameraAltitude
	);
	 
	// tell the camera to look at a point along the route
	camera.lookAtPoint({
		lng: alongRoute[0],
		lat: alongRoute[1]
	});
	 
	map.setFreeCameraOptions(camera);
	 
	window.requestAnimationFrame(frame);
}
 
window.requestAnimationFrame(frame);

Customize camera animations

在这里插入图片描述
1 自定义相机动画

// each function takes a parameter t that represents
// the progress of the animation.
// t is in a range of 0 to 1 where 0 is the initial
// state and 1 is the completed state.
var easingFunctions = {
	// start slow and gradually increase speed
	easeInCubic: function (t) {
		return t * t * t;
	},
	// start fast with a long, slow wind-down
	easeOutQuint: function (t) {
		return 1 - Math.pow(1 - t, 5);
	},
	// slow start and finish with fast middle
	easeInOutCirc: function (t) {
		return t < 0.5
		? (1 - Math.sqrt(1 - Math.pow(2 * t, 2))) / 2
		: (Math.sqrt(1 - Math.pow(-2 * t + 2, 2)) + 1) / 2;
	},
	// fast start with a "bounce" at the end
	easeOutBounce: function (t) {
		var n1 = 7.5625;
		var d1 = 2.75;
		 
		if (t < 1 / d1) {
			return n1 * t * t;
		} else if (t < 2 / d1) {
			return n1 * (t -= 1.5 / d1) * t + 0.75;
		} else if (t < 2.5 / d1) {
			return n1 * (t -= 2.25 / d1) * t + 0.9375;
		} else {
			return n1 * (t -= 2.625 / d1) * t + 0.984375;
		}
	}
};

2 animationOptionsmap.flyTo()方法

var animationOptions = {
	duration: duration,
	easing: easingFn,
	offset: [offsetX, offsetY],
	animate: animate,
	essential: true // animation will happen even if user has `prefers-reduced-motion` setting on
};
animationOptions.center = center;
map.flyTo(animationOptions);

Fly to a location based on scroll position

在这里插入图片描述
1 自定义各城市的相机参数

var chapters = {
	'baker': {
		bearing: 27,
		center: [-0.15591514, 51.51830379],
		zoom: 15.5,
		pitch: 20
	},
	'aldgate': {
		duration: 6000,
		center: [-0.07571203, 51.51424049],
		bearing: 150,
		zoom: 15,
		pitch: 0
	},
	'london-bridge': {
		bearing: 90,
		center: [-0.08533793, 51.50438536],
		zoom: 13,
		speed: 0.6,
		pitch: 40
	},
	'woolwich': {
		bearing: 90,
		center: [0.05991101, 51.48752939],
		zoom: 12.3
	},
	'gloucester': {
		bearing: 45,
		center: [-0.18335806, 51.49439521],
		zoom: 15.3,
		pitch: 20,
		speed: 0.5
	},
	'caulfield-gardens': {
		bearing: 180,
		center: [-0.19684993, 51.5033856],
		zoom: 12.3
	},
	'telegraph': {
		bearing: 90,
		center: [-0.10669358, 51.51433123],
		zoom: 17.3,
		pitch: 40
	},
	'charing-cross': {
		bearing: 90,
		center: [-0.12416858, 51.50779757],
		zoom: 14.3,
		pitch: 20
	}
};

2 cameraOptionsmap.flyTo()方法

map.flyTo(chapters[chapterName]);

Navigate the map with game-like controls

在这里插入图片描述
地图使用panBy方法前后移动,easeTo方法左右移动。

// pixels the map pans when the up or down arrow is clicked
var deltaDistance = 100;
 
// degrees the map rotates when the left or right arrow is clicked
var deltaDegrees = 25;
 
function easing(t) {
	return t * (2 - t);
}

map.getCanvas().addEventListener('keydown',	function (e) {
		e.preventDefault();
		if (e.which === 38) {
			// up
			map.panBy([0, -deltaDistance], {
				easing: easing
			});
		} else if (e.which === 40) {
			// down
			map.panBy([0, deltaDistance], {
				easing: easing
			});
		} else if (e.which === 37) {
			// left
			map.easeTo({
				bearing: map.getBearing() - deltaDegrees,
				easing: easing
			});
		} else if (e.which === 39) {
			// right
			map.easeTo({
				bearing: map.getBearing() + deltaDegrees,
				easing: easing
			});	
		}
	},
	true
);

Offset the vanishing point using padding

在这里插入图片描述
利用map.easeTo()方法的padding属性控制地图的左右偏移。

var padding = {};
padding['left'] = 300;
map.easeTo({
	padding: padding,
	duration: 1000 // In ms, CSS transition duration property for the sidebar matches this value
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值