From 3ad73ad7d9ec19a5872a9c54a940cb55cbaea26f Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sun, 6 Dec 2020 23:54:58 +0900
Subject: [PATCH] =?UTF-8?q?=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?=
 =?UTF-8?q?=E7=AD=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/client/pages/about-misskey.vue | 87 ++++++++++++++++++++++++------
 src/client/scripts/physics.ts      | 14 ++---
 2 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/src/client/pages/about-misskey.vue b/src/client/pages/about-misskey.vue
index bdda2e2533..8da5a1f698 100644
--- a/src/client/pages/about-misskey.vue
+++ b/src/client/pages/about-misskey.vue
@@ -2,12 +2,12 @@
 <div style="overflow: hidden;">
 	<FormBase class="znqjceqz">
 		<div id="debug"></div>
-		<section class="_formItem">
-			<div class="_formPanel" style="text-align: center; padding: 16px;" ref="about">
-				<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;" ref="icon" @load="iconLoaded" draggable="false"/>
-				<div style="margin: 0.75em auto 0 auto; width: max-content;">Misskey</div>
-				<div style="margin: 0 auto; opacity: 0.5; width: max-content;">v{{ version }}</div>
-				<span v-for="emoji in easterEggEmojis" :key="emoji.emoji" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }" :style="{ position: 'absolute', top: emoji.top, left: emoji.left, userSelect: 'none' }"><MkEmoji style="pointer-events: none; font-size: 24px; width: 24px;" :emoji="emoji.emoji" :custom-emojis="$store.state.instance.meta.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span>
+		<section class="_formItem about">
+			<div class="_formPanel panel" :class="{ playing: easterEggEngine != null }" ref="about">
+				<img src="/assets/icons/512.png" alt="" class="icon" ref="icon" @load="iconLoaded" draggable="false"/>
+				<div class="misskey">Misskey</div>
+				<div class="version">v{{ version }}</div>
+				<span class="emoji" v-for="emoji in easterEggEmojis" :key="emoji.id" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :custom-emojis="$store.state.instance.meta.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span>
 			</div>
 		</section>
 		<section class="_formItem" style="text-align: center; padding: 0 16px;" @click="gravity">
@@ -127,17 +127,6 @@ export default defineComponent({
 		}
 	},
 
-	created() {
-		const emojis = this.$store.state.settings.reactions;
-		for (let i = 0; i < 32; i++) {
-			this.easterEggEmojis.push({
-				top: -(32 + (Math.random() * 256)) + 'px',
-				left: (Math.random() * 99) + '%',
-				emoji: emojis[Math.floor(Math.random() * emojis.length)],
-			});
-		}
-	},
-
 	mounted() {
 		VanillaTilt.init(this.$refs.icon, {
 			max: 30,
@@ -155,6 +144,17 @@ export default defineComponent({
 
 	methods: {
 		iconLoaded() {
+			const emojis = this.$store.state.settings.reactions;
+			const containerWidth = this.$refs.about.offsetWidth;
+			for (let i = 0; i < 32; i++) {
+				this.easterEggEmojis.push({
+					id: i.toString(),
+					top: -(128 + (Math.random() * 256)),
+					left: (Math.random() * containerWidth),
+					emoji: emojis[Math.floor(Math.random() * emojis.length)],
+				});
+			}
+
 			this.$nextTick(() => {
 				this.easterEggReady = true;
 			});
@@ -175,5 +175,58 @@ export default defineComponent({
 	max-width: 800px;
 	box-sizing: border-box;
 	margin: 0 auto;
+
+	> .about {
+		> .panel {
+			position: relative;
+			text-align: center;
+			padding: 16px;
+
+			&.playing {
+				&, * {
+					user-select: none;
+				}
+
+				* {
+					will-change: transform;
+				}
+
+				> .emoji {
+					visibility: visible;
+				}
+			}
+
+			> .icon {
+				display: block;
+				width: 100px;
+				margin: 0 auto;
+				border-radius: 16px;
+			}
+
+			> .misskey {
+				margin: 0.75em auto 0 auto;
+				width: max-content;
+			}
+
+			> .version {
+				margin: 0 auto;
+				width: max-content;
+				opacity: 0.5;
+			}
+
+			> .emoji {
+				position: absolute;
+				top: 0;
+				left: 0;
+				visibility: hidden;
+
+				> .emoji {
+					pointer-events: none;
+					font-size: 24px;
+					width: 24px;
+				}
+			}
+		}
+	}
 }
 </style>
diff --git a/src/client/scripts/physics.ts b/src/client/scripts/physics.ts
index 8f452dfc53..0366de96e7 100644
--- a/src/client/scripts/physics.ts
+++ b/src/client/scripts/physics.ts
@@ -58,18 +58,21 @@ export function physics(container: HTMLElement) {
 	const objEls = Array.from(container.children);
 	const objs = [];
 	for (const objEl of objEls) {
+		const left = objEl.dataset.physicsX ? parseInt(objEl.dataset.physicsX) : objEl.offsetLeft;
+		const top = objEl.dataset.physicsY ? parseInt(objEl.dataset.physicsY) : objEl.offsetTop;
+
 		let obj;
 		if (objEl.classList.contains('_physics_circle_')) {
 			obj = Matter.Bodies.circle(
-				objEl.offsetLeft + (objEl.offsetWidth / 2),
-				objEl.offsetTop + (objEl.offsetHeight / 2),
+				left + (objEl.offsetWidth / 2),
+				top + (objEl.offsetHeight / 2),
 				Math.max(objEl.offsetWidth, objEl.offsetHeight) / 2,
 			);
 		} else {
 			const style = window.getComputedStyle(objEl);
 			obj = Matter.Bodies.rectangle(
-				objEl.offsetLeft + (objEl.offsetWidth / 2),
-				objEl.offsetTop + (objEl.offsetHeight / 2),
+				left + (objEl.offsetWidth / 2),
+				top + (objEl.offsetHeight / 2),
 				objEl.offsetWidth,
 				objEl.offsetHeight,
 				{
@@ -106,8 +109,6 @@ export function physics(container: HTMLElement) {
 		objEl.style.top = 0;
 		objEl.style.left = 0;
 		objEl.style.margin = 0;
-		objEl.style.userSelect = 'none';
-		objEl.style.willChange = 'transform';
 	}
 
 	window.requestAnimationFrame(update);
@@ -122,7 +123,6 @@ export function physics(container: HTMLElement) {
 			const x = (obj.position.x - objEl.offsetWidth / 2);
 			const y = (obj.position.y - objEl.offsetHeight / 2);
 			const angle = obj.angle;
-
 			objEl.style.transform = `translate(${x}px, ${y}px) rotate(${angle}rad)`;
 		}