react-track icon indicating copy to clipboard operation
react-track copied to clipboard

Tracked Position on Page load

Open mikegallay opened this issue 7 years ago • 12 comments

A few of the items I am tracking appear slightly above the bottom of the page on load. These items are appearing with a translate3d y-position of -33% (see code below). Once I scroll they jump to the calculated position based on my tween. Is there any way to have the tween calculate and apply while their position on load (without seeing a jump)?

I have already tried applying a scroll using js, but you can still see they items jump once the calculated tween takes hold. Thanks!

<DIV
	className='tile-wrapper-scroll'
	style={ tween(scrollY, [
		[posTopBottom, { transform: translate3d(0, percent(0), 0) }],
		[posBottomTop, { transform: translate3d(0, percent(-33), 0) }]
	])}
	>
	<div className='tile-wrapper' style={tileStyle}></div>
</DIV>

mikegallay avatar Mar 20 '17 21:03 mikegallay

Try adding the updateOnDidMount prop to <TrackDocument /> and lmk if it works. For some reason I never documented this prop.

gilbox avatar Mar 20 '17 21:03 gilbox

So, it should look like this?

<TrackDocument updateOnDidMount formulas={[getDocumentElement, ...

mikegallay avatar Mar 20 '17 21:03 mikegallay

yes

gilbox avatar Mar 20 '17 21:03 gilbox

I don't see any difference. Is there anything else I need to import?

mikegallay avatar Mar 20 '17 21:03 mikegallay

Nah that's it... I'm not sure to what extend the problem you're experiencing is specific to react-track... try logging the values of scrollY, posTopBottom, posBottomTop in your render function. I suspect that one of them is jumping, probably posBottomTop.

gilbox avatar Mar 20 '17 21:03 gilbox

On page load: scrollY = 0; posTopBottom = -677; posBottomTop = 0; On slight scroll: scrollY = 2; posTopBottom = 250; posBottomTop = 1404; From what I can tell, the scroll position is calculated just before the content is actually on the page, so that position and value get locked in. As soon as I scroll, the new positioning takes over.

mikegallay avatar Mar 20 '17 21:03 mikegallay

I set a breakpoint in the demo page and noticed the same behavior happening there. I wonder if you can somehow structure your page in a similar way so that the initial calculation doesn't mess anything up? Another thing to try is to use visibility: hidden until the calculation is correct.

gilbox avatar Mar 20 '17 22:03 gilbox

Unfortunately, I cannot hide the content until the scroll fires. One thing to note, I am actually mapping an array of content through another render function:

{ this.props.data.map(this.renderTile.bind(this,[topBottom, bottomTop]))

I am passing the formulas I need to this function, which has the subsequent <Track> elements. I'm not sure if this has any bearing on the load order or how the positioning is calculated.

Have you come across any simple/effective ways to fire off the scroll once the content is in place? I've tried TweenMax from a position, adding scrollBy functions and a few more things, but nothing has produced an effective result. Thanks again for responding.

mikegallay avatar Mar 20 '17 22:03 mikegallay

What you can do is modify the source here so that instead of doing

const update = ....

we do

this.update = ...

then you can grab the ref of <TrackDocument

<TrackDocument ref={r => this.trackDocument = r}

Finally, you can trigger an update whenever you want by doing

this.trackDocument.update()

Try it out on your project and if it works, feel free to create a PR to add this feature.

gilbox avatar Mar 20 '17 22:03 gilbox

Awesome. I will check this out and get back to you. Thanks.

On Mar 20, 2017, at 6:27 PM, Gil Birman [email protected] wrote:

What you can do is modify the source here so that instead of doing

const update = .... we do

this.update = ... then you can grab the ref of <TrackDocument

<TrackDocument ref={r => this.trackDocument = r} Finally, you can trigger an update whenever you want by doing

this.trackDocument.update() Try it out on your project and if it works, feel free to create a PR to add this feature.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

mikegallay avatar Mar 20 '17 22:03 mikegallay

This gets me much closer, but the calculation isn't perfect and unfortunately there is still a noticeable jump. I'm thinking that it has something to do with mapping through an array and calling another function to render the elements I'm having issues with (full code below).

When I put the <Track> code within the same render call with the <TrackDocument> there doesn't seem to be an issue and everything is where it is supposed to be. Note: I tested putting everything under one render call without doing the update suggestion you recommended above and the jump effect was still there. This isn't a real solution for me since I would still need to map through an array.

So, the issue appears to be a combination of using your update suggestion and something else, which may or may not have something to do with calling another render function from within the original <TrackDocument> render function. I'm providing a little more code to show you how I've set up the functions. Notice how I pass the formulae I need to renderTile(). Let me know if you see any issues with this or have any other suggestions. Thanks!

renderTile(formulas,item, idx, collection) {
		var tileStyle = {
			background: 'url('+ item.secondaryImage +')',
			backgroundSize:'cover'
		};

		return (
			<Link
				className='tile'
				key={ item.slug }
				to={ `/work/${item.slug}` }

			>
			<Track component="div" formulas={[formulas[0],formulas[1]]}>
			{(DIV,posTopBottom, posBottomTop) =>
				<DIV
					className='tile-wrapper-scroll'
					style={ tween(scrollY, [
						[posTopBottom, { transform: translate3d(0, percent(0), 0) }],
						[posBottomTop, { transform: translate3d(0, percent(-33), 0) }]
					])}
					>
					<div className='tile-wrapper' style={tileStyle}></div>

				</DIV>

			}</Track>
				<div className="tile-inner">
					<p className="tile-office">{ `${item.office}` }</p>
					<div className="tile-copy">
						<h4 className="tile-client">{ `${item.client}` }</h4>
						<p>{ `${item.blurb}` }</p>
					</div>
				</div>

			</Link>
		);
	}

	render() {
		return (
			<TrackDocument
			 	ref={r => this.$trackDocument = r}
				formulas={[getDocumentElement, getDocumentRect, calculateScrollY, topTop, topBottom, topCenter, centerCenter, bottomBottom, bottomTop]}>
			     {(documentElement, documentRect, scrollY, topTop, topBottom, topCenter, centerCenter, bottomBottom, bottomTop) =>

				<div className={`work-tiles ${this.props.expandedTiles} ${this.props.dataReady == true ? 'dataReady' : ''}`}>
					{this.props.dataReady && this.props.data.map(this.renderTile.bind(this,[topBottom, bottomTop]))}

				</div>

			}</TrackDocument>
		);
	}

mikegallay avatar Mar 21 '17 02:03 mikegallay

I wanted to follow up with you. I have found a solve after writing a custom fix, but after going through this process I believe a piece of what I did is what our missing element was.

Exposing that update function does work, but calling it onMount was not enough. Apparently, the timing of the onMount call doesn't give all the rendered elements enough time to actually "mount". Even with my custom solve I need to tell the page to update using a setTimeout. The timeout was only 50ms, but that was enough for the page to render using the correct scroll calculation.

In order to keep the viewer from seeing the position of the track elements jump on this update call, I simply hid them until it happened, by setting the state of another variable {onInit : true} and using it to add a class ('showElements') to my elements that controlled their opacity:

className={'work-detail-wrapper ${this.state.onInit ? 'showElements' : ''}'}

Note: the single quotes directly inside the outer-most curly brackets should be backticks. The formatting on git-hub keeps them from rendering properly.

Hopefully, this fix works for anyone who has a similar issue. Thanks for your input and feedback.

mikegallay avatar Mar 24 '17 16:03 mikegallay