Animated SVG elements on scroll
Project Links
This set script will look for all elements with the .animated-swoop class and guage its position on the page and percentage scrolled and perform a CSS
transform on the element in order to flatten out the curve in the SVG as you scroll down. This class can be changed to anything you want, but make sure you
globally replace it in the following scripts:
HTML
<div class="twoColumnSub__container swoop-bottom animate-swoop wide remove-blank hero__subpage-banner">
<div class="container-fluid pr-lg-0">
<div class="row d-lg-flex flex-lg-nowrap position-relative">
<div class="twoColumnSub__content hero__subpage-content position-lg-absolute w-100 h-100 mb-0 mb-lg-0 order-lg-1 d-flex align-items-center banner-mobile-swoop">
<div class="container">
<div class="row">
<div class="col-lg-5 mb-lg-10 pb-2 pt-4 py-lg-0 pr-lg-5">
<h1 class="h2 page-title">Subpage Title</h1>
<div data-content-block="bannerContent" data-content="content" data-editable="editable" class="content alt">
<p>We all have reasons to start saving. Invest in your future today.</p><br /><br />
<a href="https://www.google.com" class="btn btn-primary">Compare Savings Accounts</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6 offset-lg-6 twoColumnSub__image hero__subpage-image center-crop-parent bg-default px-lg-0 order-lg-0">
<div data-content-block="bannerImage" data-content="content" data-editable="editable" class="content center-crop">
<img src="https://picsum.photos/id/7/850/580" alt="Slide 1">
</div>
</div>
</div>
</div>
<div class="after animator"><svg viewBox="0 0 1440 155" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M 1387.7 59.6835C 1288.67 70.0243 1058.07 83.1032 774.314 26.3001C 380.736 -45.3088 0 52.0071 0 52.0071V 155H 1440V 52.9393L 1387.7 59.6835Z" fill="currentColor"></path>
</svg></div>
</div>
CSS
/* styles for demo only */
.twoColumnSub {
&__container {
background:#c0c0c0
}
&__content {
left:0;
top:0;
bottom:0;
right:0;
position:absolute;
z-index:10;
}
&__image {
.content {
min-height:749px;
}
&.border-right {
border-right:15px solid #ffffff!important;
}
}
&__container {
overflow:hidden;
}
}
.swoop-top,.swoop-bottom {
position:relative;
.before, .after {
pointer-events: none;
position:absolute;
left:0;
right:0;
z-index:9;
color:#ffffff;
&.animator {
transform-origin: 50% 100%;
will-change: transform;
}
}
$behind-offset: 150px;
&.behind {
margin-top:$behind-offset;
overflow-y:visible!important;
.before {
z-index:3;
}
.content {
margin-top:-($behind-offset);
position:relative;
z-index:4;
}
}
&.flip-x-bottom {
.after {
transform:scale(-1,1);
}
}
&.flip-x-top {
.before {
transform:rotate(180deg) scale(-1,1);
}
}
}
.swoop-top {
.before {
top:-20px;
content:"";
transform:rotate(180deg);
}
}
.swoop-bottom {
.after {
content:"";
bottom:-20px;
}
}
.spacer {
padding-block:100px;
}
/*styles required for effect */
.animate-swoop {
.before,.after {
transition: all 0.05s ease-in;
&.animator {
transform-origin: 50% 100%;
will-change: transform;
}
}
}
Javascript (Vanilla, ES6)
var OnScreenPercentage = function(querySelector, callback){
var self = this;
this.callback = callback;
this.elements = querySelector?querySelector:[];
this.remove = function(){
if(this.handler){
window.removeEventListener("scroll", this.handler);
}
}
var calcTop = function(rect, win){
return Math.max(rect.height+rect.y, 0)/rect.height;
}
var calcBottom = function(rect, win){
return Math.max(win.height-rect.y, 0)/rect.height;
}
var calcPercentages = function(){
var win = {height: window.innerHeight};
for(var e=0; e<self.elements.length; ++e){
var rect = self.elements[e].getBoundingClientRect();
self.callback({
element: self.elements[e],
percentage: rect.y<0 ? calcTop(rect, win) : (rect.y+rect.height)>win.height ? calcBottom(rect, win) : 1,
location: rect.y<0 ? 'top' : (rect.y+rect.height)>win.height ? 'bottom' : 'middle'
});
}
}
this.handler = window.addEventListener('scroll', function() {
calcPercentages()
});
calcPercentages();
}
var onScreen = new OnScreenPercentage(document.querySelectorAll('.animate-swoop'), function(data){
var percent = data.element.querySelector('.animator');
percent.style.transform = `translate3d(0px, 0px, 0px) scale(1, ${data.percentage})`
});