@@ -5,6 +5,7 @@ import { context as fiberContext, RootState, useFrame, useThree } from '@react-t
55import { DomEvent } from '@react-three/fiber/'
66import { easing } from 'maath'
77import { ForwardRefComponent } from '../../../utils/ts-utils'
8+ import { roundToPixelRatio } from '../../../utils/generic'
89
910export type ScrollControlsProps = {
1011 /** Precision, default 0.00001 */
@@ -27,6 +28,8 @@ export type ScrollControlsProps = {
2728 /** If true attaches the scroll container before the canvas */
2829 prepend ?: boolean
2930 enabled ?: boolean
31+ /** Snaps translate3d values to physical device pixels to prevent subpixel blurriness, default true */
32+ pixelPerfect ?: boolean
3033 style ?: React . CSSProperties
3134 children : React . ReactNode
3235}
@@ -44,6 +47,7 @@ export type ScrollControlsState = {
4447 range ( from : number , distance : number , margin ?: number ) : number
4548 curve ( from : number , distance : number , margin ?: number ) : number
4649 visible ( from : number , distance : number , margin ?: number ) : boolean
50+ pixelPerfect : boolean
4751}
4852
4953const context = /* @__PURE__ */ React . createContext < ScrollControlsState > ( null ! )
@@ -91,6 +95,7 @@ export function ScrollControls({
9195 damping = 0.25 ,
9296 maxSpeed = Infinity ,
9397 prepend = false ,
98+ pixelPerfect = true ,
9499 style = { } ,
95100 children,
96101} : ScrollControlsProps ) {
@@ -113,6 +118,7 @@ export function ScrollControls({
113118 delta : 0 ,
114119 scroll,
115120 pages,
121+ pixelPerfect,
116122 // 0-1 for a range between from -> from + distance
117123 range ( from : number , distance : number , margin : number = 0 ) {
118124 const start = from - margin
@@ -131,7 +137,7 @@ export function ScrollControls({
131137 } ,
132138 }
133139 return state
134- } , [ eps , damping , horizontal , pages ] )
140+ } , [ eps , damping , horizontal , pages , pixelPerfect ] )
135141
136142 React . useEffect ( ( ) => {
137143 el . style . position = 'absolute'
@@ -275,9 +281,13 @@ const ScrollHtml: ForwardRefComponent<{ children?: React.ReactNode; style?: Reac
275281 } , [ state . fixed ] )
276282 useFrame ( ( ) => {
277283 if ( state . delta > state . eps ) {
278- group . current . style . transform = `translate3d(${
279- state . horizontal ? - width * ( state . pages - 1 ) * state . offset : 0
280- } px,${ state . horizontal ? 0 : height * ( state . pages - 1 ) * - state . offset } px,0)`
284+ let x = state . horizontal ? - width * ( state . pages - 1 ) * state . offset : 0
285+ let y = state . horizontal ? 0 : height * ( state . pages - 1 ) * - state . offset
286+ if ( state . pixelPerfect ) {
287+ x = roundToPixelRatio ( x )
288+ y = roundToPixelRatio ( y )
289+ }
290+ group . current . style . transform = `translate3d(${ x } px,${ y } px,0)`
281291 }
282292 } )
283293 root . render (
0 commit comments