initial commit
This commit is contained in:
commit
6d6dbc8c13
8 changed files with 863 additions and 0 deletions
1
src/javascript.svg
Normal file
1
src/javascript.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
After Width: | Height: | Size: 995 B |
180
src/main.js
Normal file
180
src/main.js
Normal file
|
@ -0,0 +1,180 @@
|
|||
import * as p2 from 'p2-es'
|
||||
|
||||
const SCALE = 100;
|
||||
const DENSITY = 0.0001; // Ratio of area to mass of elements
|
||||
|
||||
// Create a physics world, where bodies and constraints live
|
||||
const world = new p2.World({
|
||||
gravity: [0, -10],
|
||||
broadphase: new p2.SAPBroadphase()
|
||||
})
|
||||
|
||||
world.sleepMode = p2.World.BODY_SLEEPING
|
||||
|
||||
const borderMaterial = new p2.Material()
|
||||
const boxMaterial = new p2.Material()
|
||||
|
||||
var border = new p2.ContactMaterial(borderMaterial, boxMaterial, {
|
||||
friction: 0.8,
|
||||
});
|
||||
|
||||
world.addContactMaterial(border);
|
||||
|
||||
// Add planes for browser window "walls"
|
||||
var body = document.body,
|
||||
html = document.documentElement;
|
||||
var height = Math.max(body.scrollHeight, body.offsetHeight,
|
||||
html.clientHeight, html.scrollHeight, html.offsetHeight);
|
||||
var planeBottomBody = new p2.Body({
|
||||
position: [0, - (height) / SCALE],
|
||||
type: p2.Body.KINEMATIC
|
||||
});
|
||||
planeBottomBody.addShape(new p2.Plane({ material: borderMaterial }));
|
||||
world.addBody(planeBottomBody);
|
||||
var planeTopBody = new p2.Body({
|
||||
position: [0, 0],
|
||||
type: p2.Body.KINEMATIC
|
||||
});
|
||||
planeTopBody.addShape(new p2.Plane({ material: borderMaterial }), [0, 0], Math.PI);
|
||||
world.addBody(planeTopBody);
|
||||
var planeLeftBody = new p2.Body({ type: p2.Body.KINEMATIC });
|
||||
planeLeftBody.addShape(new p2.Plane({ material: borderMaterial }), [0, 0], -Math.PI / 2);
|
||||
world.addBody(planeLeftBody);
|
||||
var planeRightBody = new p2.Body({
|
||||
position: [(document.body.getBoundingClientRect().width) / SCALE, 0],
|
||||
type: p2.Body.KINEMATIC
|
||||
});
|
||||
planeRightBody.addShape(new p2.Plane({ material: borderMaterial }), [0, 0], Math.PI / 2);
|
||||
world.addBody(planeRightBody);
|
||||
|
||||
let currentWindowSize = {
|
||||
x: window.screenLeft,
|
||||
y: window.screenTop,
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight
|
||||
}
|
||||
|
||||
// To animate the bodies, we must step the world forward in time, using a fixed time step size.
|
||||
// The World will run substeps and interpolate automatically for us, to get smooth animation.
|
||||
const fixedTimeStep = 1 / 60 // seconds
|
||||
const maxSubSteps = 10 // Max sub steps to catch up with the wall clock
|
||||
|
||||
const bodies = [];
|
||||
|
||||
let lastTime = 0
|
||||
|
||||
document.querySelectorAll(".box").forEach(element => {
|
||||
createBody(element)
|
||||
console.log("body created!")
|
||||
});
|
||||
|
||||
function createBody(element) {
|
||||
var rect = element.getBoundingClientRect();
|
||||
var body = new p2.Body({
|
||||
mass: rect.width * rect.height * DENSITY,
|
||||
position: [
|
||||
(rect.left + rect.width / 2) / SCALE,
|
||||
-(rect.top + rect.height / 2) / SCALE
|
||||
],
|
||||
angle: 0
|
||||
});
|
||||
|
||||
console.log(body.mass)
|
||||
|
||||
var shape = new p2.Box({
|
||||
width: rect.width / SCALE,
|
||||
height: rect.height / SCALE,
|
||||
material: boxMaterial
|
||||
});
|
||||
|
||||
body.allowSleep = true;
|
||||
body.sleepSpeedLimit = 0.05;
|
||||
body.sleepTimeLimit = 1;
|
||||
|
||||
body.addShape(shape);
|
||||
|
||||
world.addBody(body);
|
||||
|
||||
bodies.push({ physics: body, dom: element })
|
||||
|
||||
element.style.position = 'absolute';
|
||||
element.style.top = 0;
|
||||
element.style.left = 0;
|
||||
element.style.transformOrigin = '50% 50%';
|
||||
updateTransform(body, element);
|
||||
}
|
||||
|
||||
function resizeWindow(event) {
|
||||
const delta = {
|
||||
top: window.screenTop - currentWindowSize.y,
|
||||
bottom: (window.screenTop + window.innerHeight) - (currentWindowSize.y + currentWindowSize.h),
|
||||
left: window.screenLeft - currentWindowSize.x,
|
||||
right: (window.screenLeft + window.innerWidth) - (currentWindowSize.x + currentWindowSize.w)
|
||||
}
|
||||
|
||||
|
||||
if (Object.values(delta).some(item => item !== 0)) {
|
||||
console.log(delta)
|
||||
bodies.forEach(element => {
|
||||
element.physics.wakeUp()
|
||||
});
|
||||
|
||||
planeRightBody.velocity = [delta.right / SCALE, 0]
|
||||
planeBottomBody.velocity = [0, -delta.bottom]
|
||||
} else {
|
||||
const height = window.innerHeight;
|
||||
|
||||
const adjustment = Math.round(-height - planeBottomBody.position[1]*SCALE)/SCALE
|
||||
|
||||
planeBottomBody.velocity = [0, Math.max(Math.abs(Math.sign(adjustment)), Math.abs(adjustment)) * Math.sign(adjustment)]
|
||||
// console.log(-height - planeBottomBody.position[1]*SCALE)
|
||||
}
|
||||
|
||||
currentWindowSize = {
|
||||
x: window.screenLeft,
|
||||
y: window.screenTop,
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
world.on('postStep', resizeWindow)
|
||||
|
||||
function updateTransform(body, element) {
|
||||
|
||||
// Convert physics coordinates to pixels
|
||||
var x = SCALE * (body.interpolatedPosition[0] - body.shapes[0].width / 2);
|
||||
var y = -SCALE * (body.interpolatedPosition[1] + body.shapes[0].height / 2);
|
||||
|
||||
element.style.background = ["green", "orange", "gray"][body.sleepState]
|
||||
|
||||
// Set element style
|
||||
var style = 'translate(' + x + 'px, ' + y + 'px) rotate(' + (-body.interpolatedAngle * 57.2957795) + 'deg)';
|
||||
element.style.transform = style;
|
||||
element.style.WebkitTransform = style + ' translateZ(0)'; // Force HW Acceleration
|
||||
element.style.MozTransform = style;
|
||||
element.style.OTransform = style;
|
||||
element.style.msTransform = style;
|
||||
}
|
||||
|
||||
// Animation loop
|
||||
function animate(time) {
|
||||
requestAnimationFrame(animate)
|
||||
|
||||
|
||||
// Compute elapsed time since last render frame
|
||||
const deltaTime = (time - lastTime) / 1000
|
||||
|
||||
// Move bodies forward in time
|
||||
world.step(fixedTimeStep, deltaTime, maxSubSteps)
|
||||
|
||||
bodies.forEach(body => {
|
||||
updateTransform(body.physics, body.dom)
|
||||
});
|
||||
|
||||
lastTime = time
|
||||
}
|
||||
|
||||
// Start the animation loop
|
||||
requestAnimationFrame(animate)
|
13
src/styles.css
Normal file
13
src/styles.css
Normal file
|
@ -0,0 +1,13 @@
|
|||
.box {
|
||||
/* aspect-ratio: 1; */
|
||||
background-color: white;
|
||||
padding: 1vw;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
background-color: aliceblue;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue