1
0
Fork 0
mirror of https://github.com/mat-1/matdoesdev.git synced 2025-08-02 06:36:04 +00:00

add gravity easter egg

This commit is contained in:
mat 2024-04-13 20:57:59 +00:00
parent 664e9d569b
commit 0a6d90717a
12 changed files with 765 additions and 488 deletions

Binary file not shown.

View file

@ -1,6 +1,7 @@
(https_redirect) {
@do_https_redirect {
not header_regexp veryoldbrowser User-Agent Navigator|MSIE|Mosaic|Kindle|^curl|NintendoBrowser/
not host *.onion *.*.onion
protocol http
}
redir @do_https_redirect https://{host}{uri}
@ -205,7 +206,7 @@ Disallow: /"
}
}
}
matrix.matdoes.dev, matrix.matdoes.dev:8448 {
matrix.matdoes.dev matrix.matdoes.dev:8448 {
handle /.well-known/matrix/server {
header content-type application/json
respond "{\"m.server\":\"matrix.matdoes.dev\"}"
@ -229,7 +230,7 @@ fedi.matdoes.dev {
}
}
f.matdoes.dev {
f.matdoes.dev media.f.matdoes.dev cache.f.matdoes.dev {
@chrome {
header_regexp chrome User-Agent Chrome\/[0-9./]+\s(Mobile\s)?Safari\/[0-9./]+$
not header User-Agent *Googlebot/*
@ -241,7 +242,9 @@ f.matdoes.dev {
git.matdoes.dev {
reverse_proxy 127.0.0.1:3000
}
s.matdoes.dev {
http://s.matdoes.dev https://s.matdoes.dev {
import https_redirect
reverse_proxy 127.0.0.1:28019
}
@ -296,3 +299,19 @@ hetzner.matdoes.dev {
xmpp.matdoes.dev {
respond ""
}
mcassets.matdoes.dev {
reverse_proxy 127.0.0.1:10573
}
www.www.matdoes.dev {
header {
Content-Type text/html
Server "meow"
}
respond "<meta http-equiv=\"refresh\" content=\"15;url=https://matdoes.dev\">nyaaaaaaaaaaaaaaaaaaa" 200
}
www.matdoes.dev {
redir https://matdoes.dev{uri}
}

View file

@ -14,38 +14,40 @@
"postinstall": "patch-package"
},
"devDependencies": {
"@img/sharp-linux-x64": "^0.33.2",
"@img/sharp-linux-x64": "^0.33.3",
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"@types/cookie": "^0.6.0",
"@types/html-minifier": "^4.0.5",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"@types/matter-js": "^0.19.6",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"mdsvex": "^0.11.0",
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.2.2",
"sharp": "^0.33.2",
"sharp": "^0.33.3",
"svelte": "4.2.12",
"svelte-check": "^3.6.7",
"svelte-check": "^3.6.9",
"svelte-preprocess": "^5.1.3",
"tslib": "^2.6.2",
"typescript": "^5.4.2"
"typescript": "^5.4.4"
},
"type": "module",
"dependencies": {
"@lukeed/uuid": "^2.0.1",
"@sveltejs/adapter-node": "^5.0.1",
"@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.5.4",
"@sveltejs/kit": "^2.5.5",
"@types/js-yaml": "^4.0.9",
"cbor-x": "^1.5.8",
"cbor-x": "^1.5.9",
"cookie": "^0.6.0",
"html-minifier": "^4.0.0",
"matter-js": "^0.19.0",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"svelte-body": "^1.4.0",
"vite": "5.1.6"
"vite": "5.2.8"
},
"engines": {
"node": ">=16"

View file

@ -19,6 +19,12 @@
--text-font: 'Atkinson Hyperlegible', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
html,
body,
#page {

157
src/lib/gravity.ts Normal file
View file

@ -0,0 +1,157 @@
import { browser } from '$app/environment'
import Matter from 'matter-js'
const GRAVITY_QUERY_SELECTOR = 'p, h1, h2, .button, .icon'
export function initGravity(): () => void {
const { Engine, Bodies, Composite, Runner, Mouse, MouseConstraint } = Matter
console.log('gravity enabled')
// create an engine
const engine = Engine.create({ enableSleeping: true })
const floorBody = Bodies.rectangle(
window.innerWidth / 2,
window.innerHeight - 5,
window.innerWidth,
10,
{
isStatic: true,
}
)
Composite.add(engine.world, [floorBody])
const trackedElements = new Map<HTMLElement, Matter.Body>()
async function enableGravityOnElement(el: HTMLElement) {
await new Promise((resolve) => requestAnimationFrame(resolve))
let originalTextContent: string | null = null
if (el.classList.contains('copyright') || el.id === 'main-title') {
el.style.width = 'fit-content'
el.style.margin = '0 auto'
if (el.id === 'main-title') {
originalTextContent = el.textContent
el.textContent = 'matdoesdev'
}
}
const bb = el.getBoundingClientRect()
if (originalTextContent) el.textContent = originalTextContent
const body = Bodies.rectangle(
bb.left + bb.width / 2,
bb.top + bb.height / 2,
bb.width,
bb.height,
{ restitution: 1 }
)
el.style.position = 'absolute'
el.style.left = bb.left + 'px'
el.style.top = bb.top + 'px'
el.style.width = bb.width + 'px'
el.style.height = bb.height + 'px'
el.style.userSelect = 'none'
// el.style.outline = '1px solid red'
Composite.add(engine.world, [body])
trackedElements.set(el, body)
}
function makeAnchorUndraggable(el: HTMLAnchorElement) {
// el.style.pointerEvents = 'none'
// el.style.cursor = 'pointer'
el.draggable = false
// document.addEventListener('click', (e) => {
// el.style.pointerEvents = ''
// const clickedEl = document.elementFromPoint(e.clientX, e.clientY)
// el.style.pointerEvents = 'none'
// // if (clickedEl instanceof HTMLAnchorElement) {
// // e.preventDefault()
// // goto(clickedEl.href)
// // }
// if (el.contains(clickedEl)) {
// e.preventDefault()
// const url = new URL(el.href)
// if (url.origin === window.location.origin) {
// goto(el.href)
// } else {
// window.location.href = el.href
// }
// }
// })
}
document.querySelectorAll(GRAVITY_QUERY_SELECTOR).forEach((el) => {
enableGravityOnElement(el as HTMLElement)
})
document.querySelectorAll('a').forEach((el) => {
makeAnchorUndraggable(el as HTMLAnchorElement)
})
// update positions every frame
Matter.Events.on(engine, 'beforeUpdate', function (event) {
trackedElements.forEach((body, el) => {
if (body.position.y < 0) {
// move up
body.position.y = window.innerHeight
}
el.style.left = body.position.x - el.offsetWidth / 2 + 'px'
el.style.top = body.position.y - el.offsetHeight / 2 + 'px'
el.style.transform = `rotate(${body.angle}rad)`
// rotate
// el.style.transform = ''
// const [originalWidthStyle, originalHeightStyle] = [el.style.width, el.style.height]
// el.style.maxWidth = originalWidthStyle
// el.style.maxHeight = originalHeightStyle
// el.style.width = ''
// el.style.height = ''
// const bb = el.getBoundingClientRect()
// el.style.transform = `rotate(${body.angle}rad)`
// el.style.width = originalWidthStyle
// el.style.height = originalHeightStyle
// el.style.maxWidth = ''
// el.style.maxHeight = ''
// const fakeBody = Bodies.rectangle(
// bb.left + bb.width / 2,
// bb.top + bb.height / 2,
// bb.width,
// bb.height,
// {
// angle: body.angle,
// }
// )
// body.vertices = fakeBody.vertices
})
})
// create runner
const runner = Runner.create()
// run the engine
Runner.run(runner, engine)
// add mouse control
var mouse = Mouse.create(document.body),
mouseConstraint = MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2,
render: {
visible: false,
},
},
})
Composite.add(engine.world, mouseConstraint)
console.log('running engine')
return () => {
Runner.stop(runner)
}
}

View file

@ -2,6 +2,7 @@
import '../../app.css'
import { fly } from 'svelte/transition'
import type { LayoutData } from '../$types'
import { browser } from '$app/environment'
export let data: LayoutData
@ -11,7 +12,7 @@
let previousPathname = data.pathname
let currentPathName = data.pathname
let flyDirection = 1 // 1 is right, -1 is left
$: {
$: if (browser) {
if (previousPathname !== currentPathName) previousPathname = currentPathName
currentPathName = data.pathname
@ -19,6 +20,35 @@
if (previousPathname === '/') flyDirection = 1
else if (previousPathname === '/blog' && currentPathName !== '/') flyDirection = 1
else flyDirection = -1
onPathChange()
}
let pathChangeTimestamps: number[] = []
let stopGravity: (() => void) | null = null
async function onPathChange() {
// if we switched paths more than 10 times in the past 5 seconds, import $lib/gravity.js
pathChangeTimestamps.push(Date.now())
while (pathChangeTimestamps[0] < Date.now() - 5000) pathChangeTimestamps.shift()
console.log(pathChangeTimestamps)
if (pathChangeTimestamps.length >= 10) {
const { initGravity } = await import('$lib/gravity')
// wait 200ms for the animation to finish
await new Promise((resolve) => setTimeout(resolve, 200))
// and an animation frame
await new Promise((resolve) => requestAnimationFrame(resolve))
const lastPathChangeTimestamp = pathChangeTimestamps[pathChangeTimestamps.length - 1]
// only if it was over 200ms ago
if (lastPathChangeTimestamp < Date.now() - 200) {
if (currentPathName === '/') {
stopGravity = initGravity()
} else {
stopGravity?.()
}
}
}
}
</script>
@ -33,15 +63,12 @@
</main>
<footer>
<p>&copy; {copyrightYear} mat</p>
<p class="copyright">&copy; {copyrightYear} mat</p>
</footer>
</div>
{/key}
<style>
/* :global(body) {
overflow: hidden;
} */
#page {
height: 100%;
display: flex;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1,014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 261 B

1006
yarn.lock

File diff suppressed because it is too large Load diff