跳到主要内容

React Fiber 手势调度器

一、作用

二、手势调度

备注
export function scheduleGesture(
root: FiberRoot,
provider: GestureTimeline,
): ScheduledGesture {
let prev = root.pendingGestures;
while (prev !== null) {
if (prev.provider === provider) {
// Existing instance found.
// 已找到现有实例。
return prev;
}
const next = prev.next;
if (next === null) {
break;
}
prev = next;
}
const gesture: ScheduledGesture = {
provider: provider,
count: 0,
// 未初始化
rangeStart: 0, // Uninitialized
// 未初始化
rangeEnd: 100, // Uninitialized
types: null,
running: null,
prev: prev,
next: null,
};
if (prev === null) {
root.pendingGestures = gesture;
} else {
prev.next = gesture;
}
ensureRootIsScheduled(root);
return gesture;
}

三、开始计划手势

备注
  • getCurrentGestureOffset() 由平台实现
export function startScheduledGesture(
root: FiberRoot,
gestureTimeline: GestureTimeline,
gestureOptions: ?GestureOptions,
transitionTypes: null | TransitionTypes,
): null | ScheduledGesture {
const rangeStart =
gestureOptions && gestureOptions.rangeStart != null
? gestureOptions.rangeStart
: getCurrentGestureOffset(gestureTimeline);
const rangeEnd =
gestureOptions && gestureOptions.rangeEnd != null
? gestureOptions.rangeEnd
: rangeStart < 50
? 100
: 0;
let prev = root.pendingGestures;
while (prev !== null) {
if (prev.provider === gestureTimeline) {
// Existing instance found.
// 已找到现有实例。
prev.count++;
// Update the options.
// 更新选项。
prev.rangeStart = rangeStart;
prev.rangeEnd = rangeEnd;
if (transitionTypes !== null) {
let scheduledTypes = prev.types;
if (scheduledTypes === null) {
scheduledTypes = prev.types = [];
}
for (let i = 0; i < transitionTypes.length; i++) {
const transitionType = transitionTypes[i];
if (scheduledTypes.indexOf(transitionType) === -1) {
scheduledTypes.push(transitionType);
}
}
}
return prev;
}
const next = prev.next;
if (next === null) {
break;
}
prev = next;
}
// No scheduled gestures. It must mean nothing for this renderer updated but
// some other renderer might have updated.
//
// 没有计划中的手势。这一定不意味着此渲染器已更新,
// 但其他渲染器可能已更新。
return null;
}

三、取消计划手势

备注
export function cancelScheduledGesture(
root: FiberRoot,
gesture: ScheduledGesture,
): void {
gesture.count--;
if (gesture.count === 0) {
// Delete the scheduled gesture from the pending queue.
// 从待处理队列中删除已安排的手势。
deleteScheduledGesture(root, gesture); // 本文档实现
// TODO: If we're currently rendering this gesture, we need to restart the render
// on a different gesture or cancel the render..
// TODO: We might want to pause the View Transition at this point since you should
// no longer be able to update the position of anything but it might be better to
// just commit the gesture state.
//
// 待办事项:如果我们当前正在渲染这个手势,我们需要在不同的手势上重新开始渲染,或者取消渲染。
// 待办事项:我们可能想在这一点暂停视图过渡,因为
// 你应该不能再更新任何位置,但可能更好的是直接提交手势状态。
const runningTransition = gesture.running;
if (runningTransition !== null) {
const pendingLanesExcludingGestureLane = root.pendingLanes & ~GestureLane;
if (
includesBlockingLane(pendingLanesExcludingGestureLane) ||
includesTransitionLane(pendingLanesExcludingGestureLane)
) {
// If we have pending work we schedule the gesture to be stopped at the next commit.
// This ensures that we don't snap back to the previous state until we have
// had a chance to commit any resulting updates.
//
// 如果我们有待处理的工作,我们会安排在下一次提交时停止手势。
// 这确保了在我们有机会提交任何结果更新之前,不会回到之前的状态。
const existing = root.stoppingGestures;
if (existing !== null) {
gesture.next = existing;
existing.prev = gesture;
}
root.stoppingGestures = gesture;
} else {
gesture.running = null;
// If there's no work scheduled so we can stop the View Transition right away.
// 如果没有安排任何工作,我们可以立即停止视图过渡。
stopViewTransition(runningTransition);
}
}
}
}

四、删除计划手势

export function deleteScheduledGesture(
root: FiberRoot,
gesture: ScheduledGesture,
): void {
if (gesture.prev === null) {
if (root.pendingGestures === gesture) {
root.pendingGestures = gesture.next;
if (root.pendingGestures === null) {
// Gestures don't clear their lanes while the gesture is still active but it
// might not be scheduled to do any more renders and so we shouldn't schedule
// any more gesture lane work until a new gesture is scheduled.
//
// 手势在仍然处于活动状态时不会清除它们的通道,
// 但它可能不再被安排进行更多的渲染,因此在新的手势
// 被安排之前,我们不应安排更多的手势通道工作。
root.pendingLanes &= ~GestureLane;
}
}
if (root.stoppingGestures === gesture) {
// This should not really happen the way we use it now but just in case we start.
// 以我们现在的使用方式,这种情况实际上不应该发生,但以防万一我们还是开始吧。
root.stoppingGestures = gesture.next;
}
} else {
gesture.prev.next = gesture.next;
if (gesture.next !== null) {
gesture.next.prev = gesture.prev;
}
gesture.prev = null;
gesture.next = null;
}
}

五、停止已完成的手势

备注
  • stopViewTransition() 由渲染平台实现
export function stopCompletedGestures(root: FiberRoot) {
let gesture = root.stoppingGestures;
root.stoppingGestures = null;
while (gesture !== null) {
if (gesture.running !== null) {
stopViewTransition(gesture.running);
gesture.running = null;
}
const nextGesture = gesture.next;
gesture.next = null;
gesture.prev = null;
gesture = nextGesture;
}
}