阿里云主机折上折
  • 微信号
Current Site:Index > Page jitter: setInterval(() => document.body.style.marginLeft = (Math.random()*20-10)+'px', 50);

Page jitter: setInterval(() => document.body.style.marginLeft = (Math.random()*20-10)+'px', 50);

Author:Chuan Chen 阅读数:37801人阅读 分类: JavaScript

Page Jitter: setInterval(() => document.body.style.marginLeft = (Math.random()*20-10)+'px', 50);

Page jitter is a common visual effect that creates a shaking sensation by rapidly altering an element's position. Combining setInterval with a random number generator easily achieves this dynamic change. The following code adjusts the left margin of the body element randomly every 50 milliseconds, producing a left-right wobbling visual effect:

setInterval(() => {
  document.body.style.marginLeft = (Math.random() * 20 - 10) + 'px';
}, 50);

Implementation Principle Analysis

This code revolves around three key points: timers, random number calculations, and style modifications. Math.random() generates a floating-point number between 0 and 1. Multiplying it by 20 scales the range to 0-20, and subtracting 10 yields a range of -10 to 10. This ensures each execution produces a different negative or positive value:

// Breakdown of random number generation
const randomValue = Math.random(); // 0 ≤ x < 1
const scaledValue = randomValue * 20; // 0 ≤ x < 20
const finalValue = scaledValue - 10; // -10 ≤ x < 10

The timer interval of 50 milliseconds (i.e., 20 frames per second) ensures smooth animation. This frequency is close to the limit of human visual persistence, creating a continuous animation effect without appearing choppy.

Practical Application Scenarios

Though simple, this jitter effect is highly practical in specific scenarios:

  1. Enhanced Error Notifications: Lightly shake an input field when form validation fails.
function shakeElement(element) {
  let count = 0;
  const interval = setInterval(() => {
    element.style.transform = `translateX(${Math.random() * 6 - 3}px)`;
    if(++count >= 10) clearInterval(interval);
  }, 50);
}
  1. Game Effects: Feedback when a character takes damage.
// Example of character jitter in games
const character = document.getElementById('game-character');
function takeDamage() {
  const originalPosition = character.getBoundingClientRect().left;
  const interval = setInterval(() => {
    character.style.left = originalPosition + (Math.random() * 10 - 5) + 'px';
  }, 30);
  setTimeout(() => clearInterval(interval), 300);
}
  1. Attention Guidance: Draw user attention to specific interface elements.
function highlightElement(element) {
  const originalMargin = element.style.marginLeft;
  const interval = setInterval(() => {
    element.style.marginLeft = (Math.random() * 15 - 7.5) + 'px';
  }, 40);
  
  // Stop after 3 seconds
  setTimeout(() => {
    clearInterval(interval);
    element.style.marginLeft = originalMargin;
  }, 3000);
}

Performance Optimization Solutions

The original implementation, while simple, has performance drawbacks. Here are optimization approaches:

  1. Replace setInterval with requestAnimationFrame
function startShake() {
  let lastTime = 0;
  function shake(timestamp) {
    if(timestamp - lastTime > 50) {
      document.body.style.marginLeft = (Math.random() * 20 - 10) + 'px';
      lastTime = timestamp;
    }
    requestAnimationFrame(shake);
  }
  requestAnimationFrame(shake);
}
  1. CSS Animation Solution (Better Performance)
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
  20%, 40%, 60%, 80% { transform: translateX(5px); }
}

.shake-element {
  animation: shake 0.5s linear infinite;
}
  1. Limit Jitter Range to Avoid Layout Reflows
// Use transform instead of margin
setInterval(() => {
  document.body.style.transform = `translateX(${Math.random() * 20 - 10}px)`;
}, 50);

Advanced Variants

More complex effects can be built upon the basic jitter:

  1. 3D Jitter (Add Y and Z-axis variations)
setInterval(() => {
  const x = Math.random() * 10 - 5;
  const y = Math.random() * 8 - 4;
  document.body.style.transform = `translate3d(${x}px, ${y}px, 0)`;
}, 50);
  1. Decaying Jitter (Amplitude gradually decreases)
function decayingShake(element, duration = 1000) {
  const startTime = Date.now();
  const maxOffset = 15;
  
  function update() {
    const elapsed = Date.now() - startTime;
    const progress = Math.min(elapsed / duration, 1);
    const currentOffset = maxOffset * (1 - progress);
    
    if(progress < 1) {
      element.style.transform = `translateX(${(Math.random() * 2 - 1) * currentOffset}px)`;
      requestAnimationFrame(update);
    } else {
      element.style.transform = '';
    }
  }
  
  update();
}
  1. Rhythmic Jitter (Sync with music beats)
