UNPKG

framer-motion

Version:

An open source and production-ready motion library for React on the web

251 lines (215 loc) • 7.21 kB
import { createCrossfader } from "../crossfader" import { visualElement } from "../../../../render" import { axisBox } from "../../../../utils/geometry" import { ResolvedValues } from "../../../../render/types" type MockInstance = (values: ResolvedValues) => void interface MockState { latest: ResolvedValues } const mockVisualElement = visualElement<MockInstance, MockState, {}>({ treeType: "mock", createRenderState() { return { latest: {}, } }, build(_element, renderState, valuesToRender) { renderState.latest = valuesToRender }, makeTargetAnimatable(_element, target) { return target }, measureViewportBox() { return axisBox() }, readValueFromInstance() { return 0 }, resetTransform() {}, restoreTransform() {}, render(instance, state) { instance(state.latest) }, removeValueFromMutableState() {}, scrapeMotionValuesFromProps(props) { return props.style as ResolvedValues }, }) describe("crossfader", () => { test("Correctly crossfades from follow to lead", async () => { const crossfader = createCrossfader() const lead = mockVisualElement({ props: { initial: { borderRadius: 40, backgroundColor: "#fff", }, }, }) const follow = mockVisualElement({ props: { initial: { borderTopLeftRadius: 20, backgroundColor: "#000", }, }, }) let latestLeadValues: ResolvedValues = {} let latestFollowValues: ResolvedValues = {} ;(lead.ref as any)((latest: ResolvedValues) => { latestLeadValues = latest }) ;(follow.ref as any)( (latest: ResolvedValues) => (latestFollowValues = latest) ) crossfader.setOptions({ lead, follow }) lead.setCrossfader(crossfader) follow.setCrossfader(crossfader) crossfader.toLead({ duration: 1000, ease: () => 0.25, }) return new Promise<void>((resolve) => { setTimeout(() => { expect(latestLeadValues.borderTopLeftRadius).toBe(25) expect(latestFollowValues.borderTopLeftRadius).toBe(25) expect(latestLeadValues.borderBottomRightRadius).toBe(10) expect(latestFollowValues.borderBottomRightRadius).toBe(10) /** * Don't crossfade background color if there's a following element */ expect(latestLeadValues.backgroundColor).toBe("#fff") expect(latestFollowValues.backgroundColor).toBe("#000") /** * Don't crossfade opacity unless requested */ expect(latestLeadValues.opacity).toBeUndefined() expect(latestFollowValues.opacity).toBeUndefined() crossfader.stop() resolve() }, 50) }) }) test("Correctly crossfades from follow to lead with opacity", async () => { const crossfader = createCrossfader() const lead = mockVisualElement({ props: { initial: { opacity: 0.4 }, }, }) const follow = mockVisualElement({ props: { initial: { opacity: 1, }, }, }) let latestLeadValues: ResolvedValues = {} let latestFollowValues: ResolvedValues = {} ;(lead.ref as any)((latest: ResolvedValues) => { latestLeadValues = latest }) ;(follow.ref as any)( (latest: ResolvedValues) => (latestFollowValues = latest) ) crossfader.setOptions({ lead, follow, crossfadeOpacity: true }) lead.setCrossfader(crossfader) follow.setCrossfader(crossfader) crossfader.toLead({ duration: 1000, ease: () => 0.25, }) return new Promise<void>((resolve) => { setTimeout(() => { expect(latestLeadValues.opacity).toBe(0.3464101615137755) expect(latestFollowValues.opacity).toBe(1) crossfader.stop() resolve() }, 50) }) }) test("Correctly preserves follow opacity", async () => { const crossfader = createCrossfader() const lead = mockVisualElement({ props: { initial: { opacity: 0.4 }, }, }) const follow = mockVisualElement({ props: { initial: { opacity: 1, }, }, }) let latestLeadValues: ResolvedValues = {} let latestFollowValues: ResolvedValues = {} ;(lead.ref as any)((latest: ResolvedValues) => { latestLeadValues = latest }) ;(follow.ref as any)( (latest: ResolvedValues) => (latestFollowValues = latest) ) crossfader.setOptions({ lead, follow, crossfadeOpacity: true, preserveFollowOpacity: true, }) lead.setCrossfader(crossfader) follow.setCrossfader(crossfader) crossfader.toLead({ duration: 1000, ease: () => 0.25, }) return new Promise<void>((resolve) => { setTimeout(() => { expect(latestLeadValues.opacity).toBe(0.3464101615137755) expect(latestFollowValues.opacity).toBe(1) crossfader.stop() resolve() }, 50) }) }) test("Correctly crossfades from snapshot to lead", async () => { const crossfader = createCrossfader() const lead = mockVisualElement({ props: { initial: { borderRadius: 40, backgroundColor: "#fff", opacity: 1, }, }, }) let latestLeadValues: ResolvedValues = {} ;(lead.ref as any)((latest: ResolvedValues) => { latestLeadValues = latest }) crossfader.setOptions({ lead, prevValues: { borderTopLeftRadius: 20, backgroundColor: "#000", opacity: 0.4, }, }) lead.setCrossfader(crossfader) crossfader.toLead({ duration: 1000, ease: () => 0.25, }) return new Promise<void>((resolve) => { setTimeout(() => { expect(latestLeadValues.borderTopLeftRadius).toBe(25) expect(latestLeadValues.borderBottomRightRadius).toBe(10) expect(latestLeadValues.backgroundColor).toBe( "rgba(128, 128, 128, 1)" ) expect(latestLeadValues.opacity).toBe(0.55) crossfader.stop() resolve() }, 50) }) }) })