I’m trying to use JavaScript to make it so that when certain pieces of text in the document are clicked, they become physical objects and drop down to the bottom of the screen. I’m using matter.js to do this and it’s only the rendering that’s tripping me up.
The default renderer in matter.js doesn’t allow objects to contain text, so I’ve made to cobble one together from what I’ve seen online (without really understanding it). I’m re-rendering each time I add a new object to the scene – which works perfectly fine, apart from the fact that the scene doubles in speed each time it’s rendered!
I’m not a programmer, so apologies for the crazy spaghetti code. I just want this one thing to work and then I’ll never have to look at the matter.js docs again. God, I can’t wait.
const engine = Matter.Engine.create();
const physicscanvas = document.getElementById("physicscanvas"); //canvas the scene is rendered on
const ground = Matter.Bodies.rectangle(
200, 2560, 2000, 120, {
isStatic: true
}
);
Matter.Composite.add(
engine.world, [ground]
);
(function rerender() {
Matter.Engine.update(engine);
requestAnimationFrame(rerender);
})();
//function called whenever text is clicked
function explodeMe(textid) {
const explodedName = textid.innerHTML;
//finds x and y of clicked name
var x_of_physicscanvas = physicscanvas.getBoundingClientRect().left;
var x_of_text = textid.getBoundingClientRect().left;
var x_pos_bugged = x_of_text - x_of_physicscanvas;
var y_of_physicscanvas = physicscanvas.getBoundingClientRect().top;
var y_of_text = textid.getBoundingClientRect().top;
var y_pos = y_of_text - y_of_physicscanvas;
//hide the old text
textid.style.visibility = "hidden";
//create the HTML for the falling text
const fallingContainer = document.createElement("div");
fallingContainer.innerHTML = explodedName;
fallingContainer.classList.add("fallingtext");
physicscanvas.appendChild(fallingContainer);
//find width + height
var container_width = fallingContainer.offsetWidth;
var container_height = fallingContainer.offsetHeight;
//accounts for skewed width bug
x_pos = x_pos_bugged + (container_width / 2);
//convert html into matter.js object
var box = {
w: container_width,
h: container_height,
body: Matter.Bodies.rectangle(x_pos, y_pos, container_width, container_height, {
restitution: 0.7
}),
elem: fallingContainer,
render() {
const {
x,
y
} = this.body.position;
this.elem.style.top = `${y - this.h / 2}px`;
this.elem.style.left = `${x - this.w / 2}px`;
this.elem.style.transform = `rotate(${this.body.angle}rad)`;
},
};
//add matter.js object into canvas
Matter.Composite.add(
engine.world, [box.body]
);
//render
(function rerender() {
box.render();
Matter.Engine.update(engine);
requestAnimationFrame(rerender);
})();
return;
}
.fallingtext {
position: absolute;
z-index: 50;
color: blue;
background-color: #0f011f;
text-align: center;
}
#physicscanvas {
position: fixed;
bottom: 0;
margin: auto;
width: 800px;
height: 2500px;
z-index: -5;
opacity: 1;
}
html,
body {
position: relative;
height: 100%;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>
<div>
<div id="physicscanvas">
<div id="ground"></div>
</div>
<p>When <span onclick="explodeMe(this)">this</span> text is clicked, it drops! Likewise, <span onclick="explodeMe(this)">text over here</span> drops too.</p>
</div>
itsolie is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1