devo-book/index.html
2021-08-04 14:38:48 -04:00

250 lines
5.5 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<style>
body
{
margin:0;
}
section
{
position:relative;
height: 100vh;
box-sizing: border-box;
}
nav
{
position:fixed;
right:50px;
bottom:50px;
z-index:10;
}
h2
{
width:500px;
margin:0 auto;
text-align:center;
}
h2[data-spy='true']
{
background:black;
color: white;;
}
</style>
</head>
<body>
<nav>
<a href="#top" >Top</a>
<a href="#order">Order</a>
<a href="#video">Video</a>
<a href="#about">About</a>
<a href="#specs">Specs</a>
<a href="#email">Sign-up</a>
</nav>
<section id="video">
<h2 data-spy="0.2|0.8">Videos</h2>
</section>
<section id="about">
<h2 data-spy="0.2|0.8">About</h2>
</section>
<section id="specs">
<h2 data-spy="0.2|0.8">Specs</h2>
</section>
<script>
var Time =
{
Jobs:[],
Stamp:false,
Queue:false,
Loop:false,
Add:function(inJob)
{
if(Time.Loop)
{
console.log("cannot modify queue while processing");
return;
}
if(!Time.Queue)
{
window.requestAnimationFrame(Time.Update);
}
Time.Queue = true;
Time.Jobs.push(inJob);
},
Remove:function(inJob)
{
if(Time.Loop)
{
console.log("cannot modify queue while processing");
return;
}
var index = Time.Jobs.indexOf(inJob);
if(index > -1)
{
Time.Jobs.splice(index, 1);
}
},
Update:function(inTimestamp)
{
var delta;
var i;
if(!Time.Stamp)
{
Time.Stamp = inTimestamp;
}
delta = inTimestamp - Time.Stamp;
Time.Stamp = inTimestamp;
Time.Loop = true;
for(i=0; i<Time.Jobs.length; i++)
{
if(Time.Jobs[i](delta) === false)
{
Time.Jobs.splice(i, 1);
i--;
}
}
Time.Loop = false;
if(Time.Jobs.length > 0)
{
window.requestAnimationFrame(Time.Update);
}
else
{
Time.Stamp = false;
Time.Queue = false;
}
}
};
function JobDuration(inDuration, inHandler, inDone)
{
var timeCurrent = 0;
var timeLimit = inDuration*1000;
var timeRelative = 0;
var timeMaxed = false;
return function(inDelta)
{
timeCurrent += inDelta;
timeMaxed = timeCurrent > timeLimit;
if(timeMaxed)
{
inHandler(1);
inDone();
return false;
}
return inHandler(timeCurrent / timeLimit);
};
}
document.querySelector("nav").addEventListener("click", function(inEvent)
{
var domHtml = document.querySelector("html");
var domGoal = document.querySelector(inEvent.target.getAttribute("href"));
var posStart = domHtml.scrollTop - 200;
var posRange = domGoal.getBoundingClientRect().top;
var evtTick = function(inProgress){ domHtml.scrollTop = posStart + posRange*Math.sqrt(1 - Math.pow(1-(inProgress), 2)); };
var evtDone = function(){ Spy.Resume(); };
Spy.Suspend();
Time.Add( JobDuration(0.4, evtTick, evtDone) );
inEvent.preventDefault();
});
</script>
<script>
var Spy =
{
Attribute:"data-spy",
Members:[],
Defaults:[0, 1, 0, 1],
Disabled:false,
Suspend:function()
{
Spy.Disabled = true;
},
Resume:function()
{
Spy.Disabled = false;
Spy.UpdateAll();
},
UpdateAll:function()
{
var i, member, aabb, top, bottom, left, right;
var visible;
if(Spy.Disabled){ return; }
for(i=0; i<Spy.Members.length; i++)
{
member = Spy.Members[i];
top = window.innerHeight * member.Bounds[0];
bottom = window.innerHeight * member.Bounds[1];
left = window.innerWidth * member.Bounds[2];
right = window.innerWidth * member.Bounds[3];
aabb = member.Element.getBoundingClientRect();
visible = (aabb.top < bottom && aabb.bottom > top) && (aabb.left < right && aabb.right > left);
if(visible != member.Visible)
{
member.Element.setAttribute(Spy.Attribute, visible);
member.Visible = visible;
member.Change(visible);
}
}
},
Create:function(inElement)
{
var j, bounds;
var attr;
var obj;
attr = inElement.getAttribute(Spy.Attribute)||"";
inElement.removeAttribute(Spy.Attribute);
bounds = attr.split("|");
for(j=0; j<Spy.Defaults.length; j++)
{
if(bounds[j])
{
bounds[j] = parseFloat(bounds[j]);
}
else
{
bounds[j] = Spy.Defaults[j];
}
}
obj = {
Element:inElement,
Bounds:bounds,
Visible:undefined,
Change:function(){}
};
Spy.Members.push(obj);
return obj;
},
CreateAll:function()
{
var i, elements;
elements = document.querySelectorAll("*["+Spy.Attribute+"]");
for(i=0; i<elements.length; i++)
{
Spy.Create(elements[i]);
}
},
Init:function()
{
Spy.CreateAll();
Spy.UpdateAll();
document.addEventListener("scroll", Spy.UpdateAll, {passive:true});
window.addEventListener("resize", Spy.UpdateAll, {passive:true});
}
};
Spy.Init();
</script>
</body>
</html>