Support different sized SVGs, center picture
|
@ -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
|
@ -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
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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
|
@ -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 |
57
script.js
|
@ -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)
|
||||
|
|
|
@ -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
|
@ -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 |