File size: 6,098 Bytes
b455d0c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
var Sakura = function Sakura(selector, options) {
var _this = this;
if (typeof selector === 'undefined') {
throw new Error('No selector present. Define an element.');
}
this.el = document.querySelector(selector); // Defaults for the option object, which gets extended below.
var defaults = {
className: 'sakura',
// Classname of the petal. This corresponds with the css.
fallSpeed: 1,
// Speed factor in which the petal falls.
maxSize: 14,
// The maximum size of the petal.
minSize: 10,
// The minimum size of the petal.
delay: 300,
// Delay between petals.
gradientColorStart: 'rgba(255, 183, 197, 0.9)',
// Gradient color start (rgba).
gradientColorEnd: 'rgba(255, 197, 208, 0.9)',
// Gradient color end (rgba).
gradientColorDegree: 120 // Gradient degree angle.
}; // Merge defaults with user options.
var extend = function extend(originalObj, newObj) {
Object.keys(originalObj).forEach(function (key) {
if (newObj && Object.prototype.hasOwnProperty.call(newObj, key)) {
var origin = originalObj;
origin[key] = newObj[key];
}
});
return originalObj;
};
this.settings = extend(defaults, options); // Hide horizontal scrollbars on the target element.
this.el.style.overflowX = 'hidden'; // Random array element
function randomArrayElem(arr) {
return arr[Math.floor(Math.random() * arr.length)];
} // Random integer
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
} // Check for animation events.
var prefixes = ['webkit', 'moz', 'MS', 'o', ''];
function PrefixedEvent(element, type, callback) {
for (var p = 0; p < prefixes.length; p += 1) {
var animType = type;
if (!prefixes[p]) {
animType = type.toLowerCase();
}
element.addEventListener(prefixes[p] + animType, callback, false);
}
} // Check if the element is in the viewport.
function elementInViewport(el) {
var rect = el.getBoundingClientRect();
return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
}
this.createPetal = function () {
if (_this.el.dataset.sakuraAnimId) {
setTimeout(function () {
window.requestAnimationFrame(_this.createPetal);
}, _this.settings.delay);
} // Name the animations. These have to match the animations in the CSS file.
var animationNames = {
blowAnimations: ['blow-soft-left', 'blow-medium-left', 'blow-soft-right', 'blow-medium-right'],
swayAnimations: ['sway-0', 'sway-1', 'sway-2', 'sway-3', 'sway-4', 'sway-5', 'sway-6', 'sway-7', 'sway-8']
}; // Get one random animation of each type and randomize fall time of the petals
var blowAnimation = randomArrayElem(animationNames.blowAnimations);
var swayAnimation = randomArrayElem(animationNames.swayAnimations);
var fallTime = (document.documentElement.clientHeight * 0.007 + Math.round(Math.random() * 5)) * _this.settings.fallSpeed; // Create animations
var animationsArr = ["fall ".concat(fallTime, "s linear 0s 1"), "".concat(blowAnimation, " ").concat((fallTime > 30 ? fallTime : 30) - 20 + randomInt(0, 20), "s linear 0s infinite"), "".concat(swayAnimation, " ").concat(randomInt(2, 4), "s linear 0s infinite")];
var animations = animationsArr.join(', '); // Create petal and give it a random size.
var petal = document.createElement('div');
petal.classList.add(_this.settings.className);
var height = randomInt(_this.settings.minSize, _this.settings.maxSize);
var width = height - Math.floor(randomInt(0, _this.settings.minSize) / 3);
petal.style.background = "linear-gradient(".concat(_this.settings.gradientColorDegree, "deg, ").concat(_this.settings.gradientColorStart, ", ").concat(_this.settings.gradientColorEnd, ")");
petal.style.webkitAnimation = animations;
petal.style.animation = animations;
petal.style.borderRadius = "".concat(randomInt(_this.settings.maxSize, _this.settings.maxSize + Math.floor(Math.random() * 10)), "px ").concat(randomInt(1, Math.floor(width / 4)), "px");
petal.style.height = "".concat(height, "px");
petal.style.left = "".concat(Math.random() * document.documentElement.clientWidth - 100, "px");
petal.style.marginTop = "".concat(-(Math.floor(Math.random() * 20) + 15), "px");
petal.style.width = "".concat(width, "px"); // Remove petals of which the animation ended.
PrefixedEvent(petal, 'AnimationEnd', function () {
if (!elementInViewport(petal)) {
petal.remove();
}
}); // Remove petals that float out of the viewport.
PrefixedEvent(petal, 'AnimationIteration', function () {
if (!elementInViewport(petal)) {
petal.remove();
}
}); // Add the petal to the target element.
_this.el.appendChild(petal);
};
this.el.setAttribute('data-sakura-anim-id', window.requestAnimationFrame(this.createPetal));
};
Sakura.prototype.start = function () {
var animId = this.el.dataset.sakuraAnimId;
if (!animId) {
this.el.setAttribute('data-sakura-anim-id', window.requestAnimationFrame(this.createPetal));
} else {
throw new Error('Sakura is already running.');
}
};
Sakura.prototype.stop = function () {
var _this2 = this;
var graceful = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var animId = this.el.dataset.sakuraAnimId;
if (animId) {
window.cancelAnimationFrame(animId);
this.el.setAttribute('data-sakura-anim-id', '');
} // Remove all current blossoms at once.
// You can also set 'graceful' to true to stop new petals from being created.
// This way the petals won't be removed abruptly.
if (!graceful) {
setTimeout(function () {
var petals = document.getElementsByClassName(_this2.settings.className);
while (petals.length > 0) {
petals[0].parentNode.removeChild(petals[0]);
}
}, this.settings.delay + 50);
}
}; |