Skip to content

Commit 2c5ce9e

Browse files
committed
fix: fix useIonicHeaderParallax hook
1 parent 0b316e8 commit 2c5ce9e

File tree

1 file changed

+121
-105
lines changed

1 file changed

+121
-105
lines changed

src/useIonicHeaderParallax.ts

Lines changed: 121 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,209 +1,225 @@
1-
import * as React from 'react'
1+
import * as React from "react";
22

33
export type UseIonHeaderParallaxInput = {
4-
image: string
5-
expandedColor?: string
6-
titleColor?: string
7-
maximumHeight?: number
8-
}
4+
image: string;
5+
expandedColor?: string;
6+
titleColor?: string;
7+
maximumHeight?: number;
8+
};
99

1010
export type UseIonHeaderParallaxResult = {
11-
ref: React.RefObject<any>
12-
}
11+
ref: React.RefObject<any>;
12+
};
1313

1414
export function useIonHeaderParallax({
1515
image,
16-
titleColor = '#AAA',
17-
expandedColor = '#313131',
16+
titleColor = "#AAA",
17+
expandedColor = "#313131",
1818
maximumHeight = 300,
1919
}: UseIonHeaderParallaxInput): UseIonHeaderParallaxResult {
2020
/** styles */
21-
const [ticking, setTicking] = React.useState<boolean>(false)
21+
const [ticking, setTicking] = React.useState<boolean>(false);
2222

23-
const ref: React.RefObject<any> = React.useRef<any>(null)
23+
const ref: React.RefObject<any> = React.useRef<any>(null);
2424

2525
React.useEffect(() => {
2626
setTimeout(() => {
27-
initElements()
28-
}, 300)
29-
}, [image, titleColor, expandedColor, maximumHeight, ref])
27+
initElements();
28+
}, 300);
29+
}, [image, titleColor, expandedColor, maximumHeight, ref]);
3030

3131
const initElements = () => {
3232
// ion-header
3333
if (ref && ref.current) {
34-
const header = ref.current
35-
const parentElement = header.parentElement
36-
if (!parentElement) throw new Error('No IonPage parent element')
34+
const header = ref.current;
35+
const parentElement = header.parentElement;
36+
if (!parentElement) throw new Error("No IonPage parent element");
3737

3838
// ion-toolbar
39-
const toolbar = header.querySelector('ion-toolbar') as HTMLElement
40-
if (!toolbar) throw new Error('No <ion-toolbar>')
39+
const toolbar = header.querySelector("ion-toolbar") as HTMLElement;
40+
if (!toolbar) throw new Error("No <ion-toolbar>");
4141

4242
// ion-toolbar background
43-
const toolbarShadowRoot = toolbar.shadowRoot
43+
const toolbarShadowRoot = toolbar.shadowRoot;
4444

45-
if (!toolbarShadowRoot) throw new Error('No shadow')
46-
const toolbarBackground = toolbarShadowRoot.querySelector('.toolbar-background') as HTMLElement
45+
if (!toolbarShadowRoot) throw new Error("No shadow");
46+
const toolbarBackground = toolbarShadowRoot.querySelector(
47+
".toolbar-background"
48+
) as HTMLElement;
4749

4850
// ion-title
49-
const ionTitle = toolbar.querySelector('ion-title')
51+
const ionTitle = toolbar.querySelector("ion-title");
5052

5153
// ion-buttons
52-
const barButtons = header.querySelector('ion-buttons') as HTMLElement
54+
const barButtons = header.querySelector("ion-buttons") as HTMLElement;
5355

5456
// ion-content
55-
const ionContent = parentElement.querySelector('ion-content')
56-
if (!ionContent) throw new Error('Parallax requires an <ion-content> element on the page to work.')
57-
const scrollContent = ionContent.shadowRoot?.querySelector('.inner-scroll') as HTMLElement
57+
const ionContent = parentElement.querySelector("ion-content");
58+
if (!ionContent)
59+
throw new Error(
60+
"Parallax requires an <ion-content> element on the page to work."
61+
);
62+
const scrollContent = ionContent.shadowRoot?.querySelector(
63+
".inner-scroll"
64+
) as HTMLElement;
5865
if (!scrollContent) {
59-
throw new Error('Parallax directive requires an <ion-content> element on the page to work.')
66+
throw new Error(
67+
"Parallax directive requires an <ion-content> element on the page to work."
68+
);
6069
}
6170

6271
// create image overly
63-
const imageOverlay = document.createElement('div')
64-
imageOverlay.classList.add('image-overlay')
65-
const colorOverlay = document.createElement('div')
66-
colorOverlay.classList.add('color-overlay')
67-
colorOverlay.appendChild(imageOverlay)
68-
header.appendChild(colorOverlay)
72+
const imageOverlay = document.createElement("div");
73+
imageOverlay.classList.add("image-overlay");
74+
const colorOverlay = document.createElement("div");
75+
colorOverlay.classList.add("color-overlay");
76+
colorOverlay.appendChild(imageOverlay);
77+
header.appendChild(colorOverlay);
6978

70-
const overlayTitle = ionTitle && (ionTitle.cloneNode(true) as HTMLElement)
79+
const overlayTitle =
80+
ionTitle && (ionTitle.cloneNode(true) as HTMLElement);
7181

7282
if (overlayTitle) {
73-
overlayTitle.classList.add('parallax-title')
83+
overlayTitle.classList.add("parallax-title");
7484

7585
setTimeout(() => {
7686
if (overlayTitle.shadowRoot) {
77-
const toolbarTitle = overlayTitle.shadowRoot.querySelector('.toolbar-title') as HTMLElement
78-
toolbarTitle.style.pointerEvents = 'unset'
87+
const toolbarTitle = overlayTitle.shadowRoot.querySelector(
88+
".toolbar-title"
89+
) as HTMLElement;
90+
toolbarTitle.style.pointerEvents = "unset";
7991
}
80-
}, 200)
92+
}, 200);
8193
}
8294

