ai

App thổi nến sinh nhật —

App thổi nến sinh nhật —

App เป่าเทียน

App thổi nến sinh nhật —

App เป่าเทียนวันเกิด Blow Detection Microphone Web Audio API Animation Canvas CSS Confetti Mobile React Native Flutter Production

TechnologyPlatformBlow DetectionAnimationDifficulty
Web Audio API + CanvasWeb BrowserAnalyserNodeCanvas/CSSปานกลาง
React + Web AudioWeb (React)Custom HookFramer Motionปานกลาง
React Native + ExpoiOS Androidexpo-avReanimatedปานกลาง
FlutteriOS Androidaudio_streamerCustomPainterปานกลาง
Swift (iOS Native)iOSAVAudioEngineSpriteKitสูง
Kotlin (Android)AndroidAudioRecordCanvasสูง

Blow Detection

=== Web Audio Blow Detection ===

JavaScript Implementation

async function initBlowDetection(onBlow) {

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });

const audioContext = new AudioContext();

const source = audioContext.createMediaStreamSource(stream);

const analyser = audioContext.createAnalyser();

analyser.fftSize = 2048;

analyser.smoothingTimeConstant = 0.8;

source.connect(analyser);

const bufferLength = analyser.frequencyBinCount;

const dataArray = new Uint8Array(bufferLength);

const BLOW_THRESHOLD = 150; // 0-255

const LOW_FREQ_START = 5; // ~200Hz

const LOW_FREQ_END = 15; // ~500Hz

let isBlowing = false;

let blowTimeout = null;

function detectBlow() {

analyser.getByteFrequencyData(dataArray);

Focus on low frequencies (blow sound range)

let sum = 0;

for (let i = LOW_FREQ_START; i < LOW_FREQ_END; i++) {

sum += dataArray[i];

}

const average = sum / (LOW_FREQ_END - LOW_FREQ_START);

if (average > BLOW_THRESHOLD && !isBlowing) {

isBlowing = true;

onBlow();

blowTimeout = setTimeout(() => { isBlowing = false; }, 1000);

}

requestAnimationFrame(detectBlow);

}

detectBlow();

}

Usage

initBlowDetection(() => {

console.log('Blow detected! Extinguish candles!');

extinguishCandles();

เนื้อหาเกี่ยวข้อง — Overclock RAM — คู่มือฉบับสมบูรณ์ 2026

});

from dataclasses import dataclass

@dataclass

class AudioConfig:

param: str

value: str

purpose: str

configs = [

AudioConfig("fftSize", "2048", "Frequency resolution — higher = more precise"),

AudioConfig("smoothingTimeConstant", "0.8", "Smooth frequency data — reduce noise"),

AudioConfig("BLOW_THRESHOLD", "150 (0-255)", "Volume level to trigger blow detection"),

แนะนำเพิ่มเติม — หนังสือเทรดที่ SiamCafeBook

AudioConfig("LOW_FREQ_START", "5 (~200Hz)", "Start of blow frequency range"),

AudioConfig("LOW_FREQ_END", "15 (~500Hz)", "End of blow frequency range"),

AudioConfig("Debounce", "1000ms", "Prevent multiple triggers from single blow"),

]

print("=== Audio Configuration ===")

for c in configs:

print(f" [{c.param}] Value: {c.value}")

print(f" Purpose: {c.purpose}")

Candle Animation

=== CSS Candle Animation ===

/* Candle Base */

