devo-book/index.html
2021-08-04 16:51:40 -04:00

329 lines
9.0 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<style>
body
{
margin:0;
}
section
{
position:relative;
height: 100vh;
box-sizing: border-box;
padding:50px;
}
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>
<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;
}
}
};
</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});
}
};
</script>
</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="order">
<style>
.shot3d
{
position: relative;
height: 350px;
width: 350px;
margin-left: 60px;
border: 1px solid blue;
perspective: 400px;
perspective-origin: 50% 50%;
}
.shot3d img
{
position:relative;
width:100%;
height:auto;
transform-style: preserve-3d;
transform: rotateX(-15deg);
}
.shot3d::before
{
position:absolute;
content:" ";
top:100%;
left:0%;
width:100%;
height:100px;
background:red;
transform-style: preserve-3d;
transform-origin: top center;
transform: rotateX(90deg) translateY(-50px);
}
</style>
<div class="shot3d">
<img src="https://truthforlife.org/static/images/productimage-picture-encore-2021-9729.jpg"/>
</div>
<h2 data-spy="0.2|0.8">Order</h2>
<h3>Truth For Life</h3>
<h4>365 Daily Devotionals</h4>
<h5>by Alistair Begg</h5>
<p>
Duis augue neque, dignissim at diam ac, mattis cursus justo. Morbi blandit in ligula eu scelerisque.
Maecenas hendrerit eu nunc non molestie. Vivamus augue enim, egestas a magna vitae, consequat facilisis urna.
Nullam semper ligula in est tincidunt, vel fringilla nunc vehicula. Nam tempus pellentesque ante, nec iaculis nisi porta id.
Ut aliquet purus nec mi egestas ornare.
</p>
<a href="https://truthforlife.org/store/buy/">Buy Now</a>
<span>$10.00 (free shipping)</span>
</section>
<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>
<p>
Duis augue neque, dignissim at diam ac, mattis cursus justo. Morbi blandit in ligula eu scelerisque.
Maecenas hendrerit eu nunc non molestie. Vivamus augue enim, egestas a magna vitae, consequat facilisis urna.
Nullam semper ligula in est tincidunt, vel fringilla nunc vehicula. Nam tempus pellentesque ante, nec iaculis nisi porta id.
Ut aliquet purus nec mi egestas ornare.
</p>
<ul>
<li>
<strong>Head</strong><p>Nam tempus pellentesque ante, nec iaculis nisi porta id.</p>
</li>
<li>
<strong>Hands</strong><p>Vivamus augue enim, egestas a magna vitae, consequat facilisis urna.</p>
</li>
<li>
<strong>Heart</strong><p>Morbi blandit in ligula eu scelerisque. Maecenas hendrerit eu nunc non molestie.</p>
</li>
</ul>
<a href="#">Look Inside</a>
</section>
<section id="specs">
<h2 data-spy="0.2|0.8">Specs</h2>
</section>
<section id="email">
<h2 data-spy="0.2|0.8">Sign Up</h2>
</section>
<script>
Spy.Init();
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;
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>
</body>
</html>