8395
if (overlayTitle) {
84-
imageOverlay.appendChild(overlayTitle)
96+
imageOverlay.appendChild(overlayTitle);
8597
}
8698
if (barButtons) {
87-
imageOverlay.appendChild(barButtons)
99+
imageOverlay.appendChild(barButtons);
88100
}
89101

90102
/*** initStyles ***/
91103
// still in init use JS DOM
92-
setTicking(false)
104+
setTicking(false);
93105

94106
// fetch styles
95-
maximumHeight = parseFloat(maximumHeight.toString())
96-
let headerMinHeight = toolbar.offsetHeight
107+
maximumHeight = parseFloat(maximumHeight.toString());
108+
let headerMinHeight = toolbar.offsetHeight;
97109

98-
let scrollContentPaddingTop: number = parseFloat(
99-
window.getComputedStyle(scrollContent as Element, null).paddingTop.replace('px', '')
100-
)
101-
102-
const originalToolbarBgColor = window.getComputedStyle(toolbarBackground as Element, null).backgroundColor
110+
const originalToolbarBgColor = window.getComputedStyle(
111+
toolbarBackground as Element,
112+
null
113+
).backgroundColor;
103114
if (!originalToolbarBgColor) {
104-
throw new Error('Error: toolbarBackround is null.')
115+
throw new Error("Error: toolbarBackround is null.");
105116
}
106117

107118
// header and title
108-
header.style.position = 'relative'
119+
header.style.position = "relative";
109120

110121
if (overlayTitle) {
111-
overlayTitle.style.color = titleColor
112-
overlayTitle.style.position = 'absolute'
113-
overlayTitle.style.width = '100%'
114-
overlayTitle.style.height = '100%'
115-
overlayTitle.style.textAlign = 'center'
122+
overlayTitle.style.color = titleColor;
123+
overlayTitle.style.position = "absolute";
124+
overlayTitle.style.width = "100%";
125+
overlayTitle.style.height = "100%";
126+
overlayTitle.style.textAlign = "center";
116127
}
117128

118129
// color overlay
119-
colorOverlay.style.backgroundColor = originalToolbarBgColor
120-
colorOverlay.style.height = `${maximumHeight}px`
121-
colorOverlay.style.position = 'absolute'
122-
colorOverlay.style.top = `${-headerMinHeight * 0}px`
123-
colorOverlay.style.left = '0'
124-
colorOverlay.style.width = '100%'
125-
colorOverlay.style.zIndex = '10'
126-
colorOverlay.style.pointerEvents = 'none'
130+
colorOverlay.style.backgroundColor = originalToolbarBgColor;
131+
colorOverlay.style.height = `${maximumHeight}px`;
132+
colorOverlay.style.position = "absolute";
133+
colorOverlay.style.top = `${-headerMinHeight * 0}px`;
134+
colorOverlay.style.left = "0";
135+
colorOverlay.style.width = "100%";
136+
colorOverlay.style.zIndex = "10";
137+
colorOverlay.style.pointerEvents = "none";
127138

128139
// image overlay
129-
imageOverlay.style.backgroundColor = expandedColor
130-
imageOverlay.style.backgroundImage = `url(${image})`
131-
imageOverlay.style.height = '100%'
132-
imageOverlay.style.width = '100%'
133-
imageOverlay.style.pointerEvents = 'none'
134-
imageOverlay.style.backgroundSize = 'cover'
135-
imageOverlay.style.backgroundPosition = 'center'
140+
imageOverlay.style.backgroundColor = expandedColor;
141+
imageOverlay.style.backgroundImage = `url(${image})`;
142+
imageOverlay.style.height = "100%";
143+
imageOverlay.style.width = "100%";
144+
imageOverlay.style.pointerEvents = "none";
145+
imageOverlay.style.backgroundSize = "cover";
146+
imageOverlay.style.backgroundPosition = "center";
136147

