自定义相机动画
使用AnimationOptions自定义相机动画;
<!DOCTYPE html>
<html lang="en">
<head>
<title>自定义相机动画</title>
<meta property="og:description" content="使用AnimationOptions自定义相机动画" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
.overlay {
position: absolute;
top: 20px;
left: 20px;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px 20px;
border-radius: 5px;
z-index: 1;
}
.overlay h3 {
margin-top: 5px;
}
button {
margin: 2px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="overlay">
<h3>过渡</h3>
<div>
<button id="fly">飞行</button>
<button id="jump">跳跃</button>
<button id="linear">线性</button>
<button id="ease">缓动</button>
</div>
<div id="easing-functions">
<h3>缓动函数</h3>
</div>
</div>
<script>
const easingFunctions = {
// 自定义缓动函数示例
// t: 当前时间, b: 开始值, c: 变化值, d: 持续时间
// 返回值:当前时刻的值
linear: function (t) {
return t;
},
easeInQuad: function (t) {
return t * t;
},
easeOutQuad: function (t) {
return t * (2 - t);
},
easeInOutQuad: function (t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
easeInCubic: function (t) {
return t * t * t;
},
easeOutCubic: function (t) {
return (--t) * t * t + 1;
},
easeInOutCubic: function (t) {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
easeInQuart: function (t) {
return t * t * t * t;
},
easeOutQuart: function (t) {
return 1 - (--t) * t * t * t;
},
easeInOutQuart: function (t) {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
},
easeInQuint: function (t) {
return t * t * t * t * t;
},
easeOutQuint: function (t) {
return 1 + (--t) * t * t * t * t;
},
easeInOutQuint: function (t) {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t;
},
easeInSine: function (t) {
return 1 - Math.cos(t * Math.PI / 2);
},
easeOutSine: function (t) {
return Math.sin(t * Math.PI / 2);
},
easeInOutSine: function (t) {
return 0.5 * (1 - Math.cos(Math.PI * t));
},
easeInExpo: function (t) {
return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
},
easeOutExpo: function (t) {
return (t === 1) ? 1 : 1 - Math.pow(2, -10 * t);
},
easeInOutExpo: function (t) {
if (t === 0) return 0;
if (t === 1) return 1;
if ((t /= 0.5) < 1) return 0.5 * Math.pow(2, 10 * (t - 1));
return 0.5 * (2 - Math.pow(2, -10 * --t));
},
easeInCirc: function (t) {
return -(Math.sqrt(1 - t * t) - 1);
},
easeOutCirc: function (t) {
return Math.sqrt(1 - (--t) * t);
},
easeInOutCirc: function (t) {
if ((t /= 0.5) < 1) return -0.5 * (Math.sqrt(1 - t * t) - 1);
return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
},
easeInElastic: function (t) {
let s = 1.70158;
let p = 0;
let a = 1;
if (t === 0) return 0;
if (t === 1) return 1;
if (!p) p = 0.3;
if (a < 1) {
a = 1;
s = p / 4;
} else {
s = p / (2 * Math.PI) * Math.asin(1 / a);
}
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
},
easeOutElastic: function (t) {
let s = 1.70158;
let p = 0;
let a = 1;
if (t === 0) return 0;
if (t === 1) return 1;
if (!p) p = 0.3;
if (a < 1) {
a = 1;
s = p / 4;
} else {
s = p / (2 * Math.PI) * Math.asin(1 / a);
}
return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;
},
easeInOutElastic: function (t) {
let s = 1.70158;
let p = 0;
let a = 1;
if (t === 0) return 0;
if ((t /= 0.5) === 2) return 1;
if (!p) p = 0.3 * 1.5;
if (a < 1) {
a = 1;
s = p / 4;
} else {
s = p / (2 * Math.PI) * Math.asin(1 / a);
}
if (t < 1) {
return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));
}
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;
},
easeInBack: function (t) {
const s = 1.70158;
return t * t * ((s + 1) * t - s);
},
easeOutBack: function (t) {
const s = 1.70158;
return (t = t - 1) * t * ((s + 1) * t + s) + 1;
},
easeInOutBack: function (t) {
let s = 1.70158;
if ((t /= 0.5) < 1) {
return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
}
return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
},
easeInBounce: function (t) {
return 1 - easingFunctions.easeOutBounce(1 - t);
},
easeOutBounce: function (t) {
if (t < (1 / 2.75)) {
return 7.5625 * t * t;
} else if (t < (2 / 2.75)) {
return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75;
} else if (t < (2.5 / 2.75)) {
return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375;
} else {
return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375;
}
},
easeInOutBounce: function (t) {
if (t < 0.5) return easingFunctions.easeInBounce(t * 2) * 0.5;
return easingFunctions.easeOutBounce(t * 2 - 1) * 0.5 + 0.5;
}
};
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [-73.9749, 40.7736],
zoom: 12,
pitch: 20
});
// 随机生成目的地坐标
function generateDestination() {
return {
center: [
-73.9749 + (Math.random() - 0.5) * 0.1,
40.7736 + (Math.random() - 0.5) * 0.1
],
zoom: 14 + Math.random() * 4,
bearing: Math.random() * 360,
pitch: 20 + Math.random() * 50
};
}
// 创建缓动函数按钮
function createEasingFunctionButtons() {
const container = document.getElementById('easing-functions');
for (const name in easingFunctions) {
const button = document.createElement('button');
button.textContent = name;
button.addEventListener('click', () => {
map.flyTo({
...generateDestination(),
duration: 2000,
easing: easingFunctions[name]
});
});
container.appendChild(button);
}
}
document.getElementById('fly').addEventListener('click', () => {
map.flyTo({
...generateDestination(),
duration: 2000
});
});
document.getElementById('jump').addEventListener('click', () => {
map.jumpTo(generateDestination());
});
document.getElementById('linear').addEventListener('click', () => {
map.easeTo({
...generateDestination(),
duration: 2000,
easing: easingFunctions.linear
});
});
document.getElementById('ease').addEventListener('click', () => {
map.easeTo({
...generateDestination(),
duration: 2000
});
});
// 创建缓动函数按钮
createEasingFunctionButtons();
</script>
</body>
</html>