Support different sized SVGs, center picture

This commit is contained in:
Anthony Wang 2024-01-29 23:38:39 +00:00
parent 389eeeb48d
commit 04d15f2b1d
Signed by: a
SSH key fingerprint: SHA256:B5ADfMCqd2M7d/jtXDoihAV/yfXOAbWWri9+GdCN4hQ
11 changed files with 48 additions and 40 deletions

View file

@ -7,11 +7,6 @@
</head>
<body>
<img src="anime.png">
<!--
Draw 200x200 SVGs in Inkscape with the pencil tool and a stroke width of 20
Make sure the scale is set to 1 and that the id is set to a unique value
Also, change the stroke to currentColor so we can style the color with CSS
-->
<svg id="hiragana-ni"></svg>
<svg id="hiragana-small-ya"></svg>
<svg id="hiragana-a"></svg>

2
b.svg
View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="b"
id="svg1"
sodipodi:docname="b.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

2
d.svg
View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="d"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="d.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="hiragana-a"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-a.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="hiragana-ni"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-ni.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="hiragana-small-ya"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-small-ya.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -7,9 +7,9 @@
</head>
<body>
<!--
Draw 200x200 SVGs in Inkscape with the pencil tool and a stroke width of 20
Make sure the scale is set to 1 and that the id is set to a unique value
Also, change the stroke to currentColor so we can style the color with CSS
Draw SVGs in Inkscape with the scale set to 1
Use the pencil tool with a stroke width of 20 and round endcaps
Then change the stroke color to currentColor so we can style it with CSS (might have to do this in a text editor)
-->
<svg id="d"></svg>
<svg id="u"></svg>

2
m.svg
View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="m"
id="svg1"
sodipodi:docname="u.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -7,23 +7,37 @@ document.querySelectorAll("svg").forEach(function(svg) {
})
let rad = 10 // Stroke radius
let size = 200 // SVG width and height
let A = [] // Objects
let cnt = 0
let rowsize = Math.floor(window.innerWidth / 1.1 / size)
let idcnt = 0
let ix = 0
let iy = 0
let ny = 0
document.querySelectorAll("svg").forEach(function(svg) {
// Move objects so they aren't overlapping
svg.style.left = 1.1 * size * (cnt % rowsize) + "px"
svg.style.top = 1.1 * size * Math.floor(cnt / rowsize) + "px"
cnt++
// Position objects so they aren't overlapping
if (ix + svg.width.baseVal.value > window.innerWidth) {
ix = 0
iy += ny
ny = 0
}
svg.style.left = ix + "px"
svg.style.top = iy + "px"
ix += svg.width.baseVal.value
ny = Math.max(svg.height.baseVal.value, ny)
svg.id = idcnt++
const rect = svg.getBoundingClientRect()
let a = {
id: svg.id, // Unique ID
p: [], // Collision circles
cm: svg.createSVGPoint(), // Center of mass
cm: svg.createSVGPoint(), // Position of center of mass relative to top left corner
x: rect.x, // x position of center of mass
y: rect.y, // y position of center of mass
vx: Math.random(), // x velocity
vy: Math.random(), // y velocity
th: 0, // Angular position
w: Math.random() / 100 // Angular velocity
w: Math.random() / 100, // Angular velocity
m: 0, // Mass
mi: 0, // Moment of inertia
r: 0 // Distance to farthest point from center of mass
}
svg.querySelectorAll("path").forEach(function(path) {
// Get circles on path for collision checking
@ -45,17 +59,16 @@ document.querySelectorAll("svg").forEach(function(svg) {
a.cm.x /= a.p.length
a.cm.y /= a.p.length
// Change origin to center of mass
const rect = svg.getBoundingClientRect()
a.x = rect.x + a.cm.x // Position of center of mass
a.y = rect.y + a.cm.y // Position of center of mass
a.x += a.cm.x
a.y += a.cm.y
for (const p of a.p) {
p.x -= a.cm.x
p.y -= a.cm.y
}
svg.style.transformOrigin = a.cm.x + "px " + a.cm.y + "px"
a.m = a.p.length // Mass
a.mi = 0 // Moment of inertia
a.m = a.p.length
for (const p of a.p) a.mi += p.x ** 2 + p.y ** 2
for (const p of a.p) a.r = Math.max(Math.sqrt(p.x ** 2 + p.y ** 2), a.r)
A.push(a)
})
@ -100,7 +113,7 @@ function collide(a, b, c, n) {
// Collision of object a with wall at position k and direction d
function wallCollide(a, k, d) {
if ((d == 0 && Math.abs(a.x - k) < size) || (d == 1 && Math.abs(a.y - k) < size)) {
if ((d == 0 && Math.abs(a.x - k) < a.r) || (d == 1 && Math.abs(a.y - k) < a.r)) {
let c = {x: 0, y: 0, cnt: 0}
for (const p of a.p.map(x => rot(a, x))) {
if ((d == 0 && Math.abs(p.x - k) < rad) || (d == 1 && Math.abs(p.y - k) < rad)) {
@ -122,7 +135,7 @@ function wallCollide(a, k, d) {
// Collision of object a with object b
function objectsCollide(a, b) {
if (ds(a, b) < 2 * (size + 2 * rad) ** 2) {
if (ds(a, b) < (a.r + b.r + 2 * rad) ** 2) {
// Objects are close
let c = {x: 0, y: 0, cnt: 0}
let n = {x: 0, y: 0}
@ -131,10 +144,10 @@ function objectsCollide(a, b) {
let aa = []
let bb = []
for (const p of a.p.map(x => rot(a, x))) {
if (ds(p, b) < 2 * (size + 2 * rad) ** 2) aa.push(p)
if (ds(p, b) < (a.r + b.r + 2 * rad) ** 2) aa.push(p)
}
for (const p of b.p.map(x => rot(b, x))) {
if (ds(p, a) < 2 * (size + 2 * rad) ** 2) bb.push(p)
if (ds(p, a) < (a.r + b.r + 2 * rad) ** 2) bb.push(p)
}
for (const p of aa) {
for (const q of bb) {
@ -187,9 +200,9 @@ function tick() {
}
}
// Render every 10ms
cnt++
if (cnt == 10) {
cnt = 0
tickcnt++
if (tickcnt == 10) {
tickcnt = 0
for (a of A) {
let e = document.getElementById(a.id)
e.style.left = a.x - a.cm.x + "px"
@ -220,6 +233,6 @@ function updatev(event) {
}, 1000)
}
cnt = 0
let tickcnt = 0
setInterval(tick, 1)
document.addEventListener("click", updatev)

View file

@ -49,8 +49,8 @@ div {
}
img {
display: block;
margin-left: auto;
margin-right: auto;
position: absolute;
left: 50vw;
transform: translateX(-50%);
height: 100vh;
}

2
u.svg
View file

@ -6,7 +6,7 @@
height="200"
viewBox="0 0 200 200"
version="1.1"
id="u"
id="svg1"
sodipodi:docname="u.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB