阿里云主机折上折
  • 微信号
Current Site:Index > Mouse events and physics engine: Interactive design for stirring coffee

Mouse events and physics engine: Interactive design for stirring coffee

Author:Chuan Chen 阅读数:14389人阅读 分类: 前端综合

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:

  1. Limiting the number of particles (between 50-200)
  2. Using a throttled version of requestAnimationFrame
  3. Stopping physics calculations for particles far from the viewport
  4. 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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.