我已经编写了第一段代码,我认为它实际上可以重用并且可能对其他人有用。代码是一些css,一些javascript类和一些js函数。
要使用该软件包,请设置一些HTML,然后传递html元素和可选参数,例如:
dom = new DOM(document.getElementById('fullScreenWrapper'), 175),
我想以某种方式打包它,以便你基本上包含一个js文件,一个css文件,然后你可以在任何项目中使用它。 jQuery有一个扩展自己的设计模式,但我不使用jQuery。对于像这样的东西,有没有最佳实践?
这是模型,未打包:
<html>
<head>
<style>
/* specific styles */
&:root {--scrollPosition:0}
.flicWrapper{
height: calc(var(--wrapperHeight));
}
.flicWrapper .flicChild{
top: calc(var(--previousHeight));
position: fixed;
}
.flicWrapper.transition{
height: initial;
}
.flicWrapper.transition .flicChild{
transition: transform .3s cubic-bezier(0, 0, 0.25, 1);
}
.flicWrapper .before{
transform: translate3d(0,calc((var(--previousHeight)*-1)),0);
}
.flicWrapper .active{
transform: translate3d(0, calc((var(--previousHeight)*-1) + var(--stickyScrollPosition)), 0);
}
.flicWrapper .next{
transform: translate3d(0, calc(var(--scrollPosition)), 0);
}
/*custom style*/
body{
margin: 0;
}
section{
width: 100%;
height: 100%;
}
.s1{
height: 100%;
background: repeating-linear-gradient(
45deg,
red,
red 10px,
blue 10px,
blue 20px
);
}
.s2{
height: 150%;
background: repeating-linear-gradient(
45deg,
#606dbc,
#606dbc 10px,
#465298 10px,
#465298 20px
);
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="fullScreenWrapper" id="fullScreenWrapper">
<section class="s1" ></section>
<section class="s2"></section>
<section class="s3" style="background: red";></section>
<section class="s4" style="background: green";></section>
<section class="s5" style="background: black";></section>
</div>
<script type="text/javascript">
var State = class {
constructor(heights, offset) {
this.breakingPoints = heights;
this.offset = offset;
this.state = this.currentState;
}
get currentState(){
return this.breakingPoints.findIndex((elm, i, arr)=> {
if(window.scrollY >= arr[i] && window.scrollY < arr[i+1] ){
return[i]
}
})
}
get update(){
var isUpdated = Math.sign( this.currentState - this.state)
this.state += isUpdated;
return isUpdated !== 0
}
get snapPos() {
var offset = this.state ? this.offset : 0; // first state should not have offset.
return this.breakingPoints[this.state] + offset;
}
},
DOM = class {
constructor(wrapper, offset) {
this.wrapper = wrapper;
this.offset = offset
this.children = Array.from(wrapper.children);
this.childHeights = [];
this.scrollHeights = this.getScrollHeights;
this.wrapper.classList.add('flicWrapper')
setGlobalProperty('wrapperHeight', this.documentHeight)
//apply custom css-values
this.children.forEach((child, i) => {
child.classList.add('flicChild')
var height = 0
if(i > 0 ){
var height = this.children[i-1].offsetHeight;
}
child.style.setProperty('--previousHeight', height+'px');
this.childHeights.push(child.offsetHeight - window.innerHeight);
})
}
get getScrollHeights() {
var heights = [0];
//calculate al the heights
this.children.forEach((el, i) => {
var mod = 2;
if(i === 0 || i === this.children.length -1){mod = 1}; //first and last should only have one offset
var elheight = el.offsetHeight - window.innerHeight + this.offset * mod;
heights.push( elheight + heights[i] );
})
return heights;
}
get documentHeight() {return this.scrollHeights.slice(-1)[0]+window.innerHeight-1}
},
Scroll = class{
constructor(){
this.on = true;
}
throttle(fn, wait){
var time = Date.now();
return () => {
if ((time + wait - Date.now()) < 0 && this.on) {
fn();
time = Date.now();
}
}
}
},
scrollEvent = () => {
if(state.update){ //check state
scroll.on = false;
dom.wrapper.classList.add('transition')
setClasses();
setScrollPos(0, dom.childHeights[state.state]);
setTimeout(changeDone, 1200);
}
},
setClasses = () => {
var s = state.state;
dom.children.forEach((child, i) => {
let classes = child.classList;
classes.toggle('before', i < s);
classes.toggle('after', i > s);
classes.toggle('active', i === s);
classes.toggle('previous', i === s-1);
classes.toggle('next', i === s+1);
})
},
changeDone = () => {
dom.wrapper.classList.remove('transition');
window.scrollTo(0, state.snapPos);
scroll.on = true;
},
//helper
setGlobalProperty = (name, value) => {
document.documentElement.style.setProperty('--'+name, (value+'px'))
},
setScrollPos = (pos, max) => {
setGlobalProperty('scrollPosition', -pos)
setGlobalProperty('stickyScrollPosition', (Math.min(pos, max)*-1))
},
dom = new DOM(document.getElementById('fullScreenWrapper'), 175),
state = new State(dom.scrollHeights, dom.offset),
scroll = new Scroll();
setClasses();
window.addEventListener('scroll', scroll.throttle(scrollEvent, 50));
window.addEventListener('scroll', scroll.throttle(() => {setScrollPos(window.scrollY - state.snapPos, dom.childHeights[state.state])}, 0))
</script>
</body>