import {
Bodies,
Body,
Bounds,
Composite,
Engine,
Events,
Mouse,
MouseConstraint,
Render,
Runner,
} from "matter-js";
import { useEffect, useRef } from "react";
const Bubbles = () => {
const boxRef = useRef(null);
const engine = useRef(Engine.create());
const ballPositions = useRef(
new Map()
);
const ballColors = useRef(new Map());
useEffect(() => {
if (!boxRef.current) return;
// Clear any existing canvas to avoid duplicates
const existingCanvas = boxRef.current.querySelector("canvas");
if (existingCanvas) {
existingCanvas.remove();
}
const engineRef = engine.current;
const world = engineRef.world;
const width = boxRef.current.clientWidth;
const height = boxRef.current.clientHeight;
// Create bounds vertices that match the wall coordinates
const boundsVertices = [
{ x: 0, y: 0 }, // Top-left corner
{ x: width, y: 0 }, // Top-right corner
{ x: width, y: height }, // Bottom-right corner
{ x: 0, y: height }, // Bottom-left corner
];
const bounds = Bounds.create(boundsVertices);
const render = Render.create({
element: boxRef.current,
engine: engineRef,
bounds,
options: {
width: boxRef.current.clientWidth,
height: boxRef.current.clientHeight,
wireframes: false,
background: "transparent",
hasBounds: true,
},
});
// Create a mapping between ball index and bubble state ID
const ballToBubbleId = new Map();
let balls = [];
for (let i = 0; i < 2; i++) {
// Use stored position if available, otherwise random
const xPos = Math.random() * (width - 100) + 50;
const yPos = Math.random() * (height - 100) + 50;
const color = "red";
const body = Bodies.circle(xPos, yPos, 50, {
frictionAir: 0,
friction: 0,
restitution: 1,
force: { x: 0.1, y: 0.1 },
render: {
fillStyle: color,
opacity: 0.5,
},
collisionFilter: {
group: -1,
},
label: `bubble-${i}`,
});
balls.push(body);
}
// Create walls around the screen - positioned outside the visible area
const walls = [
// Top wall - positioned above the container
Bodies.rectangle(width / 2, -512, width, 1024, {
isStatic: true,
restitution: 1,
collisionFilter: { category: 0x0001, mask: 0x0001 },
}),
// Bottom wall - positioned below the container
Bodies.rectangle(width / 2, height + 512, width, 1024, {
isStatic: true,
restitution: 1,
collisionFilter: { category: 0x0001, mask: 0x0001 },
}),
// Left wall - positioned to the left of the container
Bodies.rectangle(-512, height / 2, 1024, height, {
isStatic: true,
restitution: 1,
collisionFilter: { category: 0x0001, mask: 0x0001 },
}),
// Right wall - positioned to the right of the container
Bodies.rectangle(width + 512, height / 2, 1024, height, {
isStatic: true,
restitution: 1,
collisionFilter: { category: 0x0001, mask: 0x0001 },
}),
];
Composite.add(world, [...walls, ...balls]);
// Create mouse constraint for dragging
const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engineRef, {
mouse: mouse,
constraint: {
stiffness: 0.2, // Lower stiffness for more controlled dragging
render: {
visible: false,
},
},
collisionFilter: {
group: 1,
},
});
Composite.add(world, mouseConstraint);
// Keep the mouse in sync with rendering
render.mouse = mouse;
let selectedBubbleIndex: number | null = null;
// Add mouseUp event listener to check for ball overlaps
Events.on(mouseConstraint, "mousedown", ({ source }) => {
const body = source.body;
if (body) {
// Find the index of the selected bubble
selectedBubbleIndex = balls.findIndex((b) => b.id === body.id);
}
});
Events.on(mouseConstraint, "mousemove", ({ source }) => {
const body = source.body;
if (body) {
const { y } = body.position;
console.log(y);
console.log(source.constraint.bodyB);
if (y {
Render.stop(render);
Runner.stop(runner);
Composite.clear(world, false);
Engine.clear(engineRef);
render.canvas.remove();
};
}, []); // Only depend on bubbles, not refs
return (
style={{
backgroundColor: "blue",
width: "100%",
height: "500px",
overflow: "hidden",
}}
ref={boxRef}
>
);
};
export default Bubbles;
Wenn ich einen Ball aus dem blauen Rahmen ziehe, beginnt er sich schnell zu drehen, und wenn ich die Maustaste loslasse, während ich mich außerhalb des Begrenzungsrahmens befinde, wird das Element weiter gezogen. Ich möchte den Ball loslassen, wenn die Maus den Begrenzungsrahmen berührt.
Ich habe eine Codesandbox erstellt, um mein Problem zu veranschaulichen: https://codesandbox.io/p/sandbox/hvmg69 bubbles.tsx [code]import { Bodies, Body, Bounds, Composite, Engine, Events, Mouse, MouseConstraint, Render, Runner, } from "matter-js"; import { useEffect, useRef } from "react";
export default Bubbles; [/code] Wenn ich einen Ball aus dem blauen Rahmen ziehe, beginnt er sich schnell zu drehen, und wenn ich die Maustaste loslasse, während ich mich außerhalb des Begrenzungsrahmens befinde, wird das Element weiter gezogen. [url=viewtopic.php?t=30561]Ich möchte[/url] den Ball loslassen, wenn die Maus den Begrenzungsrahmen berührt.
Ich frage mich, ob es neben der Bequemlichkeit der Abstraktion einen inhärenten Vorteil hat, wenn ein Kernel > 1d ist. Ich denke, wenn die Dimension des Kernels relevant ist, hängt die Antwort...
Mein Programm soll die Steuer aus einem eingegebenen Dollarbetrag berechnen. Das Programm funktioniert, aber der Dollarbetrag geht zu weit, statt „12,87 $“ als Ausgabe anzuzeigen, gibt es „12,875 $“...
Angenommen, ich habe eine Beschriftung auf einer Webseite und möchte den Effekt haben, dass ein Eingabefeld herausgeschoben wird, wenn ich mit der Maus über die Beschriftung fahre. Gibt es einen...
Angenommen, ich habe eine Beschriftung auf einer Webseite und möchte den Effekt haben, dass ein Eingabefeld herausgeschoben wird, wenn ich mit der Maus über die Beschriftung fahre. Gibt es einen...