Skip to content

Instantly share code, notes, and snippets.

View mattgperry's full-sized avatar

Matt Perry mattgperry

View GitHub Profile
@mattgperry
mattgperry / index.html
Created February 1, 2024 14:35
Number.toString() #jsbench #jsperf (https://jsbench.github.io/#bbe25417c2edc2573bf060860d23e23e) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Number.toString() #jsbench #jsperf</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<script src="./suite.js"></script>
</head>
<body>
<h1>Open the console to view the results</h1>
@mattgperry
mattgperry / pregenerated-keyframe-performance.html
Last active January 13, 2024 16:48
Pre-generated keyframes performance issues in Chrome
<html>
<head>
<title>Pre-generated keyframes performance</title>
<!--
This file demonstrates that the performance of pre-generated keyframes is poor in Chrome
under surprising circumstances.
Specifically, pre-generated keyframes are fine in isolation. But when combined with a
requestAnimationFrame animation, AND another WAAPI animation, performance becomes
(literally) 100x worse.
@mattgperry
mattgperry / useGreensock.js
Last active February 20, 2023 15:19
Simplify the use of Greensock and React
function useGreensock(callback, deps, optionalScope) {
const defaultScope = useRef()
const scope = optionalScope || defaultScope
useLayoutEffect(() => {
const context = gsap.context(callback, scope)
return () => context.revert()
}, deps)
@mattgperry
mattgperry / TextSplit.tsx
Created October 29, 2020 15:25
TextSplit
'The animator’s JavaScript toolbox.'.split('').map((character, i) => (
<TaglineCharacter index={i} key={i} character={character} />
))
function TaglineCharacter({ character, index }) {
const ref = useRef(null);
useEffect(() => {
const controls = animate({
from: 0,
import {
AnimatePresence,
AnimateSharedLayout,
motion,
useMotionValue,
useIsPresent,
} from "framer-motion";
import * as React from "react";
import { useEffect, useRef, useState } from "react";
import { shuffle } from "lodash";
import { useEffect } from "react";
function handleSpace(event: KeyboardEvent) {
if (event.key === " ") {
event.preventDefault();
const delta = event.shiftKey ? -window.innerHeight : window.innerHeight;
window.scrollTo(0, window.scrollY + delta);
}
}
@mattgperry
mattgperry / pointerEvents.tsx
Created August 26, 2020 15:19
Disable pointer-events at low opacity in Framer Motion
import { motion, useMotionValue, useTransform } from "framer-motion"
export function Overlay({ isVisible }) {
const opacity = useMotionValue(0)
const pointerEvents = useTransform(
opacity,
latest => latest < 0.5 ? "none" : "auto"
)
return (
@mattgperry
mattgperry / gist:c4d23752a0fae7888596c4ff6d92733a
Created August 10, 2020 13:36
useTransform tuple types
class MotionValue<T> {
constructor(public current: T) {}
}
type UnwrapMotionValueArray<V extends MotionValue<any>[]> = { [K in keyof V ]: V[K] extends MotionValue<infer T> ? T : never }
function unwrap<T extends MotionValue<any>[]>(value: [...T]): UnwrapMotionValueArray<typeof value> {
return value.map(v => v.current) as [...UnwrapMotionValueArray<T>]
}
@mattgperry
mattgperry / useMotionTemplate.ts
Last active May 14, 2020 13:58
useMotionTemplate: Combine multiple motion values into a new one using a template literal
import { useEffect } from "react";
import sync from "framesync";
import { useMotionValue, MotionValue } from "framer-motion";
/**
* Combine multiple motion values into a new one using a template literal.
*
* Updates in source motion values are batched to once per frame.
*
* ```javascript
@mattgperry
mattgperry / test.ts
Created March 31, 2020 07:51
Framer Motion example test
test("drag handlers aren't frozen at drag session start", async () => {
let count = 0
const onDragEnd = deferred()
const Component = () => {
const [increment, setIncrement] = useState(1)
return (
<MockDrag>
<motion.div
drag
onDragStart={() => {