面试题答案
一键面试优化策略
- 减少计算量:
- 缓存计算结果:在处理手势事件时,一些计算结果可能在短时间内不会改变,例如元素的初始位置和大小。可以将这些结果缓存起来,避免重复计算。例如,在开始双指缩放或旋转前,记录元素的初始尺寸和位置:
let initialWidth, initialHeight, initialLeft, initialTop; function startGesture(event) { const target = event.target; initialWidth = target.offsetWidth; initialHeight = target.offsetHeight; initialLeft = target.offsetLeft; initialTop = target.offsetTop; }
- 简化计算逻辑:对于复杂的手势计算,尽量简化公式。例如在旋转计算中,使用三角函数时,可以预先计算一些常用的值,而不是每次都重新计算。
- 合理利用
requestAnimationFrame
:- 合并渲染:将手势操作引起的元素变换集中在
requestAnimationFrame
回调函数中执行。这样可以避免频繁的重排和重绘。例如,在双指缩放和旋转手势事件处理函数中,记录变换值,但不立即应用到元素上:
let scale = 1; let rotation = 0; function handleGesture(event) { // 根据手势事件计算scale和rotation // 例如双指缩放计算scale const newScale = calculateScale(event); scale *= newScale; // 例如双指旋转计算rotation const newRotation = calculateRotation(event); rotation += newRotation; } function updateElement() { const target = document.getElementById('target - element'); target.style.transform = `scale(${scale}) rotate(${rotation}deg)`; } function loop() { updateElement(); requestAnimationFrame(loop); } requestAnimationFrame(loop);
- 合并渲染:将手势操作引起的元素变换集中在
- 事件节流与防抖:
- 节流:对于频繁触发的手势事件(如双指移动过程中的缩放和旋转计算),可以使用节流函数,限制事件处理函数的调用频率。例如,使用
lodash
的throttle
函数:
import throttle from 'lodash/throttle'; function handleGesture(event) { // 手势处理逻辑 } const throttledHandleGesture = throttle(handleGesture, 100); document.addEventListener('touchmove', throttledHandleGesture);
- 防抖:在手势结束时(如手指离开屏幕),可能需要进行一些最终的计算或操作。这时可以使用防抖函数,避免在短时间内多次触发相同的操作。例如:
import debounce from 'lodash/debounce'; function endGesture() { // 最终的计算或操作 } const debouncedEndGesture = debounce(endGesture, 200); document.addEventListener('touchend', debouncedEndGesture);
- 节流:对于频繁触发的手势事件(如双指移动过程中的缩放和旋转计算),可以使用节流函数,限制事件处理函数的调用频率。例如,使用
关键代码片段示例(Vue实现)
<template>
<div id="app" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
<div id="target - element" :style="transformStyle"></div>
</div>
</template>
<script>
export default {
data() {
return {
initialDistance: 0,
initialAngle: 0,
scale: 1,
rotation: 0,
transformStyle: ''
};
},
methods: {
handleTouchStart(event) {
if (event.touches.length === 2) {
const touch1 = event.touches[0];
const touch2 = event.touches[1];
this.initialDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY));
this.initialAngle = Math.atan2(touch2.clientY - touch1.clientY, touch2.clientX - touch1.clientX);
}
},
handleTouchMove(event) {
if (event.touches.length === 2) {
const touch1 = event.touches[0];
const touch2 = event.touches[1];
const newDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY));
const newAngle = Math.atan2(touch2.clientY - touch1.clientY, touch2.clientX - touch1.clientX);
const newScale = newDistance / this.initialDistance;
const newRotation = (newAngle - this.initialAngle) * (180 / Math.PI);
this.scale *= newScale;
this.rotation += newRotation;
this.transformStyle = `scale(${this.scale}) rotate(${this.rotation}deg)`;
}
},
handleTouchEnd() {
// 可以在这里进行防抖处理的操作
}
}
};
</script>
<style>
#target - element {
width: 200px;
height: 200px;
background - color: lightblue;
}
</style>
上述代码通过Vue实现了基本的双指缩放和旋转功能,在实际应用中,可以结合前面提到的优化策略进一步提升性能。