Генератор птиц
С помощью jаvascript генерируются летящие птицы с разным оперением, которые сами сделаны на чистом CSS
В демке с помощью шестеренки в углу можно вызвать панель для управления генерацией птиц.
В демке с помощью шестеренки в углу можно вызвать панель для управления генерацией птиц.
HTML
<div class="stage">
<button class="form-toggle settings-toggle">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" >
<path d="M23,13.4v-2.8l-3-0.8c-0.2-0.7-0.5-1.4-0.8-2l1.6-2.8l-1.9-1.9l-2.8,1.6c-0.6-0.4-1.3-0.7-2-0.8l-0.8-3h-2.8
L9.9,4c-0.7,0.2-1.4,0.5-2,0.8L5.1,3.3L3.3,5.1l1.6,2.8C4.5,8.5,4.2,9.2,4,9.9l-3,0.8v2.8l3,0.8c0.2,0.7,0.5,1.4,0.8,2l-1.6,2.8
l1.9,1.9l2.8-1.6c0.6,0.4,1.3,0.7,2,0.8l0.8,3h2.8l0.8-3c0.7-0.2,1.4-0.5,2-0.8l2.8,1.6l1.9-1.9l-1.6-2.8c0.4-0.6,0.7-1.3,0.8-2
L23,13.4z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S14.8,17,12,17z"/>
</svg>
</button>
<div class="settings-form hidden">
<button class="form-toggle close-toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<title>close-24x24</title>
<g id="_24x24">
<path d="M14.58,12l5.88-5.89a1.82,1.82,0,0,0-2.58-2.58L12,9.42,6.12,3.53A1.82,1.82,0,1,0,3.53,6.11L9.42,12,3.53,17.89a1.82,1.82,0,1,0,2.58,2.58L12,14.58l5.88,5.88a1.82,1.82,0,1,0,2.58-2.58Z"/>
</g>
</svg>
</button>
<div class="form-field-group">
<label>Spawn Rate</label>
<span>Slow</span>
<input class="inverted" type="range" min="50" max="2000" value="1000" data-name="spawnRate"/>
<span>Fast</span>
</div>
<div class="form-field-group">
<label>Flight Speed</label>
<span>Slow</span>
<input class="inverted" type="range" min="1" max="5" value="3" data-name="durationMultiple"/>
<span>Fast</span>
</div>
</div>
</div>
CSS
html, body {
width: 100%;
overflow: hidden;
box-sizing: border-box;
}
.stage {
display: flex;
align-items: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: visible;
background: linear-gradient(#69FFC5, #69fff7);
box-sizing: border-box;
}
.birb-container {
position: absolute;
top: 50%;
right: 100%;
transform-origin: left center;
animation: fly-by 2000ms linear;
}
.birb {
position: relative;
display: block;
width: 20vw;
height: 20vw;
animation: infinite altitude-variance 500ms ease;
}
.body {
position: absolute;
left: 0;
top: 20%;
width: 70%;
height: 40%;
border-bottom-right-radius: 50% 80%;
border-bottom-left-radius: 50% 80%;
box-shadow: inset -3vw -2vw 2vw rgba(0, 0, 20, 0.2);
-webkit-backface-visibility: hidden;
}
.body:after {
content: '';
display: block;
position: absolute;
left: -10%;
top: 35%;
width: 30%;
height: 30%;
border-radius: 0 0 100% 0;
background: linear-gradient(#f7c96e, #f7e06e);
}
.head-container {
position: relative;
left: 80%;
top: 0;
width: 50%;
height: 80%;
z-index: 1;
}
.head {
position: absolute;
width: 100%;
height: 100%;
border-radius: 0 100% 100% 100%;
box-shadow: inset -1vw -2vw 1vw rgba(0, 0, 10, 0.2);
z-index: 1;
-webkit-backface-visibility: hidden;
}
.head:before {
content: '';
display: block;
position: absolute;
left: 55%;
top: 35%;
width: 15%;
height: 15%;
border-radius: 100%;
background: rgba(82, 20, 20, 0.2);
z-index: 1;
}
.head:after {
content: '';
display: block;
position: absolute;
right: 10%;
bottom: 25%;
width: 50%;
height: 50%;
border-radius: 100%;
background: rgba(255, 255, 255, 0.25);
z-index: 2;
-webkit-backface-visibility: hidden;
}
.beak {
position: absolute;
left: 80%;
top: 20%;
width: 50%;
height: 70%;
background: #f7e06e;
box-shadow: inset -1vw -2vw 1vw #f7f76e;
border-radius: 0 100% 0 0;
z-index: -2;
}
.beak:after {
content: '';
display: block;
position: absolute;
left: -50%;
top: 100%;
width: 100%;
height: 20%;
border-radius: 0 0 100% 0;
background: #f7c96e;
z-index: -1;
-webkit-backface-visibility: hidden;
}
.wing-front {
position: absolute;
width: 60%;
height: 180%;
top: 0;
left: 25%;
transform-origin: top center;
border-radius: 0 0 100% 10%;
animation: infinite wing-front-flap 300ms ease;
z-index: 1;
}
.wing-back {
z-index: -2;
position: absolute;
width: 40%;
height: 130%;
top: 0;
left: 60%;
transform-origin: top center;
border-radius: 0 0 100% 10%;
animation: infinite wing-back-flap 300ms ease;
}
.tail {
position: absolute;
top: 0%;
right: 90%;
height: 35%;
width: 100%;
border-bottom-left-radius: 100% 100%;
transform: rotate(3deg);
transform-origin: top right;
}
@keyframes fly-by {
50% {
opacity: 1;
}
100% {
transform: translate(120vw, -30vh);
opacity: .1;
}
}
@keyframes altitude-variance {
50% {
transform: translate(0, 6%);
}
}
@keyframes wing-front-flap {
0%,100% {
transform: rotateX(10deg);
}
50% {
transform: rotateX(140deg);
}
}
@keyframes wing-back-flap {
0%,100% {
transform: rotateX(0deg);
}
50% {
transform: rotateX(-120deg);
}
}
.form-toggle {
display: block;
box-sizing: border-box;
border: none;
appearance: none;
padding: .5rem;
height: 2.5rem;
cursor: pointer;
background: none;
text-transform: uppercase;
font-family: 'Montserrat', sans-serif;
font-weight: 600;
color: #009c94;
border-radius: 4px;
letter-spacing: .1em;
fill: #009c94;
z-index: 2;
overflow: auto;
}
.settings-toggle {
position: absolute;
bottom: .5rem;
right: .5rem;
}
.close-toggle {
position: absolute;
top: 0;
right: 0;
}
.settings-form {
position: absolute;
right: .5rem;
bottom: 0;
left: .5rem;
z-index: 3;
background: rgba(255, 255, 255, 0.9);
padding: 2rem 1rem;
box-sizing: border-box;
position: absolute;
border-radius: 4px 4px 0 0;
transition: all 300ms ease;
font-family: 'Montserrat', sans-serif;
letter-spacing: .1em;
font-size: 1rem;
box-shadow: 0 4px 4px rgba(255, 255, 255, 0.25);
}
.settings-form.hidden {
transform: translateY(100%);
}
.form-field-group {
white-space: nowrap;
display: flex;
flex-wrap: wrap;
margin-bottom: .5rem;
max-width: 40rem;
margin: 0 auto 1rem;
text-transform: uppercase;
user-select: none;
}
.form-field-group label {
display: block;
width: 100%;
text-align: center;
margin-bottom: .5rem;
color: #009c94;
}
.form-field-group input {
display: block;
flex-grow: 1;
}
.form-field-group input.inverted {
transform: rotate(180deg);
}
.form-field-group span {
width: 4rem;
flex-shrink: 0;
text-align: center;
font-size: .75rem;
color: #009c94;
}
JS
// Settings and controls
var settings = {
spawnRate: 1000, // ms
minAnimationDuration: 400, // ms
maxAnimationDuration: 1000, // ms
durationMultiple: 3,
minSize: 5, // vw
maxSize: 25, // vw
saturation: 70, // %
lightness: 75 // %
};
var updateSetting = function updateSetting(e) {
var target = e.target;
var settingName = target.getAttribute('data-name');
settings[settingName] = parseInt(target.value);
console.log(settings);
};
var toggleSettingsMenu = function toggleSettingsMenu() {
var settingsMenu = document.querySelector('.settings-form');
settingsMenu.classList.contains('hidden') ? settingsMenu.classList.remove('hidden') : settingsMenu.classList.add('hidden');
};
var settingsToggle = document.querySelector('.settings-toggle');
settingsToggle.addEventListener('click', toggleSettingsMenu, false);
var closeToggle = document.querySelector('.close-toggle');
closeToggle.addEventListener('click', toggleSettingsMenu, false);
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++) {if (window.CP.shouldStopExecution(1)){break;}
inputs[i].addEventListener('change', updateSetting, false);
}
window.CP.exitedLoop(1);
// Helper functions
var getRandomHslColorObject = function getRandomHslColorObject() {
var colorObject = {
h: getRandomNumberInRange(0, 360),
s: settings.saturation,
l: settings.lightness
};
return colorObject;
};
var getRandomNumberInRange = function getRandomNumberInRange() {
var min = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
return '' + (Math.floor(Math.random() * (max - min)) + min);
};
// Birb stuff
var removeBirb = function removeBirb(e) {
var birb = e.target;
birb.parentElement.removeChild(birb);
};
var createBirb = function createBirb() {
var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { h: 100, s: 60, l: 100 };
var birbSize = getRandomNumberInRange(settings.minSize, settings.maxSize) + 'vw';
var birbContainer = document.createElement('div');
birbContainer.classList.add('birb-container');
birbContainer.style.top = getRandomNumberInRange(0, 100) + '%';
birbContainer.style.animationDuration = getRandomNumberInRange(settings.minAnimationDuration * settings.durationMultiple, settings.maxAnimationDuration * settings.durationMultiple) + 'ms';
birbContainer.addEventListener('animationend', removeBirb, false);
var birb = document.createElement('div');
birb.classList.add('birb');
birb.style.height = birbSize;
birb.style.width = birbSize;
birbContainer.appendChild(birb);
var body = document.createElement('div');
body.classList.add('body');
body.style.backgroundColor = 'hsl(' + color.h + ', ' + color.s + '%, ' + color.l + '%)';
birb.appendChild(body);
var headContainer = document.createElement('div');
headContainer.classList.add('head-container');
body.appendChild(headContainer);
var head = document.createElement('div');
head.classList.add('head');
head.style.backgroundColor = 'hsl(' + (color.h + 90) + ', ' + color.s + '%, ' + color.l + '%)';
headContainer.appendChild(head);
var beak = document.createElement('div');
beak.classList.add('beak');
headContainer.appendChild(beak);
var wingFront = document.createElement('div');
wingFront.classList.add('wing-front');
wingFront.style.backgroundColor = 'hsl(' + color.h + ', ' + color.s + '%, ' + (color.l - 10) + '%)';
body.appendChild(wingFront);
var wingBack = document.createElement('div');
wingBack.classList.add('wing-back');
wingBack.style.backgroundColor = 'hsl(' + color.h + ', ' + color.s + '%, ' + (color.l - 20) + '%)';
body.prepend(wingBack);
var tail = document.createElement('div');
tail.classList.add('tail');
tail.style.backgroundColor = 'hsl(' + color.h + ', ' + color.s + '%, ' + color.l + '%)';
body.appendChild(tail);
return birbContainer;
};
var makeBirbs = function makeBirbs() {
var birdCount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
for (var i = 0; i < birdCount; i++) {if (window.CP.shouldStopExecution(2)){break;}
var birbColorObject = getRandomHslColorObject();
var birbContainer = createBirb(birbColorObject);
var targetElement = document.querySelector('.stage');
targetElement.appendChild(birbContainer);
}
window.CP.exitedLoop(2);
setTimeout(makeBirbs, settings.spawnRate);
};
//Init stuff
makeBirbs();