Skip to content

Commit 256f428

Browse files
authored
Merge pull request #1 from TylerK/release
Fixing cross-browser jank
2 parents 956b64c + 42220d2 commit 256f428

File tree

4 files changed

+107
-91
lines changed

4 files changed

+107
-91
lines changed

demo.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,33 @@ class Example extends Component {
3737
<ParallaxHover
3838
width={200}
3939
height={200}
40-
borderRadius={8}
40+
borderRadius={10}
41+
rotation={3}
42+
shine={3}
4143
>
4244
<ExampleComponent>
43-
<img width="100%" src="http://www.lorempixel.com/200/200" />
45+
<img src="http://lorempixel.com/200/200/" alt=""/>
4446
</ExampleComponent>
4547
</ParallaxHover>
48+
4649
<ParallaxHover
4750
width={200}
4851
height={200}
49-
borderRadius={8}
52+
rotation={9}
5053
>
5154
<ExampleComponent>
52-
<img width="100%" src="http://www.lorempixel.com/220/220" />
55+
<img src="http://lorempixel.com/220/220/" alt=""/>
5356
</ExampleComponent>
5457
</ParallaxHover>
58+
5559
<ParallaxHover
5660
width={200}
5761
height={200}
58-
borderRadius={8}
62+
borderRadius={33}
63+
shine={9}
5964
>
6065
<ExampleComponent>
61-
<img width="100%" src="http://www.lorempixel.com/240/240" />
66+
<img src="http://lorempixel.com/240/240/" alt=""/>
6267
</ExampleComponent>
6368
</ParallaxHover>
6469
</div>

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
display: flex;
1717
justify-content: center;
1818
align-items: center;
19+
overflow: hidden;
1920
}
2021
</style>
2122
</head>

index.js

Lines changed: 94 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import React, { Component, PropTypes } from 'react';
22
import { StyleSheet, css } from 'aphrodite/no-important';
33

