Mouse events and physics engine: Interactive design for stirring coffee
The combination of mouse events and physics engines has brought more possibilities to front-end interaction design. The interactive effect of stirring coffee, which simulates liquid flow through a physics engine and combines it with mouse drag events, can create a realistic dynamic experience. This technology not only enhances user experience but also provides new ideas for scenarios such as web games and data visualization.
Basics and Applications of Mouse Events
Mouse events are one of the most commonly used interaction methods in front-end development. The combination of three events—mousedown
, mousemove
, and mouseup
—can implement the basic logic of drag-and-drop operations. In the coffee-stirring interaction, these events are used to capture the user's operational intent.
let isDragging = false;
const coffeeCup = document.getElementById('coffee-cup');
coffeeCup.addEventListener('mousedown', (e) => {
isDragging = true;
// Record initial position
startX = e.clientX;
startY = e.clientY;
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
// Calculate movement distance
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
// Update stirrer position
updateStirrerPosition(deltaX, deltaY);
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
For touch devices, implementations need to consider touchstart
, touchmove
, and touchend
events to ensure mobile compatibility. The clientX
and clientY
properties of the event object provide pointer coordinates, which form the basis for calculating stirring direction and speed.
Selection and Integration of Physics Engines
Physics engines simulate the laws of the physical world. For liquid simulation, Matter.js and Cannon.js are excellent choices. Matter.js is lighter and suitable for 2D scenes, while Cannon.js supports 3D but is more complex.
// Using Matter.js to create an engine
const engine = Matter.Engine.create();
const world = engine.world;
// Create liquid particles
function createLiquidParticles() {
const particles = [];
for (let i = 0; i < 100; i++) {
const particle = Matter.Bodies.circle(
Math.random() * 300 + 50,
Math.random() * 200 + 50,
5,
{ restitution: 0.8 }
);
particles.push(particle);
}
Matter.Composite.add(world, particles);
return particles;
}
The engine requires continuous updates to produce dynamic effects. An animation loop is implemented using requestAnimationFrame
:
function animate() {
Matter.Engine.update(engine);
renderParticles();
requestAnimationFrame(animate);
}
animate();
Implementation Principles of the Stirring Effect
The force field generated by the stirring motion affects liquid particles. Based on the speed and direction of mouse movement, a force is calculated and applied to the particles.
let prevX, prevY;
function updateStirrerPosition(x, y) {
// Calculate velocity
const velocityX = x - prevX;
const velocityY = y - prevY;
prevX = x;
prevY = y;
// Apply force to each particle
liquidParticles.forEach(particle => {
const distance = Math.sqrt(
Math.pow(particle.position.x - x, 2) +
Math.pow(particle.position.y - y, 2)
);
if (distance < 100) {
const force = {
x: velocityX * 0.1 / distance,
y: velocityY * 0.1 / distance
};
Matter.Body.applyForce(particle, particle.position, force);
}
});
}
Force attenuation is also crucial. Particles farther from the stirring center are less affected. This non-uniform force distribution creates a natural vortex effect.
Visual Rendering and Performance Optimization
Canvas or WebGL is suitable for rendering large numbers of particles. The Canvas API is simpler, while WebGL offers better performance. Below is a Canvas rendering example:
const canvas = document.getElementById('coffee-canvas');
const ctx = canvas.getContext('2d');
function renderParticles() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw coffee cup
ctx.fillStyle = '#6F4E37';
ctx.beginPath();
ctx.arc(200, 200, 150, 0, Math.PI * 2);
ctx.fill();
// Draw particles
ctx.fillStyle = '#4B3621';
liquidParticles.forEach(particle => {
ctx.beginPath();
ctx.arc(
particle.position.x,
particle.position.y,
particle.circleRadius,
0,
Math.PI * 2
);
ctx.fill();
});
}
Performance optimization strategies include:
- Limiting the number of particles (between 50-200)
- Using a throttled version of
requestAnimationFrame
- Stopping physics calculations for particles far from the viewport
- Using Web Workers to handle complex physics computations
Refining Interaction Details
A realistic stirring experience requires attention to these details:
- Stirrer shape affects fluid patterns
- Adjusting coffee viscosity parameters
- Inertia effects (liquid continues moving after stirring stops)
- Rebound coefficients for collisions with the cup wall
// Adjust physics parameters
Matter.Body.setVelocity(particle, {
x: particle.velocity.x * 0.98, // Friction
y: particle.velocity.y * 0.98
});
// Cup wall collision
Matter.Events.on(engine, 'collisionStart', event => {
event.pairs.forEach(pair => {
if (isWall(pair.bodyA) || isWall(pair.bodyB)) {
// Play collision sound
playSound('collision');
}
});
});
Audio feedback enhances immersion. Different stirring speeds can trigger liquid flow sounds with varying pitches.
Expanding Application Scenarios
This technology can be extended to other scenarios:
- Cocktail mixing simulator
- Paint mixing experiments
- Fluid data visualization
- Scientific education tools
In data visualization, particles can represent data points, and stirring actions can trigger data filtering or reorganization. For example:
// Special behavior for data particles
function updateDataParticles() {
particles.forEach(particle => {
if (particle.data.value > threshold) {
// High-value particles react more strongly to the force field
Matter.Body.applyForce(particle, particle.position, {
x: force.x * 2,
y: force.y * 2
});
}
});
}
Responsive design requires parameter adjustments for different screen sizes. Touch events on mobile devices may need larger trigger areas and more pronounced visual feedback.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn