framer-motion#useTransform TypeScript Examples
The following examples show how to use
framer-motion#useTransform.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From tesla-homepage-ui-clone with MIT License | 6 votes |
ModelOverlay: React.FC<Props> = ({ model, children }) => {
const { scrollY } = useWrapperScroll();
const getSectionDimensions = useCallback(() => {
return {
offsetTop: model.sectionRef.current?.offsetTop ?? 0,
offsetHeight: model.sectionRef.current?.offsetHeight ?? 0,
} as SectionDimensions;
}, [model.sectionRef]);
const [dimensions, setDimensions] = useState<SectionDimensions>(getSectionDimensions());
useLayoutEffect(() => {
function onResize() {
window.requestAnimationFrame(() => setDimensions(getSectionDimensions()));
}
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize);
}, [getSectionDimensions, model.sectionRef]);
const sectionScrollProgress = useTransform(scrollY, y => (y - dimensions.offsetTop) / dimensions.offsetHeight);
const opacity = useTransform(sectionScrollProgress, [-0.65, -0.05, 0.05, 0.65], [0, 1, 1, 0]);
const pointerEvents = useTransform(opacity, value => (value > 0 ? 'auto' : 'none'));
return <Container style={{ opacity, pointerEvents }}>{children}</Container>;
}
Example #2
Source File: index.tsx From tesla-homepage-ui-clone with MIT License | 6 votes |
UniqueOverlay: React.FC = () => {
const { scrollYProgress } = useWrapperScroll();
const opacity = useTransform(scrollYProgress, [0.9, 1], [0, 1]);
return (
<Container id="top-page">
<Header />
<Footer opacity={opacity} />
</Container>
);
}
Example #3
Source File: parallax.tsx From samuelkraft-next with MIT License | 6 votes |
Parallax = ({ children, offset = 50, clampInitial, clampFinal }: ParallaxProps): JSX.Element => {
const prefersReducedMotion = useReducedMotion()
const [elementTop, setElementTop] = useState(0)
const [clientHeight, setClientHeight] = useState(0)
const ref = useRef(null)
const { scrollY } = useViewportScroll()
const initial = elementTop - clientHeight
const final = elementTop + offset
const yRange = useTransform(scrollY, [initial, final], [clampInitial ? 0 : offset, clampFinal ? 0 : -offset])
const y = useSpring(yRange, { stiffness: 400, damping: 90 })
useLayoutEffect(() => {
const element = ref.current
const onResize = () => {
setElementTop(element.getBoundingClientRect().top + window.scrollY || window.pageYOffset)
setClientHeight(window.innerHeight)
}
onResize()
window.addEventListener('resize', onResize)
return () => window.removeEventListener('resize', onResize)
}, [ref])
// Don't parallax if the user has "reduced motion" enabled
if (prefersReducedMotion) {
return <>{children}</>
}
return (
<motion.div ref={ref} style={{ y }}>
{children}
</motion.div>
)
}
Example #4
Source File: Parallax.tsx From vignette-web with MIT License | 5 votes |
Parallax = ({
children,
id,
offset = 30,
className,
fadeIn,
}: ParallaxProps): JSX.Element => {
const prefersReducedMotion = useReducedMotion()
const [elementTop, setElementTop] = useState(0)
const [clientHeight, setClientHeight] = useState(0)
const ref = useRef<HTMLDivElement>(null)
const { scrollY } = useViewportScroll()
const initial = elementTop - clientHeight
const final = elementTop + offset
const router = useRouter()
const yRange = useTransform(scrollY, [initial, final], [offset, -offset], {
clamp: true,
})
const y = useSpring(yRange, { stiffness: 400, damping: 90 })
useEffect(() => {
const element = ref.current
const onResize = () => {
if (element) {
setElementTop(
element.getBoundingClientRect().top + window.scrollY ||
window.pageYOffset,
)
}
setClientHeight(window.innerHeight)
}
onResize()
window.addEventListener(`resize`, onResize)
return () => window.removeEventListener(`resize`, onResize)
}, [ref, router.pathname])
// Don't parallax if the user has "reduced motion" enabled
if (prefersReducedMotion) {
return <>{children}</>
}
return (
<motion.div
id={id}
className={className}
ref={ref}
style={{ y }}
transition={fadeIn ? { delay: 0.15, duration: 0.3 } : {}}
initial={fadeIn && { opacity: 0 }}
whileInView={fadeIn ? { opacity: 1 } : {}}
viewport={{ once: true }}
>
{children}
</motion.div>
)
}
Example #5
Source File: ActionCard.tsx From nosgestesclimat-site with MIT License | 4 votes |
Card = ({ children, style, onVote, id, ...props }) => {
// motion stuff
const cardElem = useRef(null)
const x = useMotionValue(0)
const controls = useAnimation()
const [constrained, setConstrained] = useState(true)
const [direction, setDirection] = useState()
const [velocity, setVelocity] = useState()
const getVote = (childNode, parentNode) => {
const childRect = childNode.getBoundingClientRect()
const parentRect = parentNode.getBoundingClientRect()
let result =
parentRect.left >= childRect.right
? false
: parentRect.right <= childRect.left
? true
: undefined
return result
}
// determine direction of swipe based on velocity
const getDirection = () => {
return velocity >= 1 ? 'right' : velocity <= -1 ? 'left' : undefined
}
const getTrajectory = () => {
setVelocity(x.getVelocity())
setDirection(getDirection())
}
const flyAway = (min) => {
const flyAwayDistance = (direction) => {
const parentWidth = cardElem.current.parentNode.getBoundingClientRect()
.width
const childWidth = cardElem.current.getBoundingClientRect().width
return direction === 'left'
? -parentWidth / 2 - childWidth / 2
: parentWidth / 2 + childWidth / 2
}
if (direction && Math.abs(velocity) > min) {
setConstrained(false)
controls.start({
x: flyAwayDistance(direction),
})
}
}
useEffect(() => {
const unsubscribeX = x.onChange(() => {
const childNode = cardElem.current
const parentNode = cardElem.current.parentNode
const result = getVote(childNode, parentNode)
result !== undefined && onVote(result)
})
return () => unsubscribeX()
})
const xInput = [-100, 0, 100]
const background = useTransform(x, xInput, [
'linear-gradient(180deg, #f2a4f4 0%, #f49494 100%)',
'linear-gradient(180deg, #fff 0%, #fff 100%)',
'linear-gradient(180deg, rgb(230, 255, 0) 0%, rgb(3, 209, 0) 100%)',
])
return (
<StyledCard
animate={controls}
dragConstraints={constrained && { left: 0, right: 0, top: 0, bottom: 0 }}
dragElastic={1}
ref={cardElem}
style={{ x }}
onDrag={getTrajectory}
myBackground={background}
onDragEnd={() => flyAway(500)}
whileTap={{ scale: 1.1 }}
{...props}
>
{children}
</StyledCard>
)
}
Example #6
Source File: Checkbox.tsx From chroma-react with MIT License | 4 votes |
Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
(
{
['aria-label']: ariaLabel,
checked,
className,
classes: additionalClasses,
color = 'default',
disabled = false,
errorMessage,
hasError,
helpMessage,
indeterminate = false,
id,
label,
name,
...rootProps
},
ref
) => {
const classes = useStyles({ classes: additionalClasses });
const [uniqueId] = React.useState<string>(
() => id || name || generateUniqueId('checkbox-')
);
const pathLength = useMotionValue(0);
const opacity = useTransform(pathLength, [0.05, 0.15], [0, 1]);
if (!label && !ariaLabel && process.env.NODE_ENV === 'development') {
throw new Error(
'If a "label" is not provided to Checkbox, please provide "aria-label".'
);
}
const variant = [
checked ? 'checked' : 'unchecked',
disabled ? 'disabled' : 'enabled',
];
return (
<motion.div
className={clsx(classes.root, className)}
animate={variant}
initial={false}
whileHover="hover"
whileTap="pressed"
>
<input
aria-describedby={buildDescribedBy({
hasError,
hasHelpMessage: !!helpMessage,
uniqueId,
})}
aria-checked={
checked && !indeterminate
? 'true'
: !checked && !indeterminate
? 'false'
: !checked && indeterminate
? 'mixed'
: 'false'
}
className={clsx(classes.input, {
[classes.inputInverse]: color === 'inverse',
})}
ref={ref}
type="checkbox"
id={uniqueId}
name={name}
checked={checked}
disabled={disabled}
tabIndex={0}
{...rootProps}
/>
<div className={classes.labelContainer}>
<motion.label
className={classes.label}
htmlFor={uniqueId}
animate={variant}
whileHover="hover"
whileTap="pressed"
>
<motion.svg
className={classes.svg}
width="21"
height="21"
viewBox="0 0 21 21"
>
<motion.path
className={classes.box}
d="M1,5.524A4.523,4.523,0,0,1,5.524,1h9.952A4.523,4.523,0,0,1,20,5.524v9.952A4.523,4.523,0,0,1,15.476,20H5.524A4.523,4.523,0,0,1,1,15.476Z"
fill="transparent"
stroke="var(--checkbox-secondary-emphasis)"
strokeOpacity="0"
strokeMiterlimit="10"
strokeWidth="2"
variants={getBoxVariants({
disabled,
hasError,
color,
})}
/>
{indeterminate && disabled ? (
<motion.path
d="M6.5,10.458h8"
fill="transparent"
strokeWidth="2.25"
stroke="#FFFFFF"
strokeLinecap="round"
strokeLinejoin="round"
style={{ pathLength, opacity }}
custom={checked}
variants={getTickVariants({
disabled,
indeterminate,
color,
})}
/>
) : indeterminate ? (
<>
<motion.path
d="M10.5,10.458h-4"
fill="transparent"
strokeWidth="2.25"
stroke="#FFFFFF"
strokeLinecap="round"
strokeLinejoin="round"
style={{ pathLength, opacity }}
custom={checked}
variants={getTickVariants({
disabled,
indeterminate,
color,
})}
/>
<motion.path
d="M10.5,10.458h4"
fill="transparent"
strokeWidth="2.25"
stroke="#FFFFFF"
strokeLinecap="round"
strokeLinejoin="round"
style={{ pathLength, opacity }}
custom={checked}
variants={getTickVariants({
disabled,
indeterminate,
color,
})}
/>
</>
) : (
<motion.path
d="M5.761,11.962l2.187,2.187,7.291-7.3"
fill="transparent"
strokeWidth="2.25"
stroke="#FFFFFF"
strokeOpacity="1"
strokeLinecap="round"
strokeLinejoin="round"
style={{ pathLength, opacity }}
custom={checked}
variants={getTickVariants({ disabled, indeterminate, color })}
/>
)}
</motion.svg>
<Text
size="subbody"
className={clsx(
color === 'inverse' ? classes.labelInverse : undefined,
!label && ariaLabel && classes.srOnly
)}
>
{label || ariaLabel}
</Text>
</motion.label>
</div>
{helpMessage && (
<FormHelpMessage
color={color}
rootElementId={uniqueId}
describedById={helpFor(uniqueId)}
>
{helpMessage}
</FormHelpMessage>
)}
{hasError && (
<FormErrorMessage
color={color}
rootElementId={uniqueId}
describedById={errorFor(uniqueId)}
>
{errorMessage}
</FormErrorMessage>
)}
</motion.div>
);
}
)