44
const baseStyles = {
5+
transition: {
6+
transition: 'all 222ms ease-out',
7+
},
58
layers: {
69
width: '100%',
710
height: '100%',
@@ -14,42 +17,29 @@ const baseStyles = {
1417
};
1518

1619
const styles = StyleSheet.create({
17-
outter: {
18-
transformStyle: 'preserve-3d'
19-
},
20-
wrapper: {
20+
parallaxHover__outter: {
21+
transformStyle: 'preserve-3d',
2122
position: 'relative',
22-
margin: 0,
23-
padding: 0,
24-
transition: 'all 180ms ease-in-out',
23+
overflow: 'visible',
24+
...baseStyles.transition,
2525
},
26-
shadow: {
27-
background: 'rgba(0, 0, 0, 0.2)',
26+
parallaxHover__wrapper: {
27+
overflow: 'hidden',
2828
...baseStyles.layers,
29-
filter: 'blur(3px)',
29+
},
30+
parallaxHover__shadow: {
31+
position: 'absolute',
3032
width: '80%',
3133
height: '80%',
3234
left: '10%',
3335
top: '10%',
34-
transition: 'all 180ms ease-in-out',
35-
},
36-
layers: {
37-
...baseStyles.layers
3836
},
39-
layer: {
40-
...baseStyles.layers,
37+
parallaxHover__layer: {
4138
overflow: 'hidden',
42-
},
43-
lighting: {
44-
opacity: 0,
4539
...baseStyles.layers,
4640
},
47-
text: {
48-
display: 'flex',
49-
justifyContent: 'center',
50-
alignItems: 'center',
51-
textAlign: 'center',
52-
fontSize: '5rem',
41+
parallaxHover__lighting: {
42+
...baseStyles.layers,
5343
},
5444
});
5545

@@ -60,7 +50,7 @@ const initialState = {
6050
shadowSize: 0,
6151
scale: 1,
6252
shine: 0,
63-
isScaling: false,
53+
isHovered: false,
6454
};
6555

6656
export default class ParallaxHover extends Component {
@@ -69,17 +59,21 @@ export default class ParallaxHover extends Component {
6959
this.state = initialState;
7060
}
7161

72-
buildTransformStrings(depth = 1) {
73-
const { scale, rotateX, rotateY } = this.state;
62+
componentWillMount() {
63+
const { shine } = this.props;
64+
this.setState({ shine });
65+
}
66+
67+
buildTransformStrings(depth = 0) {
68+
const { rotateX, rotateY } = this.state;
7469

75-
const scaleModifier = 1 + (scale / 100);
7670
const rotationXModifier = rotateX + depth;
7771
const rotationYModifier = rotateY + depth;
7872

7973
return {
80-
WebkitTransform: `perspective(1000px) scale(${scaleModifier}) rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`,
81-
MozTransform: `perspective(1000px) scale(${scaleModifier}) rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`,
82-
transform: `perspective(1000px) scale(${scaleModifier}) rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`
74+
WebkitTransform: `rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`,
75+
MozTransform: `rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`,
76+
transform: `rotateX(${rotationXModifier}deg) rotateY(${rotationYModifier}deg)`
8377
};
8478
}
8579

@@ -95,19 +89,28 @@ export default class ParallaxHover extends Component {
9589
return current / max * shine;
9690
}
9791

92+
handleParallaxBegin = () => {
93+
this.setState({
94+
isHovered: true,
95+
shine: this.props.shine,
96+
});
97+
}
98+
9899
handleParallaxEnd = () => {
99100
this.setState(initialState);
100101
}
101102

102103
handleParallaxMove = ({ pageX, pageY }) => {
103104
const { width, height, rotation, scale } = this.props;
104-
const { scrollTop, scrollLeft } = document.body;
105+
const { scrollY: scrollTop, scrollX: scrollLeft } = window;
106+
107+
if (!this.state.isHovered) this.setState({ isHovered: true });
105108

106109
const bounds = this.wrapper.getBoundingClientRect();
107110
const centerX = width / 2;
108111
const centerY = height / 2;
109112

110-
const widthMultiplier = 320 / width;
113+
const widthMultiplier = 360 / width;
111114
const offsetX = (pageX - bounds.left - scrollLeft) / width;
112115
const offsetY = (pageY - bounds.top - scrollTop) / height;
113116
const deltaX = (pageX - bounds.left - scrollLeft) - centerX;
@@ -119,11 +122,8 @@ export default class ParallaxHover extends Component {
119122
const angleRad = Math.atan2(deltaY, deltaX);
120123
const angleRaw = angleRad * 180 / Math.PI - 90;
121124
const angle = angleRaw < 0 ? angleRaw + 360 : angleRaw;
122-
const distanceFromCenter = this.calculateDistance(bounds, offsetX, offsetY);
123125
const shadowMovement = centerY * 0.25;
124-
const shadowSize = 120;
125-
126-
const shine = this.calculateShineFromCenter(distanceFromCenter);
126+
const shadowSize = 110;
127127

128128
this.setState({
129129
angle,
@@ -132,94 +132,104 @@ export default class ParallaxHover extends Component {
132132
scale,
133133
shadowMovement,
134134
shadowSize,
135-
shine,
136135
});
137136
}
138137

139138
renderLayers() {
140139
const { borderRadius, children } = this.props;
140+
const _styles = {
141+
borderRadius: `${borderRadius}px`,
142+
...this.buildTransformStrings(),
143+
};
141144

142145
if (!Array.isArray(children)) {
143-
const _styles = {
144-
...this.buildTransformStrings(),
145-
borderRadius: `${borderRadius}px`
146-
};
147-
148146
return (
149-
<div style={_styles} className={css(styles.layer)}>{children}</div>
147+
<div
148+
style={_styles}
149+
className={css(styles.parallaxHover__layer)}
150+
>
151+
{children}
152+
</div>
150153
);
151154
}
152155

153-
154156
return children.map((layer, key) => {
155-
const depth = key + 0.1;
156-
const _styles = {
157-
...this.buildTransformStrings(depth),
158-
borderRadius: `${borderRadius}px`
159-
};
160-
return <div style={_styles} className={css(styles.layer)} key={key}>{layer}</div>;
157+
return (
158+
<div
159+
style={_styles}
160+
className={css(styles.parallaxHover__layer)}
161+
key={key}
162+
>
163+
{layer}
164+
</div>
165+
);
161166
});
162167
}
163168

164169
render() {
165-
const { angle, shine, shadowMovement, shadowSize } = this.state;
170+
const { angle, isHovered, scale, shadowMovement, shadowSize, shine } = this.state;
166171
const { borderRadius, width, height } = this.props;
167172

168-
// Styles that need to be recalculated on render
169-
// Or passed in from props
173+
const scaleModifier = isHovered ? (1 + scale / 50) : 1;
174+
175+
// Styles that need to be recalculated on render or passed in from props
170176
const _styles = {
171-
lighting: {
172-
backgroundImage: `linear-gradient(${angle}deg, rgba(255,255,255, ${(shine / 10)}) 0%, rgba(255,255,255,0) 40%)`,
177+
overlay: {
178+
width: `${width}px`,
179+
height: `${height}px`,
180+
transform: `scale(${scaleModifier}) perspective(1000px)`
181+
},
182+
wrapper: {
183+
height: `${height}px`,
184+
width: `${width}px`,
173185
borderRadius: `${borderRadius}px`,
174-
opacity: '1',
175186
...this.buildTransformStrings(),
176187
},
177-
178-
shadow: {
179-
boxShadow: `0px ${shadowMovement}px ${shadowSize}px rgba(0, 0, 0, 0.6)`,
188+
lighting: {
189+
backgroundImage: `linear-gradient(${angle}deg, rgba(255,255,255, ${shine / 10}) 0%, rgba(255,255,255,0) 50%)`,
180190
borderRadius: `${borderRadius}px`,
181191
...this.buildTransformStrings(),
182192
},
183-
184-
wrapper: {
185-
height: `${height}px`,
186-
width: `${width}px`,
193+
shadow: {
187194
borderRadius: `${borderRadius}px`,
195+
boxShadow: `0px ${shadowMovement}px ${shadowSize}px rgba(0, 0, 0, 0.5)`,
188196
...this.buildTransformStrings(),
189197
},
190198
};
191199

192200
return (
193-
<div className={css(styles.outter)}>
201+
<div
202+
className={css(styles.parallaxHover__outter)}
203+
onMouseEnter={this.handleParallaxBegin}
204+
onMouseLeave={this.handleParallaxEnd}
205+
onMouseMove={this.handleParallaxMove}
206+
onTouchStart={this.handleParallaxBegin}
207+
onTouchMove={this.handleParallaxEnd}
208+
onTouchEnd={this.handleParallaxMove}
209+
style={_styles.overlay}
210+
>
211+
<div className={css(styles.parallaxHover__shadow)} style={_styles.shadow} />
194212
<div
195-
className={css(styles.wrapper)}
213+
className={css(styles.parallaxHover__wrapper)}
196214
style={_styles.wrapper}
197-
onMouseEnter={this.handleParallaxBegin}
198-
onMouseLeave={this.handleParallaxEnd}
199-
onMouseMove={this.handleParallaxMove}
200-
onTouchStart={this.handleParallaxBegin}
201-
onTouchMove={this.handleParallaxMove}
202-
onTouchEnd={this.handleParallaxEnd}
203215
ref={(wrapper) => { this.wrapper = wrapper; }}
204216
>
205-
<div className={css(styles.shadow)} style={_styles.shadow} />
206-
<div className={css(styles.layers)}>
207-
{ this.renderLayers() }
208-
</div>
209-
<div className={css(styles.lighting)} style={_styles.lighting} />
217+
{ this.renderLayers() }
218+
<div className={css(styles.parallaxHover__lighting)} style={_styles.lighting} />
210219
</div>
211220
</div>
212221
);
213222
}
214223
}
215224

216225
ParallaxHover.defaultProps = {
217-
speed: 100, // How fast the item scales up and down in MS
218-
scale: 5, // How large to scale the item
219-
rotation: 6, // Rotation modifier
220-
shine: 5, // Light shine brightness modifer
221-
height: 200, // Default height
222-
width: 200, // Default width
226+
speed: 100, // How fast the item scales up and down in MS
227+
scale: 6, // How large to scale the item
228+
rotation: 8, // Rotation modifier
229+
shine: 5, // Light shine brightness modifer
230+
height: 200, // Default height
231+
width: 200, // Default width
232+
borderRadius: 0 // Default border radius
223233
};
224234

225235
ParallaxHover.propTypes = {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-parallax-hover",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/TylerK/react-parallax-hover.git"

0 commit comments

Comments
 (0)