Framer X » Animation » Example animations » 15. Page: Indicators

15. Page: Indicators

Code Component

React’s useState() hook is used to keep track of the current page.

const pages = [1, 2, 3, 4, 5]
const indicatorSize = 10
const indicatorPadding = 10
const indicatorWidth = pages.length * indicatorSize
const indicatorPaddingTotal = (pages.length - 1) * indicatorPadding
const indicatorWidthTotal = indicatorWidth + indicatorPaddingTotal
const indicatorAlpha = 0.3

export function CC15PageIndicators() {
    const [current, setCurrent] = useState(0)

    return (
        <div>
            <Page
                // Visual & layout
                width={150}
                height={150}
                radius={30}
                center
                // Animation
                onChangePage={(current, previous) => {
                    setCurrent(current)
                }}
            >
                {pages.map(index => {
                    return (
                        <Frame
                            // Visual & layout
                            size={150}
                            radius={30}
                            backgroundColor="#fff"
                            // Required by React
                            key={index}
                        />
                    )
                })}
            </Page>

            {pages.map(index => {
                return (
                    <Frame
                        // Visual & layout
                        size={indicatorSize}
                        radius={30}
                        backgroundColor="#fff"
                        top="calc(50% + 100px)"
                        style={{
                            left: `calc(50% + ${index - 1} * ${indicatorSize +
                                indicatorPadding}px)`,
                        }}
                        x={-indicatorWidthTotal / 2}
                        // Animation
                        opacity={indicatorAlpha}
                        animate={{
                            opacity: current === index - 1 ? 1 : indicatorAlpha,
                        }}
                        // Required by React
                        key={index}
                    />
                )
            })}
        </div>
    )
}

Framer Motion

Not possible, because there’s no Page Component in Framer Motion library.

Override

Here Framer’s Data object is used to communicate between the distinct Overrides.

The Indicators override is attached to the parent Frame of the indicators. It maps through its children (the five indicators) and clones them, giving them an animate to the correct opacity.

const appState = Data({
    currentIndicator: 0,
})

export function Indicators(props): Override {
    return {
        children: props.children.map((indicator, index) => {
            let opacity = 0.3
            if (index === appState.currentIndicator) {
                opacity = 1
            }

            return cloneElement(indicator, {
                animate: { opacity: opacity },
            })
        }),
    }
}

export function Page(): Override {
    return {
        onChangePage(current, previous) {
            appState.currentIndicator = current
        },
    }
}

Leave a Reply