Skip to content

Commit

Permalink
fix: immediate cursor animation
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Jul 18, 2021
1 parent 627a9de commit c26aaac
Show file tree
Hide file tree
Showing 5 changed files with 1,893 additions and 1,876 deletions.
8 changes: 5 additions & 3 deletions examples/simple/src/ResizableBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ export default function ResizableBox({
height = 300,
resizable = true,
style = {},
className = ''
className = "",
}) {
return (
<div>
{resizable ? (
<ReactResizableBox width={width} height={height}>
<div
style={{
boxShadow: "0 20px 40px rgba(0,0,0,.1)",
...style,
width: "100%",
height: "100%"
height: "100%",
}}
className={className}
>
Expand All @@ -31,7 +32,8 @@ export default function ResizableBox({
style={{
width: `${width}px`,
height: `${height}px`,
...style
boxShadow: "0 20px 40px rgba(0,0,0,.1)",
...style,
}}
className={className}
>
Expand Down
45 changes: 31 additions & 14 deletions src/components/Cursors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,18 @@ function Cursor<TDatum>(props: {

const value = props.options.value ?? datumValue

const latestValue = useLatestWhen(
props.options.value ?? resolveValue(latestFocusedDatum),
typeof props.options.value !== 'undefined'
const latestPropsValue = useLatestWhen(
props.options.value,
props.options.value != null
)

const latestDatumValue = useLatestWhen(
resolveValue(latestFocusedDatum),
resolveValue(latestFocusedDatum) != null
)

const latestValue = latestPropsValue ?? latestDatumValue

// Get the sibling range
const siblingRange = siblingAxis.scale.range()

Expand All @@ -133,10 +140,10 @@ function Cursor<TDatum>(props: {

const bandWidth = axis.axisFamily === 'band' ? axis.scale.bandwidth() : 1

const px = axis.scale(latestValue)

const show = typeof value !== 'undefined' && !Number.isNaN(value)

let px = axis.scale(value)

// Vertical alignment
if (axis.isVertical) {
y = px
Expand All @@ -162,12 +169,12 @@ function Cursor<TDatum>(props: {
}
}

const lineStartX = Math.min(x1, x2)
const lineStartY = Math.min(y1, y2)
const lineEndX = Math.max(x1, x2)
const lineEndY = Math.max(y1, y2)
const lineHeight = Math.max(lineEndY - lineStartY, 0)
const lineWidth = Math.max(lineEndX - lineStartX, 0)
let lineStartX = Math.min(x1, x2)
let lineStartY = Math.min(y1, y2)
let lineEndX = Math.max(x1, x2)
let lineEndY = Math.max(y1, y2)
let lineHeight = Math.max(lineEndY - lineStartY, 0)
let lineWidth = Math.max(lineEndX - lineStartX, 0)

let bubbleX
let bubbleY
Expand Down Expand Up @@ -212,12 +219,22 @@ function Cursor<TDatum>(props: {

const svgRect = useRect(svgRef.current, show)

const immediatePos = !axis.isVertical ? lineStartX : lineStartY
const immediate = usePrevious(immediatePos) === -1 && immediatePos > -1

const lineRef = React.useRef<HTMLDivElement | null>(null)
const bubbleRef = React.useRef<HTMLDivElement | null>(null)

const latestLineStartX = useLatestWhen(lineStartX, px != null)
const latestLineStartY = useLatestWhen(lineStartY, px != null)
const latestBubbleX = useLatestWhen(bubbleX, px != null)
const latestBubbleY = useLatestWhen(bubbleY, px != null)

const previousTruePx = usePrevious(px)
const immediate = previousTruePx == null && px !== null

lineStartX = (px != null ? lineStartX : latestLineStartX) ?? NaN
lineStartY = (px != null ? lineStartY : latestLineStartY) ?? NaN
bubbleX = (px != null ? bubbleX : latestBubbleX) ?? NaN
bubbleY = (px != null ? bubbleY : latestBubbleY) ?? NaN

const lineXSpring = useSpring(
lineStartX,
[1, 210, 20],
Expand Down
15 changes: 10 additions & 5 deletions src/hooks/useSpring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@ export function useSpring(
value: number,
config: [number, number, number],
cb: (x: number) => void,
immediate?: boolean
immediate?: boolean,
debug?: boolean
) {
const springRef = React.useRef(new Spring(value, ...config))
const getImmediate = useGetLatest(immediate)
const getValue = useGetLatest(value)

const [startRaf, stopRaf] = useRaf(() => {
cb(springRef.current.x())
return springRef.current.done()
})

// Immediate
React.useEffect(() => {
if (springRef.current.endPosition !== value) {
springRef.current.setEnd(value, getImmediate())
if (immediate) {
springRef.current.snap(getValue())
startRaf()
return
}
}, [getImmediate, startRaf, value])
springRef.current.setEnd(value)
startRaf()
}, [debug, getValue, immediate, startRaf, stopRaf, value])

React.useEffect(() => {
return () => {
Expand Down
33 changes: 13 additions & 20 deletions src/utils/spring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,7 @@ export class Spring {
return this._solution ? this._solution.dx(dt) : 0
}

setEnd(x: number, immediate?: boolean) {
if (immediate) {
this._solution = null
this.endPosition = x
this._startTime = 0
return
}

setEnd(x: number) {
const t = new Date().getTime()

let velocity = 0
Expand All @@ -87,18 +80,18 @@ export class Spring {
this._startTime = t
}

// snap(x: number) {
// this._startTime = new Date().getTime()
// this.endPosition = x
// this._solution = {
// x() {
// return 0
// },
// dx() {
// return 0
// },
// }
// }
snap(x: number) {
this._startTime = new Date().getTime()
this.endPosition = x
this._solution = {
x() {
return 0
},
dx() {
return 0
},
}
}

done() {
return almostEqual(this.x(), this.endPosition) && almostZero(this.dx())
Expand Down
Loading

1 comment on commit c26aaac

@vercel
Copy link

@vercel vercel bot commented on c26aaac Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.