import imagesLoaded from "imagesloaded"
import {Scene} from "./scene"
let scene
// helper functions
const MathUtils = {
// map number x from range [a, b] to [c, d]
map: (x, a, b, c, d) => ((x - a) * (d - c)) / (b - a) + c,
// linear interpolation
lerp: (a, b, n) => (1 - n) * a + n * b
};
// body element
const wrapper = document.querySelector('.pic-wrapper')
let IMAGES
// calculate the viewport size
let winsize;
const calcWinsize = () =>
(winsize = { width: window.innerWidth, height: window.innerHeight });
calcWinsize();
// and recalculate on resize
window.addEventListener("resize", calcWinsize);
window.onbeforeunload = function() {
window.scrollTo(0, 0);
};
// scroll position and update function
let docScroll;
const getPageYScroll = () =>
(docScroll = window.pageYOffset || document.documentElement.scrollTop)
window.addEventListener("scroll", getPageYScroll)
// Item
function Item (el, scroll) {
let DOM = { el: el.img }
let currentScroll = docScroll
let animated = false
let isBeingAnimatedNow = false
let shouldRollBack = false
let shouldUnRoll = false
let positions = []
const bounds = DOM.el.getBoundingClientRect()
const fromTop = bounds.top
const windowHeight = window.innerHeight
const withoutHeight = fromTop - windowHeight
const withHeight = fromTop + bounds.height
let insideTop = withoutHeight - docScroll
let insideRealTop = fromTop + docScroll
let insideBottom = withHeight - docScroll + 50
let width = bounds.width
let height = bounds.height
let left = bounds.left
let src = document.getElementById('picture')
let mesh = scene.createMesh({
width: width,
height: height,
src: src,
image: DOM.el,
iWidth: DOM.el.width,
iHeight: DOM.el.height
})
scene.scene.add(mesh)
// use the IntersectionObserver API to check when the element is inside the viewport
// only then the element translation will be updated
let options = {
root: null,
rootMargin: "0px",
threshold: [0, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
}
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
positions.push(entry.boundingClientRect.y)
let compareArray = this.positions.slice(
positions.length - 2,
positions.length
);
let down = compareArray[0] > compareArray[1]
let isVisible = entry.intersectionRatio > 0.0
let shouldRollBack = false
let shouldUnRoll = false
if (
entry.intersectionRatio < 0.5 &&
entry.boundingClientRect.y > 0 &&
isVisible &&
!down
) {
shouldRollBack = true
}
if (
entry.intersectionRatio > 0.5 &&
entry.boundingClientRect.y > 0 &&
isVisible
) {
shouldUnRoll = true
}
console.log(isVisible, 'vis')
mesh.visible = isVisible
})
}, options)
observer.observe(DOM.el)
function resize() {
// on resize rest sizes and update the translation value
mesh.scale.set(width, height, 200)
render(scroll.renderedStyles.translationY.current)
scroll.shouldRender = true
}
// init/bind events
window.addEventListener("resize", () => resize())
function render(s) {
currentScroll = s
mesh.position.y = currentScroll + winsize.height / 2 - insideRealTop - height / 2
mesh.position.x = 0 - winsize.width / 2 + left + width / 2
}
render(0)
}
function SmoothScroll() {
let shouldRender = false
// the <main> element
let DOM = { main: document.querySelector(".pic-main") };
// the scrollable element
// we translate this element when scrolling (y-axis)
DOM.scrollable = DOM.main.querySelector(".scrollable");
// the items on the page
let items = [];
IMAGES.forEach(image => {
if (image.img.classList.contains("js-image")) {
items.push(new Item(image, this))
}
})
document.addEventListener('mousemove',()=>{
shouldRender = true
})
// here we define which property will change as we scroll the page
// in this case we will be translating on the y-axis
// we interpolate between the previous and current value to achieve the smooth scrolling effect
let renderedStyles = {
translationY: {
// interpolated value
previous: 0,
// current value
current: 0,
// amount to interpolate
ease: 0.1,
// current value setter
// in this case the value of the translation will be the same like the document scroll
setValue: () => docScroll
}
}
// set the body's height
function setSize() {
wrapper.style.height = `${DOM.scrollable.scrollHeight}px`
}
setSize()
// set the initial values
for (const key in renderedStyles) {
renderedStyles[key].current = renderedStyles[key].previous = renderedStyles[key].setValue()
}
setPosition()
shouldRender = true
// translate the scrollable element
function setPosition() {
if (
Math.round(renderedStyles.translationY.previous) !==
Math.round(renderedStyles.translationY.current) ||
renderedStyles.translationY.previous < 10
) {
shouldRender = true;
DOM.scrollable.style.transform = `translate3d(0,${-1 * renderedStyles.translationY.previous}px,0)`
for (const item of items) {
if (item.isVisible || item.isBeingAnimatedNow) {
item.render(renderedStyles.translationY.previous);
}
}
}
if(scene.targetSpeed > 0.01) shouldRender = true
if (shouldRender) {
shouldRender = false
scene.render()
}
}
// the <main> element's style needs to be modified
DOM.main.style.position = "fixed"
DOM.main.style.width = DOM.main.style.height = "100%"
DOM.main.style.top = DOM.main.style.left = 0
DOM.main.style.overflow = "hidden"
// init/bind events
window.addEventListener("resize", () => setSize());
// start the render loop
requestAnimationFrame(() => render())
function render() {
// update the current and interpolated values
for (const key in renderedStyles) {
renderedStyles[key].current = renderedStyles[key].setValue()
renderedStyles[key].previous = MathUtils.lerp(
renderedStyles[key].previous,
renderedStyles[key].current,
renderedStyles[key].ease
)
}
// and translate the scrollable element
setPosition()
// loop..
requestAnimationFrame(() => render())
}
}
/***********************************/
/********** Preload stuff **********/
export const pictureAnimation = () => {
const preloadImages = new Promise((resolve, reject) => {
imagesLoaded(document.getElementById("picture"), { background: true }, resolve);
});
preloadImages.then(images => {
IMAGES = images.images
})
console.log(IMAGES)
const preloadEverything = [preloadImages]
// And then..
Promise.all(preloadEverything).then(() => {
// Remove the loader
// Get the scroll position
getPageYScroll()
// Initialize the Smooth Scrolling
let container = document.querySelector(".pic-container")
scene = new Scene(container)
new SmoothScroll()
})
}
I wanted to use your code in react project, I changed somethings, but it ain't working....
this is the changed scene.js :
this is the changed app.js:
I don't know what to do