.candle {

width: 30px;

height: 120px;

background: linear-gradient(to bottom, #fff3b0, #ffd700);

border-radius: 3px 3px 0 0;

position: relative;

margin: 0 15px;

}

/* Flame */

.flame {

width: 20px;

height: 40px;

background: radial-gradient(ellipse at bottom,

#ff6600 0%, #ffcc00 40%, transparent 70%);

border-radius: 50% 50% 30% 30%;

position: absolute;

top: -45px;

left: 50%;

transform: translateX(-50%);

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ Go Cobra CLI Machine Learning Pipeline

animation: flicker 0.3s infinite alternate;

transition: opacity 0.5s, transform 0.5s;

}

@keyframes flicker {

0% { transform: translateX(-50%) scale(1) rotate(-2deg); }

50% { transform: translateX(-50%) scale(1.05) rotate(1deg); }

100% { transform: translateX(-50%) scale(0.95) rotate(-1deg); }

}

/* Extinguished */

.flame.out {

opacity: 0;

transform: translateX(-50%) scale(0);

}

/* Smoke */

.smoke {

width: 4px;

height: 30px;

background: rgba(150, 150, 150, 0.3);

position: absolute;

top: -50px;

แนะนำเพิ่มเติม — สัญญาณเทรดรายวัน XM Signal

left: 50%;

transform: translateX(-50%);

opacity: 0;

animation: smoke-rise 2s ease-out forwards;

}

@keyframes smoke-rise {

0% { opacity: 0.8; transform: translateX(-50%) translateY(0); }

100% { opacity: 0; transform: translateX(-50%) translateY(-40px); }

}

Confetti Animation (JavaScript)

function createConfetti(count = 100) {

for (let i = 0; i < count; i++) {

const confetti = document.createElement('div');

confetti.className = 'confetti';

confetti.style.left = Math.random() * 100 + 'vw';

confetti.style.background = `hsl(, 80%, 60%)`;

confetti.style.animationDuration = Math.random() * 2 + 1 + 's';

confetti.style.animationDelay = Math.random() * 0.5 + 's';

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ หุ้น บัวหลวง กับเทรนด์เทคโนโลยีใหม่: โอกาสการลงทุนในยุคดิจิทัล

document.body.appendChild(confetti);

setTimeout(() => confetti.remove(), 3000);

}

}

@dataclass

class AnimationLayer:

element: str

technique: str

trigger: str

duration: str

layers = [

AnimationLayer("Flame flicker", "CSS @keyframes + transform", "Always (while lit)", "0.3s infinite"),

AnimationLayer("Flame glow", "CSS radial-gradient + box-shadow", "Always (while lit)", "0.5s infinite"),

AnimationLayer("Extinguish", "CSS transition opacity + scale", "On blow detect", "0.5s ease-out"),

AnimationLayer("Smoke trail", "CSS @keyframes translateY", "After extinguish", "2s ease-out"),

AnimationLayer("Confetti", "JS DOM + CSS @keyframes", "All candles out", "1-3s random"),

AnimationLayer("Happy Birthday", "Audio play()", "All candles out", "30s"),

]

print("\n=== Animation Layers ===")

for a in layers:

print(f" [{a.element}] Tech: {a.technique}")

print(f" Trigger: {a.trigger} | Duration: {a.duration}")

Mobile Development

App thổi nến sinh nhật —

=== React Native / Flutter Implementation ===

React Native (Expo) — Blow Detection

import { Audio } from 'expo-av';

const startBlowDetection = async () => {

const { status } = await Audio.requestPermissionsAsync();

if (status !== 'granted') return;

const recording = new Audio.Recording();

await recording.prepareToRecordAsync({

android: { ...Audio.RecordingOptionsPresets.HIGH_QUALITY.android },

ios: { ...Audio.RecordingOptionsPresets.HIGH_QUALITY.ios },

});

recording.setOnRecordingStatusUpdate((status) => {

if (status.metering && status.metering > -20) {

Blow detected (metering is in dB, -160 to 0)

handleBlow();

}

});

await recording.startAsync();

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน เหรียญ ADA — คู่มือฉบับสมบูรณ์ 2026

};

Flutter — Blow Detection

import 'package:audio_streamer/audio_streamer.dart';

class BlowDetector {

final AudioStreamer _streamer = AudioStreamer();

final double _threshold = 0.5;

void start(VoidCallback onBlow) {

_streamer.start((List<double> samples) {

double rms = _calculateRMS(samples);

if (rms > _threshold) {

onBlow();

}

});

}

double _calculateRMS(List<double> samples) {

double sum = 0;

for (var s in samples) { sum += s * s; }

return sqrt(sum / samples.length);

}

}

@dataclass

class AppFeature:

feature: str

web: str

react_native: str

flutter: str

features = [

AppFeature("Mic Access", "getUserMedia()", "expo-av Audio", "audio_streamer"),

AppFeature("Blow Detect", "AnalyserNode FFT", "metering dB", "RMS calculation"),

AppFeature("Animation", "CSS + Canvas", "Reanimated + Lottie", "CustomPainter"),

AppFeature("Haptic", "navigator.vibrate()", "expo-haptics", "HapticFeedback"),

AppFeature("Sound", "Audio() play()", "expo-av Sound", "audioplayers"),

AppFeature("Share", "Web Share API", "expo-sharing", "share_plus"),

]

print("Cross-platform Comparison:")

for f in features:

print(f" [{f.feature}]")

print(f" Web: {f.web} | RN: {f.react_native} | Flutter: {f.flutter}")

เคล็ดลับ

  • Frequency: กรอง Low Frequency 200-500Hz สำหรับลมเป่า
  • Debounce: ตั้ง Debounce 1 วินาทีป้องกัน Trigger ซ้ำ
  • Permission: ขอสิทธิ์ Microphone ก่อนเริ่มเสมอ
  • Animation: ใช้ CSS Animation สำหรับ Performance ที่ดี
  • UX: เพิ่ม Fallback ปุ่มกดสำหรับกรณี Mic ไม่ทำงาน

App เป่าเทียนวันเกิดคืออะไร

แอป Microphone ตรวจลมเป่า Blow Detection Web Audio API เทียนดับ Animation เปลวไฟ ควัน Confetti Canvas CSS วันเกิด ปาร์ตี้ อวยพร

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง