UNPKG

@egjs/axes

Version:

A module used to change the information of user action entered by various input devices such as touch screen or mouse into the logical virtual coordinates. You can easily create a UI that responds to user actions.

941 lines (841 loc) • 26.5 kB
import { AxisManager } from "../../src/AxisManager"; import { InterruptManager } from "../../src/InterruptManager"; import { EventManager } from "../../src/EventManager"; import { EasingManager } from "../../src/animation/EasingManager"; import Axes from "../../src"; describe("AnimationManager", () => { let inst; let axes; let axis; let options; describe("Methods", () => { beforeEach(() => { axis = { x: { range: [0, 100], bounce: [50, 50], circular: false, }, y: { range: [0, 200], bounce: [0, 0], circular: false, }, z: { range: [-100, 200], bounce: [50, 0], circular: true, }, }; options = { deceleration: 0.0001, maximumDuration: 2000, minimumDuration: 0, }; inst = new EasingManager({ options: options, interruptManager: new InterruptManager(options), eventManager: new EventManager(null), axisManager: new AxisManager(axis, options), }); }); afterEach(() => {}); it("should check 'getDuration' method", () => { // Given // When const depaPos = { x: 0, y: 0, }; const destPos = { x: 100, y: 50, }; // When/Then expect(inst.getDuration(depaPos, destPos)).to.be.equal(1414.213562373095); // When (change option) options.maximumDuration = 1200; // Then expect(inst.getDuration(depaPos, destPos)).to.be.equal(1200); // When/Then expect(inst.getDuration(depaPos, destPos, 1000)).to.be.equal(1000); // When/Then expect(inst.getDuration(depaPos, destPos, 2000)).to.be.equal(1200); }); it("should check 'getDisplacement' method", () => { // 0.001 options.deceleration = 0.001; expect(inst.getDisplacement([1.5, 1])).to.be.eql([ 1352.0817282989958, 901.3878188659972, ]); expect(inst.getDisplacement([1, 1.5])).to.be.eql([ 901.3878188659972, 1352.0817282989958, ]); // 0.01 options.deceleration = 0.01; expect(inst.getDisplacement([1.5, 1])).to.be.eql([ 135.20817282989958, 90.13878188659973, ]); expect(inst.getDisplacement([1, 1.5])).to.be.eql([ 90.13878188659973, 135.20817282989958, ]); }); it("should check 'createAnimationParam' method", () => { // Given // When const pos = { x: 200, y: 210, z: -155, }; // When // createAnimationParam does not change the 'pos' param since 2017.10.27 let param = inst._createAnimationParam(pos, 1000); // Then expect(param.depaPos).to.be.eql({ x: 0, y: 0, z: -100 }); expect(param.destPos).to.be.eql({ x: 200, y: 210, z: -155 }); // do not change destPos. expect(param.duration).to.be.eql(1000); expect(param.delta).to.be.eql({ x: 200, y: 210, z: -55 }); expect(param.inputEvent).to.be.eql(null); expect(param.input).to.be.eql(null); // When options.maximumDuration = 500; const eventValue = { event: "i'm inputEvent" }; param = inst._createAnimationParam(pos, 1000, { event: eventValue, }); // Then expect(param.depaPos).to.be.eql({ x: 0, y: 0, z: -100 }); expect(param.destPos).to.be.eql({ x: 200, y: 210, z: -155 }); expect(param.duration).to.be.eql(500); expect(param.delta).to.be.eql({ x: 200, y: 210, z: -55 }); expect(param.inputEvent).to.be.equal(eventValue); }); }); describe("Options", () => { beforeEach(() => { axis = { x: { range: [0, 1000], bounce: [0, 0], }, }; options = { easing: (x) => { return x }, minimumDuration: 500, maximumDuration: 1000, }; axes = new Axes(axis, options); const axisManager = new AxisManager(axis, options); const eventManager = new EventManager(axes); inst = new EasingManager({ options: options, interruptManager: new InterruptManager(options), eventManager, axisManager, }); eventManager.setAnimationManager(inst); }); afterEach(() => { axes.off(); }); describe("minimumDuration", () => { it("should play animation longer than the time set in minimumDuration.", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 300 }, 100); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; }, 300); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(300); done(); }, 600); }); it("should apply changes in minimumDuration option after connected", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setOptions({ minimumDuration: 0 }); inst.setTo({ x: 300 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; }, 100); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(300); done(); }, 300); }); }); describe("maximumDuration", () => { it("should play animation shorter than the time set in maximumDuration.", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 300 }, 1500); // Then setTimeout(() => { expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(300); done(); }, 1100); }); it("should apply changes in maximumDuration option after connected", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setOptions({ maximumDuration: 1500 }); inst.setTo({ x: 300 }, 1300); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; }, 1300); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(300); done(); }, 1600); }); }); }); describe("animation test", () => { beforeEach(() => { axis = { x: { range: [0, 100], bounce: [50, 50], circular: false /* [false, false] */, }, y: { range: [0, 200], bounce: [0, 0], circular: false /* [false, false] */, }, z: { range: [-100, 200], bounce: [50, 0], circular: true /* [true, true] */, }, }; options = { easing: (x) => { return 1 - Math.pow(1 - x, 3); }, interruptable: true, deceleration: 0.0001, minimumDuration: 0, maximumDuration: 2000, }; axes = new Axes(axis, options); const axisManager = new AxisManager(axis, options); const eventManager = new EventManager(axes); inst = new EasingManager({ options: options, interruptManager: new InterruptManager(options), eventManager, axisManager, }); eventManager.setAnimationManager(inst); }); afterEach(() => { axes.off(); }); it("should check 'setTo' method (duration: 0)", () => { // Given const changeHandler = sinon.spy(); const finishHandler = sinon.spy(); axes.on({ change: changeHandler, finish: finishHandler, }); // When inst.setTo( { x: 100, y: 200, }, 0 ); // Then expect(changeHandler.calledOnce).to.be.true; expect(finishHandler.calledOnce).to.be.true; expect(inst.axisManager.get()).to.be.eql({ x: 100, y: 200, z: -100, }); }); it("should check 'setTo' method (outside)", () => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 200, z: -155, }; const self = inst; const startHandler = sinon.spy(); const changeHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, change: changeHandler, animationEnd: endHandler, }); // When inst.setTo(destPos, 0); // Then expect(startHandler.called).to.be.false; expect(endHandler.called).to.be.false; expect(changeHandler.called).to.be.true; expect(changeHandler.getCall(0).args[0].isTrusted).to.be.false; expect(self.axisManager.get()).to.be.eql({ x: 100, y: 0, z: 145 }); }); it("should check 'setTo' method (outside, duration)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 200, z: -155, }; const self = inst; const startHandler = sinon.spy(); const changeHandler = sinon.spy((event) => { expect(event.input).to.be.null; expect(event.inputEvent).to.be.null; expect(self.getEventInfo()).to.be.null; }); axes.on({ animationStart: startHandler, change: changeHandler, animationEnd: (event) => { expect(self.axisManager.get()).to.be.eql({ x: 100, y: 0, z: 145 }); expect(startHandler.callCount).to.be.equal(1); expect(startHandler.getCall(0).args[0].isTrusted).to.be.false; expect(changeHandler.called).to.be.true; expect(event.isTrusted).to.be.false; done(); }, }); // When inst.setTo(destPos, 1000); }); it("should check 'setTo' method (same position #1)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 0, z: -100, }; const self = inst; const changeHandler = sinon.spy(); axes.on({ change: changeHandler, }); // When const ret = inst.setTo(destPos); // Then setTimeout(() => { expect(changeHandler.called).to.be.false; expect(ret).to.be.eq(self); done(); }, 100); }); it("should check 'setTo' method (same position #2 - completely same)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 0, z: -100, }; const self = inst; const changeHandler = sinon.spy(); axes.on({ change: changeHandler, }); // When const ret = inst.setTo(destPos); // Then setTimeout(() => { expect(changeHandler.called).to.be.false; expect(ret).to.be.eq(self); done(); }, 100); }); it("should check 'setTo' method (circular, no duration)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { z: -200 }; const self = inst; const changeHandler = sinon.spy((event) => { // Then expect(self.axisManager.get()).to.be.eql({ x: 0, y: 0, z: 100 }); done(); }); axes.on({ change: changeHandler, }); // When const ret = inst.setTo(destPos, 0, true); }); it("should check 'setTo' method (same position after range limit, useCircular)", (done) => { // Given // depaPos: {x: 0, y: 0, z: -100} const destPos = { x: -100, z: 500 }; const self = inst; const changeHandler = sinon.spy(); axes.on({ change: changeHandler, }); // When const ret = inst.setTo(destPos, 0); // last (useCircular) param makes invalidating z-pos change(500) // Then setTimeout(() => { expect(self.axisManager.get()).to.be.eql({ x: 0, y: 0, z: -100 }); expect(changeHandler.callCount).to.be.equals(1); expect(changeHandler.args[0][0].delta).to.be.eql({ x: 0, y: 0, z: 600, }); expect(ret).to.be.eq(self); done(); }, 100); }); it("should check 'setTo' method (diff position after range limit)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: -100, z: 450 }; const self = inst; const changeHandler = sinon.spy((event) => { // Then expect(self.axisManager.get()).to.be.eql({ x: 0, y: 0, z: 150 }); done(); }); axes.on({ change: changeHandler, }); // When const ret = inst.setTo(destPos); }); it("should check 'setBy' method (inside, duration)", (done) => { // Given const depaPos = inst.axisManager.get(); const byPos = { x: 20, z: 40, }; const self = inst; const startHandler = sinon.spy(); const changeHandler = sinon.spy((event) => { expect(event.input).to.be.null; expect(event.inputEvent).to.be.null; expect(self.getEventInfo()).to.be.null; }); axes.on({ animationStart: startHandler, change: changeHandler, animationEnd: (event) => { expect(self.axisManager.get()).to.be.eql({ x: depaPos.x + byPos.x, y: 0, z: depaPos.z + byPos.z, }); expect(startHandler.callCount).to.be.equal(1); expect(startHandler.getCall(0).args[0].isTrusted).to.be.false; expect(changeHandler.called).to.be.true; expect(event.isTrusted).to.be.false; done(); }, }); // When inst.setBy(byPos, 1000); }); it("should check 'setBy' method (outside, duration)", (done) => { // Given const depaPos = inst.axisManager.get(); const minZ = axis.z.range[0]; const rangeLength = axis.z.range[1] - axis.z.range[0]; const byPos = { x: 200, z: 500, }; const self = inst; const startHandler = sinon.spy(); const changeHandler = sinon.spy((event) => { expect(event.input).to.be.null; expect(event.inputEvent).to.be.null; expect(self.getEventInfo()).to.be.null; }); axes.on({ animationStart: startHandler, change: changeHandler, animationEnd: (event) => { expect(self.axisManager.get()).to.be.eql({ x: 100, y: 0, z: 100 }); expect(startHandler.callCount).to.be.equal(1); expect(startHandler.getCall(0).args[0].isTrusted).to.be.false; expect(changeHandler.called).to.be.true; expect(event.isTrusted).to.be.false; done(); }, }); // When inst.setBy(byPos, 1000); }); it("should check 'animateTo' method (inside)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 90, z: -80, }; const self = inst; const startHandler = sinon.spy(); const changeHandler = sinon.spy((event) => { expect(event.input).to.be.null; expect(event.inputEvent).to.be.null; expect(self.getEventInfo()).to.be.null; }); axes.on({ animationStart: startHandler, change: changeHandler, animationEnd: (event) => { expect(self.axisManager.get()).to.be.eql({ x: 90, y: 0, z: -80 }); expect(startHandler.callCount).to.be.equal(1); expect(startHandler.getCall(0).args[0].isTrusted).to.be.false; expect(changeHandler.called).to.be.true; expect(event.isTrusted).to.be.false; done(); }, }); // When inst.setTo(destPos, 500); }); it("should check 'animateTo' method (outside)", (done) => { // Given const depaPos = inst.axisManager.get(); const destPos = { x: 200, z: -155, }; const self = inst; const startHandler = sinon.spy(); const endHandler = sinon.spy((event) => { if (endHandler.callCount === 1) { // first destPos expect(self.axisManager.get()).to.be.eql({ x: 200, y: 0, z: 145 }); expect(startHandler.callCount).to.be.equal(1); expect(startHandler.getCall(0).args[0].isTrusted).to.be.false; expect(event.isTrusted).to.be.false; } else if (endHandler.callCount === 2) { // Then expect(self.axisManager.get()).to.be.eql({ x: 100, y: 0, z: 145 }); expect(startHandler.getCall(1).args[0].isTrusted).to.be.false; expect(startHandler.callCount).to.be.equal(2); expect(event.isTrusted).to.be.false; done(); } }); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.animateTo(destPos, 1000); }); it("should check 'animateTo' with destPos that can cause floating point", (done) => { // circular: true, // duration: 102 // depaPos: 729.5859375 // destPos: 1055.984375 // range: [-96, 1055.984375] // Given inst.axisManager._axis.z.range = [-96, 1055.984375]; inst.setTo({ z: 729.5858375 }, 0); // When inst.animateTo({ z: 1055.984375 }, 102); setTimeout(() => { // Then expect(inst.axisManager.get().z).to.be.equals(1055.984375); done(); }, 200); }); it("should check position when animation is running. then, start other animation", (done) => { // Given const startHandler = sinon.spy(); const changeHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ change: changeHandler, animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 80, y: 150 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(changeHandler.called).to.be.true; expect(endHandler.called).to.be.false; // When inst.setTo({ x: 0, y: 0 }, 300); expect(inst.axisManager.get()).to.not.eql({ x: 80, y: 150, z: -100, }); }, 100); setTimeout(() => { expect(startHandler.calledTwice).to.be.true; expect(changeHandler.called).to.be.true; expect(endHandler.calledTwice).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(0); expect(result.y).to.be.equal(0); expect(result.z).to.be.equal(-100); done(); }, 500); }); [1, -1].forEach((direction) => { it(`should check destPos when range changes dynamically during animateLoop(direction: ${direction}, circular: true)`, (done) => { // Given const depaPos = { z: -100 }; const destPos = direction > 0 ? { z: 600 } : { z: -600 }; const resultPos = direction > 0 ? { z: 300 } : { z: 0 }; // When setTimeout(() => { // the right time for a range to be crossed // 'pos' is off the range. // z.range[1] 200 => 600 axis.z.range[1] = 600; }, 300); inst._animateLoop( { duration: 1000, depaPos, destPos, delta: { z: destPos.z - depaPos.z }, }, () => { // Then expect(inst.axisManager.get(["z"]).z).to.be.equals(resultPos.z); done(); } ); }); it(`should check destPos when range changes dynamically during animateLoop and change(direction: ${direction}, circular: true)`, (done) => { // Given const depaPos = { z: -100 }; const destPos = direction > 0 ? { z: 600 } : { z: -600 }; const resultPos = direction > 0 ? { z: 300 } : { z: 0 }; // When let willChange = false; setTimeout(() => { // Starts with the exception of -100, which is the start position. axes.on("change", (e) => { if ( // range[0] = -100 (direction === -1 && e.pos.z < -80) || // range[1] = 200 (direction === 1 && e.pos.z > 180) ) { willChange = true; } else if (willChange) { axis.z.range[1] = 600; } }); }, 100); inst._animateLoop( { duration: 1000, depaPos, destPos, delta: { z: destPos.z - depaPos.z }, }, () => { // Then expect(inst.axisManager.get(["z"]).z).to.be.equals(resultPos.z); done(); } ); }); }); it("should check 'updateAnimation' method (update destPos)", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 60, y: 70 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; // When inst.updateAnimation({ destPos: { x: 100, y: 100 } }); }, 100); setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(100); expect(result.y).to.be.equal(100); done(); }, 500); }); it("should check 'updateAnimation' method (update duration)", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 60, y: 70 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; // When inst.updateAnimation({ duration: 600 }); }, 100); setTimeout(() => { expect(endHandler.called).to.be.false; }, 400); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(60); expect(result.y).to.be.equal(70); done(); }, 700); }); it("should check 'updateAnimation' method (multiple time, update both)", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 100, y: 100 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; // When inst.updateAnimation({ destPos: { x: 30, y: 30 }, duration: 400 }); }, 100); setTimeout(() => { expect(endHandler.called).to.be.false; // When inst.updateAnimation({ destPos: { x: 12.3456, y: 1.2345 }, duration: 300, }); }, 200); setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.calledOnce).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(12.3456); expect(result.y).to.be.equal(1.2345); done(); }, 500); }); it("should check 'updateAnimation' method (restart: true)", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 10, y: 10 }, 200); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; // When inst.updateAnimation({ duration: 600, restart: true }); }, 100); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; expect(startHandler.calledTwice).to.be.true; }, 400); setTimeout(() => { expect(startHandler.calledOnce).to.be.false; expect(endHandler.calledOnce).to.be.false; expect(endHandler.calledTwice).to.be.true; const result = inst.axisManager.get(); expect(result.x).to.be.equal(10); expect(result.y).to.be.equal(10); done(); }, 700); }); it("should check 'stopAnimation' method", (done) => { // Given const startHandler = sinon.spy(); const endHandler = sinon.spy(); axes.on({ animationStart: startHandler, animationEnd: endHandler, }); // When inst.setTo({ x: 100, y: 100 }, 400); // Then setTimeout(() => { expect(startHandler.calledOnce).to.be.true; expect(endHandler.called).to.be.false; // When inst.stopAnimation(["x", "y"]); }, 100); setTimeout(() => { expect(endHandler.calledOnce).to.be.true; }, 200); setTimeout(() => { const result = inst.axisManager.get(); expect(result.x).to.not.equal(100); expect(result.y).to.not.equal(100); done(); }, 500); }); }); });