I created an SVG animation that simulates turning a page in the book. And in Mozilla it's great, the Chrome and Opera browsers are the problem. Someone to help me optimize the animation to make it more fluid in Chrome?
This is the code ( also available in Codepen ):
/*!
* classie - class helper functions
* from bonzo https://github.com/ded/bonzo
*
* classie.has( elem, 'my-class' ) -> true/false
* classie.add( elem, 'my-new-class' )
* classie.remove( elem, 'my-unwanted-class' )
* classie.toggle( elem, 'my-class' )
*/
/*jshint browser: true, strict: true, undef: true */
/*global define: false */
(function(window) {
'use strict';
// class helper functions from bonzo https://github.com/ded/bonzo
function classReg(className) {
return new RegExp("(^|\s+)" + className + "(\s+|$)");
}
// classList support for class management
// altho to be fair, the api sucks because it won't accept multiple classes at once
var hasClass, addClass, removeClass;
if ('classList' in document.documentElement) {
hasClass = function(elem, c) {
return elem.classList.contains(c);
};
addClass = function(elem, c) {
elem.classList.add(c);
};
removeClass = function(elem, c) {
elem.classList.remove(c);
};
} else {
hasClass = function(elem, c) {
return classReg(c).test(elem.className);
};
addClass = function(elem, c) {
if (!hasClass(elem, c)) {
elem.className = elem.className + ' ' + c;
}
};
removeClass = function(elem, c) {
elem.className = elem.className.replace(classReg(c), ' ');
};
}
function toggleClass(elem, c) {
var fn = hasClass(elem, c) ? removeClass : addClass;
fn(elem, c);
}
var classie = {
// full names
hasClass: hasClass,
addClass: addClass,
removeClass: removeClass,
toggleClass: toggleClass,
// short names
has: hasClass,
add: addClass,
remove: removeClass,
toggle: toggleClass
};
// transport
if (typeof define === 'function' && define.amd) {
// AMD
define(classie);
} else {
// browser global
window.classie = classie;
}
})(window);
/**
* svgLoader.js v1.0.0
* http://www.codrops.com
*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2014, Codrops
* http://www.codrops.com
*/
;
(function(window) {
'use strict';
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
function SVGLoader(el, options) {
this.el = el;
this.options = extend({}, this.options);
extend(this.options, options);
this._init();
}
SVGLoader.prototype.options = {
speedIn: 500,
easingIn: mina.linear
}
SVGLoader.prototype._init = function() {
var s = Snap(this.el.querySelector('svg'));
this.path = s.select('path');
this.initialPath = this.path.attr('d');
var openingStepsStr = this.el.getAttribute('data-opening');
this.openingSteps = openingStepsStr ? openingStepsStr.split(';') : '';
this.openingStepsTotal = openingStepsStr ? this.openingSteps.length : 0;
if (this.openingStepsTotal === 0) return;
// if data-closing is not defined then the path will animate to its original shape
var closingStepsStr = this.el.getAttribute('data-closing') ? this.el.getAttribute('data-closing') : this.initialPath;
this.closingSteps = closingStepsStr ? closingStepsStr.split(';') : '';
this.closingStepsTotal = closingStepsStr ? this.closingSteps.length : 0;
this.isAnimating = false;
if (!this.options.speedOut) {
this.options.speedOut = this.options.speedIn;
}
if (!this.options.easingOut) {
this.options.easingOut = this.options.easingIn;
}
}
SVGLoader.prototype.show = function() {
if (this.isAnimating) return false;
this.isAnimating = true;
// animate svg
var self = this,
onEndAnimation = function() {
classie.addClass(self.el, 'pageload-loading');
};
this._animateSVG('in', onEndAnimation);
classie.add(this.el, 'show');
}
SVGLoader.prototype.hide = function() {
var self = this;
classie.removeClass(this.el, 'pageload-loading');
this._animateSVG('out', function() {
// reset path
self.path.attr('d', self.initialPath);
classie.removeClass(self.el, 'show');
self.isAnimating = false;
});
}
SVGLoader.prototype._animateSVG = function(dir, callback) {
var self = this,
pos = 0,
steps = dir === 'out' ? this.closingSteps : this.openingSteps,
stepsTotal = dir === 'out' ? this.closingStepsTotal : this.openingStepsTotal,
speed = dir === 'out' ? self.options.speedOut : self.options.speedIn,
easing = dir === 'out' ? self.options.easingOut : self.options.easingIn,
nextStep = function(pos) {
if (pos > stepsTotal - 1) {
if (callback && typeof callback == 'function') {
callback();
}
return;
}
self.path.animate({
'path': steps[pos]
}, speed, easing, function() {
nextStep(pos);
});
pos++;
};
nextStep(pos);
}
// add to global namespace
window.SVGLoader = SVGLoader;
})(window);
(function() {
var pageWrap = document.getElementById('pagewrap'),
pages = [].slice.call(pageWrap.querySelectorAll('div.container')),
currentPage = 0,
triggerLoading = [].slice.call(pageWrap.querySelectorAll('a.pageload-link')),
loader = new SVGLoader(document.getElementById('loader'), {
speedIn: 1000,
easingIn: mina.easeinout
});
function init() {
triggerLoading.forEach(function(trigger) {
trigger.addEventListener('click', function(ev) {
ev.preventDefault();
loader.show();
// after some time hide loader
setTimeout(function() {
loader.hide();
classie.removeClass(pages[currentPage], 'show');
// update..
currentPage = currentPage ? 0 : 1;
classie.addClass(pages[currentPage], 'show');
}, 2000);
});
});
}
init();
})();
.container {
display: none;
}
.container.show {
display: block;
}
.pageload-overlay {
position: fixed;
width: 100%;
height: 134%;
top: -112px;
left: 0;
visibility: hidden;
background-size: cover;
}
.pageload-overlay.show {
visibility: visible;
}
.pageload-overlay svg {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<div id="pagewrap" class="pagewrap">
<div class="container show" id="page-1">
<div class="column">
<p><a class="pageload-link" href="#page-2">Show Page Loader</a></p>
</div>
</div>
<!-- /container -->
<div class="container" id="page-2">
<section>
<p><a class="pageload-link" href="#page-1">Go back</a></p>
</section>
</div>
<!-- /container -->
<div id="loader" class="pageload-overlay" data-opening="M 0,0 c 0,0 63.5,-16.5 80,0 16.5,16.5 0,60 0,60 L 0,60 Z">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 80 60" preserveAspectRatio="none">
<defs>
<pattern id="img1" width="1" height="1">
<image href="https://images4.alphacoders.com/888/thumb-1920-8.jpg" x="0" y="0" width="100%" height="100%"/>
</pattern>
</defs>
<path d="M 0,0 c 0,0 -16.5,43.5 0,60 16.5,16.5 80,0 80,0 L 0,60 Z" fill="url(#img1)"/>
</svg>
</div>
<!-- /pageload-overlay -->
</div>
<!-- /pagewrap -->