Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions packages/ngx-flicking/projects/ngx-flicking/src/lib/NgxRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,16 @@ class NgxRenderer extends ExternalRenderer {
const cameraEl = flicking.camera.element;

// We're using reversed panels here as last panel should be the last element of camera element
const reversedElements = this._strategy
.getRenderingElementsByOrder(flicking)
.reverse();
let reversedElements: HTMLElement[] = [];

if (flicking.useCSSOrder) {
// useCSSOrder를 사용하는 경우 DOM은 변화가 없지만 대신 css `order`값을 주입
reversedElements = this.getRenderedPanels().map(panel => panel.element).reverse();
} else {
reversedElements = this._strategy
.getRenderingElementsByOrder(flicking)
.reverse();
}

reversedElements.forEach((el, idx) => {
const nextEl = reversedElements[idx - 1] ? reversedElements[idx - 1] : null;
Expand Down
68 changes: 63 additions & 5 deletions src/Flicking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ export interface FlickingOptions {
| MoveTypeOptions<ValueOf<typeof MOVE_TYPE>>;
threshold: number;
dragThreshold: number;
animationThreshold: number;
useCSSOrder: boolean;
interruptable: boolean;
bounce: number | string | [number | string, number | string];
iOSEdgeSwipeThreshold: number;
Expand Down Expand Up @@ -200,6 +202,9 @@ class Flicking extends Component<FlickingEvents> {
private _moveType: FlickingOptions["moveType"];
private _threshold: FlickingOptions["threshold"];
private _dragThreshold: FlickingOptions["dragThreshold"];
private _animationThreshold: FlickingOptions["animationThreshold"];
private _useCSSOrder: FlickingOptions["useCSSOrder"];

private _interruptable: FlickingOptions["interruptable"];
private _bounce: FlickingOptions["bounce"];
private _iOSEdgeSwipeThreshold: FlickingOptions["iOSEdgeSwipeThreshold"];
Expand All @@ -225,6 +230,7 @@ class Flicking extends Component<FlickingEvents> {
private _initialized: boolean;
private _plugins: Plugin[];
private _isResizing: boolean;
private _scheduleResize = false;

// Components
/**
Expand Down Expand Up @@ -703,6 +709,30 @@ class Flicking extends Component<FlickingEvents> {
public get dragThreshold() {
return this._dragThreshold;
}
/**
* The minimum distance for animation to proceed. If the distance to be moved is less than `animationThreshold`, the movement proceeds immediately without animation (duration: 0).
* @ko animation이 진행되기 위한 최소한의 거리. 이동하려는 거리가 `animationThreshold`보다 적으면 애니메이션 없이(duration: 0) 즉시 이동한다.
* @type {number}
* @default 0.5
* @see {@link https://naver.github.io/egjs-flicking/Options#animationThreshold animationThreshold ( Options )}
*/
public get animationThreshold() {
return this._animationThreshold;
}
/**
* Using `useCSSOrder` does not change the DOM order, but the `order` CSS property changes the order on the screen. (When `circular` is used, the DOM order changes depending on the position.)
* When using `iframe`, you can prevent reloading when the DOM order changes.
* In svelte, CSS order is always used.
* @ko `useCSSOrder`를 사용하면 DOM의 순서는 변경되지 않지만 `order` css가 설정되면서 화면상 순서가 바뀐다. (`circular`를 사용한 경우 위치에 따라 DOM의 순서가 변경된다.)
* `iframe`을 사용하는 경우 DOM의 순서가 변경되면서 reload가 되는 것을 막을 수 있다.
* svelte에서는 css order를 무조건 사용한다.
* @type {boolean}
* @default false
* @see {@link https://naver.github.io/egjs-flicking/Options#useCSSOrder useCSSOrder ( Options )}
*/
public get useCSSOrder() {
return this._useCSSOrder;
}

/**
* Set animation to be interruptable by click/touch.
Expand Down Expand Up @@ -1117,6 +1147,12 @@ class Flicking extends Component<FlickingEvents> {
panInput.options.threshold = val;
}
}
public set animationThreshold(val: FlickingOptions["animationThreshold"]) {
this._animationThreshold = val;
}
public set useCSSOrder(val: FlickingOptions["useCSSOrder"]) {
this._useCSSOrder = val;
}

public set interruptable(val: FlickingOptions["interruptable"]) {
this._interruptable = val;
Expand Down Expand Up @@ -1291,7 +1327,9 @@ class Flicking extends Component<FlickingEvents> {
useFractionalSize = false,
externalRenderer = null,
renderExternal = null,
optimizeSizeUpdate = false
optimizeSizeUpdate = false,
animationThreshold = 0.5,
useCSSOrder = false,
}: Partial<FlickingOptions> = {}) {
super();

Expand Down Expand Up @@ -1340,6 +1378,8 @@ class Flicking extends Component<FlickingEvents> {
this._externalRenderer = externalRenderer;
this._renderExternal = renderExternal;
this._optimizeSizeUpdate = optimizeSizeUpdate;
this._animationThreshold = animationThreshold;
this._useCSSOrder = useCSSOrder;

// Create core components
this._viewport = new Viewport(this, getElement(root));
Expand Down Expand Up @@ -1423,7 +1463,9 @@ class Flicking extends Component<FlickingEvents> {

this._plugins.forEach((plugin) => plugin.destroy());

this._scheduleResize = false;
this._initialized = false;
this._isResizing = false;
}

/**
Expand Down Expand Up @@ -1821,11 +1863,20 @@ class Flicking extends Component<FlickingEvents> {
* @method
* @fires Flicking#beforeResize
* @fires Flicking#afterResize
* @return {this}
* @return {boolean}
*/
public async resize(): Promise<void> {
if (this._isResizing) return;
if (!this._initialized) {
return;
}
if (this._isResizing) {
// resize를 연속으로 발생하면 무시하기에 마지막 viewport를 사이즈를 알 수 없음.
// resize를 1번 더 실행할 수 잇는 스케줄링 등록
this._scheduleResize = true;
return;
}

this._scheduleResize = false;
this._isResizing = true;

const viewport = this._viewport;
Expand Down Expand Up @@ -1872,6 +1923,7 @@ class Flicking extends Component<FlickingEvents> {
camera.updatePanelOrder();
camera.updateOffset();
await renderer.render();

if (!this._initialized) {
return;
}
Expand Down Expand Up @@ -1901,6 +1953,12 @@ class Flicking extends Component<FlickingEvents> {
);

this._isResizing = false;

// 연속으로 resize를 호출하는 경우를 대비하기 위해서 스케줄링 반영
if (this._scheduleResize) {
this.resize();
}
return;
}

/**
Expand Down Expand Up @@ -2098,8 +2156,8 @@ class Flicking extends Component<FlickingEvents> {
const nearestAnchor = camera.findNearestAnchor(defaultPanel.position);
const initialPanel =
nearestAnchor &&
defaultPanel.position !== nearestAnchor.panel.position &&
defaultPanel.index !== nearestAnchor.panel.index
defaultPanel.position !== nearestAnchor.panel.position &&
defaultPanel.index !== nearestAnchor.panel.index
? nearestAnchor.panel
: defaultPanel;
control.setActive(initialPanel, null, false);
Expand Down
15 changes: 9 additions & 6 deletions src/cfc/getRenderingPanels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ export default <T>(flicking: Flicking, diffResult: DiffResult<T>) => {
map[prev] = current;
return map;
}, {});
const renderingPanels = flicking.panels
.filter(panel => !removedPanels[panel.index]);


if (!flicking.useCSSOrder) {
// useCSSOrder를 사용하게 되는 경우 sort를 하지 않는다.
renderingPanels.sort((panel1, panel2) => (panel1.position + panel1.offset) - (panel2.position + panel2.offset));
}

return [
...flicking.panels
.filter(panel => !removedPanels[panel.index])
// Sort panels by position
.sort((panel1, panel2) => (panel1.position + panel1.offset) - (panel2.position + panel2.offset))
.map(panel => diffResult.list[maintainedMap[panel.index]]),
...renderingPanels.map(panel => diffResult.list[maintainedMap[panel.index]]),
...diffResult.added.map(idx => diffResult.list[idx])
];
};

10 changes: 9 additions & 1 deletion src/control/AxesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ class AxesController {
return Promise.reject(new FlickingError(ERROR.MESSAGE.NOT_ATTACHED_TO_FLICKING, ERROR.CODE.NOT_ATTACHED_TO_FLICKING));
}

const startPos = axes.get([AXES.POSITION_KEY])[AXES.POSITION_KEY];
const startPos = this.getCurrentPosition();

if (startPos === position) {
const flicking = getFlickingAttached(this._flicking);
Expand Down Expand Up @@ -396,6 +396,14 @@ class AxesController {
});
}

/**
* Returns the current axes position
* @ko 현재 axes의 position을 반환합니다.
*/
public getCurrentPosition() {
return this._axes?.get([AXES.POSITION_KEY])[AXES.POSITION_KEY] ?? 0;
}

public updateDirection() {
const flicking = getFlickingAttached(this._flicking);
const axes = this._axes!;
Expand Down
11 changes: 9 additions & 2 deletions src/control/Control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,19 @@ abstract class Control {
axesEvent?: OnRelease;
}) {
const flicking = getFlickingAttached(this._flicking);
const animate = () => this._controller.animateTo(position, duration, axesEvent);

// 거리(1px 미만)가 매우 짧은 경우 duration이 늘어지는걸 방지하기 위해 0으로 바꿔 즉시 변경
let nextDuration = duration;

if (Math.abs(nextDuration - position) < flicking.animationThreshold) {
nextDuration = 0;
}
const animate = () => this._controller.animateTo(position, nextDuration, axesEvent);
const state = this._controller.state;

state.targetPanel = newActivePanel;

if (duration <= 0) {
if (nextDuration <= 0) {
return animate();
} else {
return animate().then(async () => {
Expand Down
5 changes: 3 additions & 2 deletions src/control/StrictControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,9 @@ class StrictControl extends Control {
const firstAnchor = anchors[0];
const lastAnchor = anchors[anchors.length - 1];

const shouldBounceToFirst = position <= cameraRange.min && isBetween(firstAnchor.panel.index, indexRange.min, indexRange.max);
const shouldBounceToLast = position >= cameraRange.max && isBetween(lastAnchor.panel.index, indexRange.min, indexRange.max);
// position이 bounce으로 인하여 범위를 넘어가야 동작하도록 변경
const shouldBounceToFirst = position < cameraRange.min && isBetween(firstAnchor.panel.index, indexRange.min, indexRange.max);
const shouldBounceToLast = position > cameraRange.max && isBetween(lastAnchor.panel.index, indexRange.min, indexRange.max);

const isAdjacent = adjacentAnchor && (indexRange.min <= indexRange.max
? isBetween(adjacentAnchor.index, indexRange.min, indexRange.max)
Expand Down
20 changes: 20 additions & 0 deletions src/renderer/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ abstract class Renderer {
return Promise.resolve();
}

/**
* Return Rendered Panels
* @ko 렌더링이 된 패널을 반환합니다.
* @return {Panel[]}
*/
public getRenderedPanels() {
const flicking = getFlickingAttached(this._flicking);

return flicking.renderer.panels.filter(panel => panel.rendered);
}

/**
* Update all panel sizes
* @ko 모든 패널의 크기를 업데이트합니다
Expand Down Expand Up @@ -554,6 +565,15 @@ abstract class Renderer {
const flicking = getFlickingAttached(this._flicking);

flicking.camera.applyTransform();

if (flicking.useCSSOrder) {
// useCSSOrder를 사용하는 경우 DOM은 변화가 없지만 대신 css `order`값을 주입
const panels = flicking.panels;

this._strategy.getRenderingIndexesByOrder(flicking).forEach((domIndex, index) => {
panels[domIndex].element.style.order = `${index}`;
});
}
}
}

Expand Down
14 changes: 11 additions & 3 deletions src/renderer/VanillaRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,17 @@ class VanillaRenderer extends Renderer {
const cameraEl = flicking.camera.element;

// We're using reversed panels here as last panel should be the last element of camera element
const reversedElements = this._strategy
.getRenderingElementsByOrder(flicking)
.reverse();

let reversedElements: HTMLElement[] = [];

if (flicking.useCSSOrder) {
// useCSSOrder를 사용하는 경우 DOM은 변화가 없지만 대신 css `order`값을 주입
reversedElements = this.getRenderedPanels().map(panel => panel.element).reverse();
} else {
reversedElements = this._strategy
.getRenderingElementsByOrder(flicking)
.reverse();
}

reversedElements.forEach((el, idx) => {
const nextEl = reversedElements[idx - 1] ? reversedElements[idx - 1] : null;
Expand Down
52 changes: 52 additions & 0 deletions test/cfc/framework/react/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/cfc/framework/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"test": "jest --config=\"./jest.config.js\""
},
"devDependencies": {
"@cfcs/react": "^0.1.0",
"@testing-library/react": "^12.1.2"
}
}
Loading