#birds
.screen(
v-on:mousemove="flyBirds"
, v-on:touchstart="touchstartEvent"
, v-on:touchend="touchendEvent"
, v-on:touchmove="touchmoveEvent"
, v-on:touchcancel="touchcancelEvent"
)
.bird(
v-for="bird, index in birds"
, v-if="bird !== null"
, v-bind:class="bird.active === true ? 'active' : ''"
, v-bind:style="bird.style"
)
.wing.left
.wing.right
View Compiled
.screen {
background-image: url("https://assets.codepen.io/430361/Sunset.svg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
width: 100vw;
height: 100vh;
}
.bird {
width: var(--width);
height: var(--height);
position: absolute;
top: var(--top);
left: var(--left);
&.active {
transform:
rotate(var(--angle))
scale(0)
translate(var(--dist-x), var(--dist-y))
;
filter: blur(2vmin);
transition: transform 2000ms ease-out, filter 2000ms ease-out;
}
}
.wing {
--stroke: calc(var(--size) * 0.2);
--half-stroke: calc(var(--stroke) / 2);
width: 100%;
height: 100%;
border: solid var(--stroke) #000000;
border-bottom: none;
position: absolute;
top: 0;
box-sizing: border-box;
border-radius: 50% 50% 0% 0% / 100% 100% 0% 0%;
&.left {
left: calc(50% - var(--half-stroke));
transform-origin: left bottom;
animation: left-wing 512ms ease-out infinite;
}
&.right {
right: calc(50% - var(--half-stroke));
transform-origin: right bottom;
animation: right-wing 512ms ease-out infinite;
}
}
@keyframes left-wing {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(-45deg) skew(10deg, 30deg);
}
75% {
transform: rotate(45deg);
}
}
@keyframes right-wing {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(45deg) skew(-10deg, -30deg);
}
75% {
transform: rotate(-45deg);
}
}
View Compiled
new Vue({
el: "#birds",
data() {
return {
birds: [],
touchActive: false,
birdsTimer: null
}
},
methods: {
random(min, max) {
return Math.random() * (max - min) + min;
},
flyBirds(evt) {
const size = this.random(9, 1);
const distX = this.random(-40, 40);
const distY = this.random(-40, 40);
const angle = this.random(-55, 55);
const index = this.birds.length;
this.birds.push({
style: {
"--left": `${evt.clientX - (size * 2)}px`,
"--top": `${evt.clientY - (size * 2)}px`,
"--width": `${size}vmin`,
"--height": `${size / 2}vmin`,
"--dist-x": `${distX}vmin`,
"--dist-y": `${distY}vmin`,
"--angle": `${angle}deg`,
"--size": `${size}vmin`,
},
"active": false
});
setTimeout(() => {
this.birds[index].active = true;
}, 1);
clearTimeout(this.birdsTimer);
this.birdsTimer = setTimeout(() => {
this.birds = [];
}, 5000);
},
touchstartEvent(evt) {
this.touchActive = true;
},
touchendEvent(evt) {
this.touchActive = false;
},
touchmoveEvent(evt) {
if (this.touchActive === false) {
return;
}
for (const touch of evt.touches) {
this.flyBirds(touch);
}
},
touchcancelEvent(evt) {
this.touchActive = false;
}
}
});
This Pen doesn't use any external CSS resources.