137148
// .toolbar-background
138-
toolbarBackground.style.backgroundColor = originalToolbarBgColor
149+
toolbarBackground.style.backgroundColor = originalToolbarBgColor;
139150

140151
// .bar-buttons
141152
if (barButtons) {
142-
barButtons.style.pointerEvents = 'all'
153+
barButtons.style.pointerEvents = "all";
143154

144155
Array.from(barButtons.children).forEach((btn) => {
145156
// console.log(btn, btn as HTMLElement)
146-
const htmlBtn = btn as HTMLElement
147-
htmlBtn.style.color = titleColor
148-
})
157+
const htmlBtn = btn as HTMLElement;
158+
htmlBtn.style.color = titleColor;
159+
});
149160
}
150161

151162
// .scroll-content
152163
if (scrollContent) {
153-
scrollContent.setAttribute('parallax', '')
154-
scrollContent.style.paddingTop = `${maximumHeight + scrollContentPaddingTop - headerMinHeight}px`
164+
scrollContent.setAttribute("parallax", "");
165+
scrollContent.style.paddingTop = `250px`;
155166
}
156167

157168
if (scrollContent) {
158-
scrollContent.addEventListener('scroll', (_e) => {
169+
scrollContent.addEventListener("scroll", (_e) => {
159170
if (!ticking) {
160171
window.requestAnimationFrame(() => {
161172
// to do
162173

163-
const scrollTop = scrollContent.scrollTop
174+
const scrollTop = scrollContent.scrollTop;
164175

165176
// Parallax total progress
166-
headerMinHeight = toolbar.offsetHeight
177+
headerMinHeight = toolbar.offsetHeight;
167178

168-
let progress = (maximumHeight - scrollTop - headerMinHeight) / (maximumHeight - headerMinHeight)
169-
progress = Math.max(progress, 0)
179+
let progress =
180+
(maximumHeight - scrollTop - headerMinHeight) /
181+
(maximumHeight - headerMinHeight);
182+
progress = Math.max(progress, 0);
170183

171-
let targetHeight = maximumHeight - scrollTop
172-
targetHeight = Math.max(targetHeight, headerMinHeight)
184+
let targetHeight = maximumHeight - scrollTop;
185+
targetHeight = Math.max(targetHeight, headerMinHeight);
173186

174187
// .toolbar-background: change color
175-
imageOverlay.style.height = `${targetHeight}px`
176-
imageOverlay.style.opacity = `${progress}`
177-
colorOverlay.style.height = `${targetHeight}px`
178-
colorOverlay.style.opacity = targetHeight > headerMinHeight ? '1' : '0'
188+
imageOverlay.style.height = `${targetHeight}px`;
189+
imageOverlay.style.opacity = `${progress}`;
190+
colorOverlay.style.height = `${targetHeight}px`;
191+
colorOverlay.style.opacity =
192+
targetHeight > headerMinHeight ? "1" : "0";
179193
toolbarBackground.style.backgroundColor =
180-
targetHeight > headerMinHeight ? 'transparent' : originalToolbarBgColor
194+
targetHeight > headerMinHeight
195+
? "transparent"
196+
: originalToolbarBgColor;
181197

182198
// .bar-buttons
183199
if (barButtons) {
184200
if (targetHeight > headerMinHeight) {
185-
imageOverlay.append(barButtons)
201+
imageOverlay.append(barButtons);
186202
Array.from(barButtons.children).forEach((btn) => {
187-
const htmlBtn = btn as HTMLElement
188-
htmlBtn.style.color = titleColor
189-
})
203+
const htmlBtn = btn as HTMLElement;
204+
htmlBtn.style.color = titleColor;
205+
});
190206
} else {
191-
toolbar.append(barButtons)
207+
toolbar.append(barButtons);
192208
Array.from(barButtons.children).forEach((btn) => {
193-
const htmlBtn = btn as HTMLElement
194-
htmlBtn.style.color = 'unset'
195-
})
209+
const htmlBtn = btn as HTMLElement;
210+
htmlBtn.style.color = "unset";
211+
});
196212
}
197213
}
198-
})
214+
});
199215
}
200-
setTicking(true)
201-
})
216+
setTicking(true);
217+
});
202218
}
203219
}
204-
}
220+
};
205221

206222
return {
207223
ref,
208-
}
209-
}
224+
};
225+
}

0 commit comments

Comments
 (0)