This commit is contained in:
parent
2112fb3896
commit
9a270e59a4
|
@ -74,6 +74,7 @@
|
||||||
"@types/koa__multer": "2.0.2",
|
"@types/koa__multer": "2.0.2",
|
||||||
"@types/koa__router": "8.0.2",
|
"@types/koa__router": "8.0.2",
|
||||||
"@types/markdown-it": "10.0.3",
|
"@types/markdown-it": "10.0.3",
|
||||||
|
"@types/matter-js": "0.14.7",
|
||||||
"@types/mocha": "7.0.2",
|
"@types/mocha": "7.0.2",
|
||||||
"@types/node": "14.0.22",
|
"@types/node": "14.0.22",
|
||||||
"@types/node-fetch": "2.5.7",
|
"@types/node-fetch": "2.5.7",
|
||||||
|
@ -175,6 +176,7 @@
|
||||||
"lookup-dns-cache": "2.1.0",
|
"lookup-dns-cache": "2.1.0",
|
||||||
"markdown-it": "11.0.1",
|
"markdown-it": "11.0.1",
|
||||||
"markdown-it-anchor": "6.0.1",
|
"markdown-it-anchor": "6.0.1",
|
||||||
|
"matter-js": "0.14.2",
|
||||||
"mocha": "8.2.1",
|
"mocha": "8.2.1",
|
||||||
"moji": "0.5.1",
|
"moji": "0.5.1",
|
||||||
"ms": "2.1.2",
|
"ms": "2.1.2",
|
||||||
|
|
|
@ -1,50 +1,54 @@
|
||||||
<template>
|
<template>
|
||||||
<FormBase class="znqjceqz">
|
<div style="overflow: hidden;">
|
||||||
<section class="_formItem">
|
<FormBase class="znqjceqz">
|
||||||
<div class="_formPanel" style="text-align: center; padding: 16px;">
|
<div id="debug"></div>
|
||||||
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;" ref="icon"/>
|
<section class="_formItem">
|
||||||
<div style="margin-top: 0.75em;">Misskey</div>
|
<div class="_formPanel" style="text-align: center; padding: 16px;" ref="about">
|
||||||
<div style="opacity: 0.5;">v{{ version }}</div>
|
<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>
|
<div style="margin: 0.75em auto 0 auto; width: max-content;">Misskey</div>
|
||||||
</section>
|
<div style="margin: 0 auto; opacity: 0.5; width: max-content;">v{{ version }}</div>
|
||||||
<section class="_formItem" style="text-align: center; padding: 0 16px;">
|
<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>
|
||||||
{{ $t('_aboutMisskey.about') }}
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<FormGroup>
|
<section class="_formItem" style="text-align: center; padding: 0 16px;" @click="gravity">
|
||||||
<FormLink to="https://github.com/syuilo/misskey" external>
|
{{ $t('_aboutMisskey.about') }}
|
||||||
<template #icon><Fa :icon="faCode"/></template>
|
</section>
|
||||||
{{ $t('_aboutMisskey.source') }}
|
<FormGroup>
|
||||||
<template #suffix>GitHub</template>
|
<FormLink to="https://github.com/syuilo/misskey" external>
|
||||||
</FormLink>
|
<template #icon><Fa :icon="faCode"/></template>
|
||||||
<FormLink to="https://crowdin.com/project/misskey" external>
|
{{ $t('_aboutMisskey.source') }}
|
||||||
<template #icon><Fa :icon="faLanguage"/></template>
|
<template #suffix>GitHub</template>
|
||||||
{{ $t('_aboutMisskey.translation') }}
|
</FormLink>
|
||||||
<template #suffix>Crowdin</template>
|
<FormLink to="https://crowdin.com/project/misskey" external>
|
||||||
</FormLink>
|
<template #icon><Fa :icon="faLanguage"/></template>
|
||||||
<FormLink to="https://www.patreon.com/syuilo" external>
|
{{ $t('_aboutMisskey.translation') }}
|
||||||
<template #icon><Fa :icon="faHandHoldingMedical"/></template>
|
<template #suffix>Crowdin</template>
|
||||||
{{ $t('_aboutMisskey.donate') }}
|
</FormLink>
|
||||||
<template #suffix>Patreon</template>
|
<FormLink to="https://www.patreon.com/syuilo" external>
|
||||||
</FormLink>
|
<template #icon><Fa :icon="faHandHoldingMedical"/></template>
|
||||||
</FormGroup>
|
{{ $t('_aboutMisskey.donate') }}
|
||||||
<FormGroup>
|
<template #suffix>Patreon</template>
|
||||||
<template #label>{{ $t('_aboutMisskey.contributors') }}</template>
|
</FormLink>
|
||||||
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
|
</FormGroup>
|
||||||
<FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
|
<FormGroup>
|
||||||
<FormLink to="https://github.com/mei23" external>@mei23</FormLink>
|
<template #label>{{ $t('_aboutMisskey.contributors') }}</template>
|
||||||
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
|
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
|
||||||
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
|
<FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
|
||||||
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
|
<FormLink to="https://github.com/mei23" external>@mei23</FormLink>
|
||||||
<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
|
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
|
||||||
<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
|
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
|
||||||
<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
|
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
|
||||||
</FormGroup>
|
<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
|
||||||
<FormGroup>
|
<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
|
||||||
<template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
|
<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
|
||||||
<FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
|
</FormGroup>
|
||||||
<template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
|
<FormGroup>
|
||||||
</FormGroup>
|
<template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
|
||||||
</FormBase>
|
<FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
|
||||||
|
<template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
|
||||||
|
</FormGroup>
|
||||||
|
</FormBase>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -57,6 +61,7 @@ import FormBase from '@/components/form/base.vue';
|
||||||
import FormGroup from '@/components/form/group.vue';
|
import FormGroup from '@/components/form/group.vue';
|
||||||
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||||
import MkLink from '@/components/link.vue';
|
import MkLink from '@/components/link.vue';
|
||||||
|
import { physics } from '@/scripts/physics.ts';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
const patrons = [
|
const patrons = [
|
||||||
|
@ -115,10 +120,24 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
version,
|
version,
|
||||||
patrons,
|
patrons,
|
||||||
|
easterEggReady: false,
|
||||||
|
easterEggEmojis: [],
|
||||||
|
easterEggEngine: null,
|
||||||
faInfoCircle, faCode, faLanguage, faHandHoldingMedical,
|
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() {
|
mounted() {
|
||||||
VanillaTilt.init(this.$refs.icon, {
|
VanillaTilt.init(this.$refs.icon, {
|
||||||
max: 30,
|
max: 30,
|
||||||
|
@ -127,6 +146,27 @@ export default defineComponent({
|
||||||
speed: 1000,
|
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>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
10
yarn.lock
10
yarn.lock
|
@ -661,6 +661,11 @@
|
||||||
"@types/mdurl" "*"
|
"@types/mdurl" "*"
|
||||||
highlight.js "^9.7.0"
|
highlight.js "^9.7.0"
|
||||||
|
|
||||||
|
"@types/matter-js@0.14.7":
|
||||||
|
version "0.14.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/matter-js/-/matter-js-0.14.7.tgz#b816f1e7b441ee7499027f9566e4fb5baea637b3"
|
||||||
|
integrity sha512-HLUhVTUoKsibpPZ2tCzoCC/f/UYRWPP9WCOUh5F61BlrUESFV5fE7eKq/CmdoEGkNrLW9v407zYlfrTc9hnGIw==
|
||||||
|
|
||||||
"@types/mdurl@*":
|
"@types/mdurl@*":
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
|
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
|
||||||
|
@ -6116,6 +6121,11 @@ material-colors@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
||||||
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
|
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
|
||||||
|
|
||||||
|
matter-js@0.14.2:
|
||||||
|
version "0.14.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/matter-js/-/matter-js-0.14.2.tgz#8169af9e06fdc356ba9e72b49624eb329839883b"
|
||||||
|
integrity sha512-3ttVT8cJlQnGRjBa8MyVrGyvGmnmOkZ3YsyemIw+KwEEdVi70mo32FH1Eta2b3GfdDJFbMDRqyMQt4heNKBUEA==
|
||||||
|
|
||||||
mdn-data@2.0.4:
|
mdn-data@2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||||
|
|
Loading…
Reference in New Issue