summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2020-12-06 12:51:00 +0900
committersyuilo <syuilotan@yahoo.co.jp>2020-12-06 12:51:00 +0900
commit9a270e59a4a7189dbe956c2585ca1bdce60fc406 (patch)
treeebdb6ecaa55ca3885dea7088935e1f242095571f /src/client
parentAdd slideshow widget (diff)
downloadmisskey-9a270e59a4a7189dbe956c2585ca1bdce60fc406.tar.gz
misskey-9a270e59a4a7189dbe956c2585ca1bdce60fc406.tar.bz2
misskey-9a270e59a4a7189dbe956c2585ca1bdce60fc406.zip
:secret:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/pages/about-misskey.vue132
-rw-r--r--src/client/scripts/physics.ts168
2 files changed, 254 insertions, 46 deletions
diff --git a/src/client/pages/about-misskey.vue b/src/client/pages/about-misskey.vue
index 4e0e74bfa1..77922fc966 100644
--- a/src/client/pages/about-misskey.vue
+++ b/src/client/pages/about-misskey.vue
@@ -1,50 +1,54 @@
<template>
-<FormBase class="znqjceqz">
- <section class="_formItem">
- <div class="_formPanel" style="text-align: center; padding: 16px;">
- <img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;" ref="icon"/>
- <div style="margin-top: 0.75em;">Misskey</div>
- <div style="opacity: 0.5;">v{{ version }}</div>
- </div>
- </section>
- <section class="_formItem" style="text-align: center; padding: 0 16px;">
- {{ $t('_aboutMisskey.about') }}
- </section>
- <FormGroup>
- <FormLink to="https://github.com/syuilo/misskey" external>
- <template #icon><Fa :icon="faCode"/></template>
- {{ $t('_aboutMisskey.source') }}
- <template #suffix>GitHub</template>
- </FormLink>
- <FormLink to="https://crowdin.com/project/misskey" external>
- <template #icon><Fa :icon="faLanguage"/></template>
- {{ $t('_aboutMisskey.translation') }}
- <template #suffix>Crowdin</template>
- </FormLink>
- <FormLink to="https://www.patreon.com/syuilo" external>
- <template #icon><Fa :icon="faHandHoldingMedical"/></template>
- {{ $t('_aboutMisskey.donate') }}
- <template #suffix>Patreon</template>
- </FormLink>
- </FormGroup>
- <FormGroup>
- <template #label>{{ $t('_aboutMisskey.contributors') }}</template>
- <FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
- <FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
- <FormLink to="https://github.com/mei23" external>@mei23</FormLink>
- <FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
- <FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
- <FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
- <FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
- <FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
- <template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
- </FormGroup>
- <FormGroup>
- <template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
- <FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
- <template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
- </FormGroup>
-</FormBase>
+<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_" :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>
+ </div>
+ </section>
+ <section class="_formItem" style="text-align: center; padding: 0 16px;" @click="gravity">
+ {{ $t('_aboutMisskey.about') }}
+ </section>
+ <FormGroup>
+ <FormLink to="https://github.com/syuilo/misskey" external>
+ <template #icon><Fa :icon="faCode"/></template>
+ {{ $t('_aboutMisskey.source') }}
+ <template #suffix>GitHub</template>
+ </FormLink>
+ <FormLink to="https://crowdin.com/project/misskey" external>
+ <template #icon><Fa :icon="faLanguage"/></template>
+ {{ $t('_aboutMisskey.translation') }}
+ <template #suffix>Crowdin</template>
+ </FormLink>
+ <FormLink to="https://www.patreon.com/syuilo" external>
+ <template #icon><Fa :icon="faHandHoldingMedical"/></template>
+ {{ $t('_aboutMisskey.donate') }}
+ <template #suffix>Patreon</template>
+ </FormLink>
+ </FormGroup>
+ <FormGroup>
+ <template #label>{{ $t('_aboutMisskey.contributors') }}</template>
+ <FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
+ <FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
+ <FormLink to="https://github.com/mei23" external>@mei23</FormLink>
+ <FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
+ <FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
+ <FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
+ <FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
+ <FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
+ <template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
+ </FormGroup>
+ <FormGroup>
+ <template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
+ <FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
+ <template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
+ </FormGroup>
+ </FormBase>
+</div>
</template>
<script lang="ts">
@@ -57,6 +61,7 @@ import FormBase from '@/components/form/base.vue';
import FormGroup from '@/components/form/group.vue';
import FormKeyValueView from '@/components/form/key-value-view.vue';
import MkLink from '@/components/link.vue';
+import { physics } from '@/scripts/physics.ts';
import * as os from '@/os';
const patrons = [
@@ -115,10 +120,24 @@ export default defineComponent({
},
version,
patrons,
+ easterEggReady: false,
+ easterEggEmojis: [],
+ easterEggEngine: null,
faInfoCircle, faCode, faLanguage, faHandHoldingMedical,
}
},
+ 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,
@@ -127,6 +146,27 @@ export default defineComponent({
speed: 1000,
});
},
+
+ beforeUnmount() {
+ if (this.easterEggEngine) {
+ this.easterEggEngine.stop();
+ }
+ },
+
+ methods: {
+ iconLoaded() {
+ this.$nextTick(() => {
+ this.easterEggReady = true;
+ });
+ },
+
+ gravity() {
+ if (!this.easterEggReady) return;
+ this.easterEggReady = false;
+ this.$refs.icon.vanillaTilt.destroy();
+ this.easterEggEngine = physics(this.$refs.about);
+ }
+ }
});
</script>
diff --git a/src/client/scripts/physics.ts b/src/client/scripts/physics.ts
new file mode 100644
index 0000000000..c7f6b44a9f
--- /dev/null
+++ b/src/client/scripts/physics.ts
@@ -0,0 +1,168 @@
+import Matter from 'matter-js';
+
+export function physics(container: HTMLElement) {
+ const containerWidth = container.offsetWidth;
+ const containerHeight = container.offsetHeight;
+ const containerCenterX = containerWidth / 2;
+
+ // サイズ固定化(要らないかも?)
+ container.style.position = 'relative';
+ container.style.boxSizing = 'border-box';
+ container.style.width = `${containerWidth}px`;
+ container.style.height = `${containerHeight}px`;
+
+ // create engine
+ const engine = Matter.Engine.create();
+ const world = engine.world;
+
+ // create renderer
+ const render = Matter.Render.create({
+ engine: engine,
+ //element: document.getElementById('debug'),
+ options: {
+ width: containerWidth,
+ height: containerHeight,
+ background: 'transparent', // transparent to hide
+ wireframeBackground: 'transparent', // transparent to hide
+ hasBounds: false,
+ enabled: true,
+ wireframes: false,
+ showSleeping: true,
+ showDebug: false,
+ showBroadphase: false,
+ showBounds: false,
+ showVelocity: false,
+ showCollisions: false,
+ showAxes: false,
+ showPositions: false,
+ showAngleIndicator: false,
+ showIds: false,
+ showShadows: false
+ }
+ });
+
+ // Disable to hide debug
+ Matter.Render.run(render);
+
+ // create runner
+ const runner = Matter.Runner.create();
+ Matter.Runner.run(runner, engine);
+
+ // add walls
+ const wallopts = {
+ isStatic: true,
+ restitution: 0.2,
+ friction: 1
+ };
+ const groundopts = {
+ isStatic: true,
+ restitution: 0.1,
+ friction: 2
+ };
+
+ const groundThickness = 100;
+ const ground = Matter.Bodies.rectangle(containerCenterX, containerHeight + (groundThickness / 2), containerWidth, groundThickness, groundopts);
+ //const wallRight = Matter.Bodies.rectangle(window.innerWidth+50, window.innerHeight/2, 100, window.innerHeight, wallopts);
+ //const wallLeft = Matter.Bodies.rectangle(-50, window.innerHeight/2, 100, window.innerHeight, wallopts);
+
+ Matter.World.add(world, [
+ ground,
+ //wallRight,
+ //wallLeft,
+ ]);
+
+ const objEls = Array.from(container.children);
+ const objs = [];
+ for (const objEl of objEls) {
+ let obj;
+ if (objEl.classList.contains('_physics_circle_')) {
+ obj = Matter.Bodies.circle(
+ objEl.offsetLeft + (objEl.offsetWidth / 2),
+ objEl.offsetTop + (objEl.offsetHeight / 2),
+ Math.max(objEl.offsetWidth, objEl.offsetHeight) / 2,
+ {
+ restitution: 0.1,
+ friction: 4,
+ frictionAir: 0,
+ frictionStatic: 50,
+ density: 100,
+ }
+ );
+ } else {
+ const style = window.getComputedStyle(objEl);
+ obj = Matter.Bodies.rectangle(
+ objEl.offsetLeft + (objEl.offsetWidth / 2),
+ objEl.offsetTop + (objEl.offsetHeight / 2),
+ objEl.offsetWidth,
+ objEl.offsetHeight,
+ {
+ restitution: 0.1,
+ friction: 4,
+ frictionAir: 0,
+ frictionStatic: 50,
+ density: 100,
+ chamfer: { radius: parseInt(style.borderRadius, 10) },
+ }
+ );
+ }
+ objEl.id = obj.id;
+ objs.push(obj);
+ }
+
+ Matter.World.add(engine.world, objs);
+
+ // Add mouse control
+
+ const mouse = Matter.Mouse.create(container);
+ const mouseConstraint = Matter.MouseConstraint.create(engine, {
+ mouse: mouse,
+ constraint: {
+ stiffness: 1,
+ render: {
+ visible: false
+ }
+ }
+ });
+
+ Matter.World.add(engine.world, mouseConstraint);
+
+ // keep the mouse in sync with rendering
+ render.mouse = mouse;
+
+ for (const objEl of objEls) {
+ objEl.style.position = `absolute`;
+ objEl.style.top = 0;
+ objEl.style.left = 0;
+ objEl.style.margin = 0;
+ objEl.style.userSelect = 'none';
+ objEl.style.willChange = 'transform';
+ }
+
+ window.requestAnimationFrame(update);
+
+ let stop = false;
+
+ function update() {
+ for (const objEl of objEls) {
+ const obj = objs.find(obj => obj.id.toString() === objEl.id.toString());
+ if (obj == null) continue;
+
+ 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)`;
+ }
+
+ if (!stop) {
+ window.requestAnimationFrame(update);
+ }
+ }
+
+ return {
+ stop: () => {
+ stop = true;
+ Matter.Runner.stop(runner);
+ }
+ };
+}