naver / egjs-flicking

🎠 ♻️ Everyday 30 million people experience. It's reliable, flexible and extendable carousel.
https://naver.github.io/egjs-flicking/
MIT License
2.69k stars 129 forks source link

fix: add findActiveAnchor fallback for bound flicking #851

Closed malangfox closed 3 months ago

malangfox commented 4 months ago

Issue

850

https://codepen.io/malangfox/pen/WNmPemg Pressing the moveTo button, opening the console, and dragging the flicking should reproduce it.

Details

Position is not reachable error occurs when using the moveTo method for the first panel with bound: true.

image

In the above demo, when 4 Panels are placed, the total number of Anchors is 2.

This is because the Panel labeled 1 and the Panel labeled 2 share the same Anchor point. Similarly, the panel with 3 and the panel with 4 share the same anchor point.

This is because there is no way to send Panels 1 / 4 to the center with the bound option enabled, which removes the left and right empty spaces.

This means that in this situation, only the Anchor points of Panel 2 and Panel 3 exist.

If we use the moveTo method with Panel 1, the Anchor point we stop at is the Anchor of Panel 2, but the index of the active Panel in the flicking will be the first Panel.

In this situation, moveToPosition, which calculates the arrival point at the end of a drag with moveType: "snap", has the following logic.

const activeAnchor = camera.findActiveAnchor();
const anchorAtCamera = camera.findNearestAnchor(camera.position);
if (!activeAnchor || !anchorAtCamera) {
  return Promise.reject(new FlickingError(...));
}

and findActiveAnchor behaves as follows.

public findActiveAnchor(): AnchorPoint | null {
  const flicking = getFlickingAttached(this._flicking);
  const activeIndex = flicking.control.activeIndex;

  return find(this._anchors, anchor => anchor.panel.index === activeIndex);
}

The activeIndex is Panel 1, but none of the anchors corresponds to Panel 1, so it returns null.

Since activeAnchor is null, an error message is raised via Promise.reject.

I handled the exception of the findActiveAnchor by returning the closest Anchor to the active panel's position as a fallback if no corresponding Anchor for the active panel exists.

coveralls commented 4 months ago

Coverage Status

coverage: 82.719% (+0.08%) from 82.638% when pulling e58557a13e0ce6a8f396924c4c613c4fbb7180ae on malangfox:fix/snapcontrol-findActiveAnchor into 3d528047f41adb7bd453430ce64fc3ceefc4a081 on naver:master.