// Assuming audio analysis data is available
function beatShake(analyser) {
  analyser.getByteFrequencyData(frequencyData);
  const bass = frequencyData[0] / 255;
  
  document.body.style.transform = `translateX(${bass * 20 - 10}px)`;
  requestAnimationFrame(() => beatShake(analyser));
}

Browser Compatibility Considerations

Different browsers handle high-frequency style changes differently:

  1. Legacy IE Limitations:
// Special handling for IE9 and below
if(document.documentMode && document.documentMode < 10) {
  // Simpler jitter approach
  let toggle = false;
  setInterval(() => {
    document.body.style.marginLeft = toggle ? '5px' : '-5px';
    toggle = !toggle;
  }, 100);
} else {
  // Standard implementation for modern browsers
  setInterval(() => {
    document.body.style.transform = `translateX(${Math.random() * 20 - 10}px)`;
  }, 50);
}
  1. Mobile Optimization:
// Reduce amplitude on touch devices
const isTouchDevice = 'ontouchstart' in window;
const amplitude = isTouchDevice ? 5 : 10;

setInterval(() => {
  document.body.style.transform = `translateX(${Math.random() * amplitude * 2 - amplitude}px)`;
}, 50);

Debugging Techniques

Debugging may be needed during development:

  1. Performance Analysis:
// Measure execution time
setInterval(() => {
  const start = performance.now();
  document.body.style.marginLeft = (Math.random() * 20 - 10) + 'px';
  console.log('Execution time:', performance.now() - start);
}, 50);
  1. Amplitude Visualization:
// Add debug panel
const debugPanel = document.createElement('div');
debugPanel.style.position = 'fixed';
debugPanel.style.bottom = '0';
document.body.appendChild(debugPanel);

setInterval(() => {
  const value = Math.random() * 20 - 10;
  document.body.style.marginLeft = value + 'px';
  debugPanel.textContent = `Current amplitude: ${value.toFixed(2)}px`;
}, 50);
  1. Frame Rate Monitoring:
let lastTime = performance.now();
let frameCount = 0;

setInterval(() => {
  document.body.style.marginLeft = (Math.random() * 20 - 10) + 'px';
  frameCount++;
  
  const now = performance.now();
  if(now - lastTime >= 1000) {
    console.log(`Current FPS: ${frameCount}`);
    frameCount = 0;
    lastTime = now;
  }
}, 50);

Integration with Animation Libraries

Basic jitter can be integrated with professional animation libraries:

  1. GSAP Implementation:
import { gsap } from "gsap";

function gsapShake(element) {
  gsap.to(element, {
    x: () => Math.random() * 20 - 10,
    duration: 0.05,
    repeat: -1
  });
}
  1. Anime.js Version:
import anime from 'animejs';

anime({
  targets: document.body,
  translateX: () => Math.random() * 20 - 10,
  duration: 50,
  loop: true
});
  1. React Component Encapsulation:
function ShakyComponent({ children, intensity = 10 }) {
  const [offset, setOffset] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setOffset(Math.random() * intensity * 2 - intensity);
    }, 50);
    return () => clearInterval(interval);
  }, [intensity]);

  return (
    <div style={{ transform: `translateX(${offset}px)` }}>
      {children}
    </div>
  );
}

Physics Engine Simulation

More realistic jitter can incorporate physics parameters:

  1. Velocity Decay Model:
let velocity = 0;
let position = 0;
const friction = 0.9;

function physicsShake() {
  // Apply random force
  velocity += (Math.random() - 0.5) * 2;
  
  // Apply physics
  velocity *= friction;
  position += velocity;
  
  // Limit boundaries
  if(Math.abs(position) > 15) {
    position = Math.sign(position) * 15;
    velocity *= -0.5;
  }
  
  document.body.style.transform = `translateX(${position}px)`;
  requestAnimationFrame(physicsShake);
}

physicsShake();
  1. Spring Jitter Model:
let position = 0;
let velocity = 0;
const spring = 0.1;
const damping = 0.8;

function springShake() {
  // Random target position
  const target = Math.random() * 20 - 10;
  
  // Spring physics
  const acceleration = (target - position) * spring;
  velocity += acceleration;
  velocity *= damping;
  position += velocity;
  
  document.body.style.transform = `translateX(${position}px)`;
  requestAnimationFrame(springShake);
}

springShake();

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.