#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;
		}
	}
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js