0 Admin اخر تحديث : Hair Dryer 3D Pro - معزول 0 ? m + ":" : "") + (s < 10 && m > 0 ? "0" : "") + s + "s"; tv.className = "timer-val " + (timerSec <= 20 ? "urgent" : "running"); } function buildLEDs(n) { var s = document.getElementById("ledStrip"); for (var i = 0; i < n; i++) { var d = document.createElement("div"); d.className = "led-dot"; d.id = "ld" + i; s.appendChild(d); } } buildLEDs(22); function buildDust() { var w = document.getElementById("dustWrap"); var cols = ["#c084c8", "#e879f9", "#9333a0", "#f5c842", "#a78bfa", "#60a5fa"]; for (var i = 0; i < 28; i++) { var d = document.createElement("div"); d.className = "dust"; var sz = Math.random() * 3 + 0.8; d.style.cssText = "width:" + sz + "px;height:" + sz + "px;left:" + (Math.random() * 100) + "%;background:" + cols[Math.floor(Math.random() * cols.length)] + ";animation-duration:" + (7 + Math.random() * 13) + "s;animation-delay:" + (Math.random() * 10) + "s;filter:blur(" + (Math.random() * 1.2) + "px)"; w.appendChild(d); } } buildDust(); function renderIntSlider(v) { var pct = ((v - 10) / 90 * 100).toFixed(1) + "%"; document.getElementById("intVal").textContent = v + "%"; document.getElementById("intSlider").style.setProperty("--fill", pct); } renderIntSlider(50); function renderFreqSlider(v) { var pct = ((v - 100) / 200 * 100).toFixed(1) + "%"; document.getElementById("freqVal").textContent = v + " Hz"; document.getElementById("freqSlider").style.setProperty("--fill", pct); var h = document.getElementById("freqHint"); if (v >= 160 && v <= 170) h.textContent = "تنظيف السبيكر ★★★"; else if (v >= 100 && v <= 130) h.textContent = "اهتزاز ناعم ◈"; else if (v >= 131 && v <= 200) h.textContent = "اهتزاز قوي ◈◈"; else if (v >= 201 && v <= 250) h.textContent = "اهتزاز شديد ◈◈◈"; else h.textContent = "اهتزاز فائق ◈◈◈◈"; } renderFreqSlider(165); document.getElementById("btnPwr").addEventListener("click", togglePower); document.getElementById("btnTurbo").addEventListener("click", toggleTurbo); document.getElementById("pwrSwG").addEventListener("click", togglePower); document.getElementById("turboBtnG").addEventListener("click", toggleTurbo); document.getElementById("intSlider").addEventListener("input", function () { setIntensity(this.value); }); document.getElementById("freqSlider").addEventListener("input", function () { setFrequency(this.value); }); var scene = document.querySelector(".dryer-scene"); scene.addEventListener("mousemove", function (e) { if (ON) return; var r = scene.getBoundingClientRect(); var dx = (e.clientX - r.left - r.width / 2) / (r.width / 2) * 8; var dy = (e.clientY - r.top - r.height / 2) / (r.height / 2) * 5; document.getElementById("dryerSVG").setAttribute("viewBox", dx + " " + dy + " 500 320"); }); scene.addEventListener("mouseleave", function () { document.getElementById("dryerSVG").setAttribute("viewBox", "0 0 500 320"); }); function togglePower() { ON = !ON; if (!ON) TURBO = false; if (ON) startTimer(); else stopTimer(); applyStateWithHeat(); } function toggleTurbo() { if (!ON) { ON = true; startTimer(); } TURBO = !TURBO; applyStateWithHeat(); } function setIntensity(v) { LEVEL = parseInt(v); renderIntSlider(LEVEL); updateLEDs(); if (ON) { if (oscillator) oscillator.frequency.setTargetAtTime(getOscFreq(), audioCtx.currentTime, 0.05); if (gainNode) gainNode.gain.setTargetAtTime(getGain(), audioCtx.currentTime, 0.05); restartVib(); } } function setFrequency(v) { FREQ = parseInt(v); renderFreqSlider(FREQ); if (ON) { if (oscillator) oscillator.frequency.setTargetAtTime(FREQ, audioCtx.currentTime, 0.05); restartVib(); } } function applyState() { var dg = document.getElementById("dryerSVG"), btnPwr = document.getElementById("btnPwr"), btnTurbo = document.getElementById("btnTurbo"), statusBar = document.getElementById("statusBar"), freqBadge = document.getElementById("freqBadge"); var pwrKnob = document.getElementById("pwrKnob"), pwrLed = document.getElementById("pwrLed"), turboLed = document.getElementById("turboLed"), mouthHeat = document.getElementById("mouthHeat"), heatAO = document.getElementById("heatAmbientOuter"); if (ON) { btnPwr.classList.add("on"); btnPwr.textContent = "⏻ إيقاف"; dg.classList.add("vib"); pwrKnob.setAttribute("cx", "35"); pwrKnob.setAttribute("fill", "url(#knobGradOn)"); pwrKnob.setAttribute("filter", "url(#glowF)"); pwrLed.setAttribute("fill", "#00ff88"); pwrLed.style.filter = "drop-shadow(0 0 5px #00ff88)"; var hg = document.getElementById("heatGrad"); if (hg) { hg.children[0].setAttribute("stop-opacity", (0.5 + LEVEL / 200).toFixed(2)); hg.children[1].setAttribute("stop-opacity", (0.6 + LEVEL / 200).toFixed(2)); hg.children[2].setAttribute("stop-opacity", (0.7 + LEVEL / 200).toFixed(2)); hg.children[3].setAttribute("stop-opacity", (0.5 + LEVEL / 200).toFixed(2)); } mouthHeat.setAttribute("opacity", "1"); heatAO.setAttribute("opacity", (0.4 + LEVEL / 200).toFixed(2)); if (TURBO) { btnTurbo.classList.add("on"); btnTurbo.textContent = "⚡ Turbo مفعّل"; turboLed.setAttribute("fill", "#ffc840"); turboLed.style.filter = "drop-shadow(0 0 6px #ffc840)"; statusBar.className = "status turbo-live"; statusBar.textContent = "⚡ TURBO"; heatAO.setAttribute("opacity", "0.85"); } else { btnTurbo.classList.remove("on"); btnTurbo.textContent = "⚡ Turbo"; turboLed.setAttribute("fill", "#1a0505"); turboLed.style.filter = "none"; statusBar.className = "status live"; statusBar.textContent = "● يعمل — جارٍ التجفيف"; } startFan(); startAir(); startSound(); startVib(); freqBadge.classList.add("active"); freqBadge.textContent = "🔊 " + FREQ + " Hz — تشغيل"; } else { btnPwr.classList.remove("on"); btnPwr.textContent = "⏻ تشغيل"; btnTurbo.classList.remove("on"); btnTurbo.textContent = "⚡ Turbo"; dg.classList.remove("vib"); pwrKnob.setAttribute("cx", "11"); pwrKnob.setAttribute("fill", "url(#knobGradOff)"); pwrKnob.removeAttribute("filter"); pwrLed.setAttribute("fill", "#1a0028"); pwrLed.style.filter = "none"; turboLed.setAttribute("fill", "#1a0505"); turboLed.style.filter = "none"; mouthHeat.setAttribute("opacity", "0"); heatAO.setAttribute("opacity", "0"); statusBar.className = "status"; statusBar.textContent = "في وضع الاستعداد"; stopFan(); stopAir(); stopSound(); stopVib(); freqBadge.classList.remove("active"); freqBadge.textContent = "🔊 صوت: إيقاف"; } updateLEDs(); } function startFan() { if (fanRafId) { cancelAnimationFrame(fanRafId); fanRafId = null; } lastFanTime = performance.now(); function loop(t) { if (!ON) { fanRafId = null; return; } var dt = Math.min(t - lastFanTime, 50); lastFanTime = t; var rpm = TURBO ? (8000 + (FREQ - 100) * 15) : (400 + LEVEL * 45 + (FREQ - 100) * 5); fanAngle = (fanAngle + rpm / 60000 * 360 * dt) % 360; document.getElementById("fanBlades").setAttribute("transform", "rotate(" + fanAngle + ")"); fanRafId = requestAnimationFrame(loop); } fanRafId = requestAnimationFrame(loop); } function stopFan() { if (fanRafId) { cancelAnimationFrame(fanRafId); fanRafId = null; } } var acv = document.getElementById("airCanvas"), actx = acv.getContext("2d"), MX = 118, MY = 178, MH = 52; function AP() { this.x = MX + 1; this.y = MY + (Math.random() - 0.5) * MH * 0.9; var spd = TURBO ? (4 + Math.random() * 5) : ((0.6 + LEVEL / 100) * (1.5 + Math.random() * 2)); this.vx = -spd; this.vy = (Math.random() - 0.5) * (TURBO ? 1.8 : 0.9); this.life = 1; this.decay = 0.009 + Math.random() * 0.016; this.r = Math.random() * 2.2 + 0.6; var hot = LEVEL > 45; if (hot) { var g = Math.floor(50 + Math.random() * 90); this.col = "rgb(" + (220 + Math.floor(Math.random() * 35)) + "," + g + ",15)"; } else { this.col = "rgb(" + (60 + Math.floor(Math.random() * 60)) + "," + (160 + Math.floor(Math.random() * 70)) + "," + (210 + Math.floor(Math.random() * 45)) + ")"; } } AP.prototype.update = function () { this.x += this.vx; this.y += this.vy; this.vy += (Math.random() - 0.5) * 0.12; this.vx *= 0.993; this.life -= this.decay + (TURBO ? 0.003 : 0); }; AP.prototype.draw = function (cx) { cx.globalAlpha = Math.max(0, this.life * 0.75); cx.fillStyle = this.col; cx.shadowColor = this.col; cx.shadowBlur = 5; cx.beginPath(); cx.arc(this.x, this.y, this.r, 0, Math.PI * 2); cx.fill(); }; function startAir() { if (airRafId) return; airLoop(); } function stopAir() { if (airRafId) { cancelAnimationFrame(airRafId); airRafId = null; } actx.clearRect(0, 0, acv.width, acv.height); airParticles = []; } function airLoop() { actx.clearRect(0, 0, acv.width, acv.height); actx.shadowBlur = 0; var spawn = TURBO ? 14 : Math.ceil(LEVEL / 11); for (var i = 0; i < spawn; i++) airParticles.push(new AP()); airParticles = airParticles.filter(function (p) { p.update(); if (p.life > 0 && p.x > -5) { p.draw(actx); return true; } return false; }); var hot = LEVEL > 45; for (var i = 0; i < 3; i++) { var gx = MX - 20 - Math.random() * 50, gy = MY + (Math.random() - 0.5) * 60; var gr = actx.createRadialGradient(gx, gy, 0, gx, gy, 22 + Math.random() * 16); var a = (hot ? 0.06 : 0.04) * (LEVEL / 100) * (TURBO ? 1.6 : 1); gr.addColorStop(0, hot ? "rgba(255,90,20," + a + ")" : "rgba(80,160,255," + a + ")"); gr.addColorStop(1, "transparent"); actx.globalAlpha = 1; actx.fillStyle = gr; actx.fillRect(gx - 40, gy - 40, 80, 80); } actx.globalAlpha = 1; actx.shadowBlur = 0; airRafId = ON ? requestAnimationFrame(airLoop) : null; } function getOscFreq() { return FREQ; } function getGain() { return Math.min(TURBO ? (0.04 + LEVEL / 100 * 0.08) : (0.012 + LEVEL / 100 * 0.035), 0.12); } function startSound() { try { if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); if (audioCtx.state === "suspended") audioCtx.resume(); if (oscillator) { oscillator.disconnect(); oscillator = null; } gainNode = audioCtx.createGain(); gainNode.gain.setValueAtTime(0, audioCtx.currentTime); gainNode.connect(audioCtx.destination); oscillator = audioCtx.createOscillator(); oscillator.type = "square"; oscillator.frequency.setValueAtTime(getOscFreq(), audioCtx.currentTime); oscillator.connect(gainNode); oscillator.start(); gainNode.gain.linearRampToValueAtTime(getGain(), audioCtx.currentTime + 0.35); var bufSz = audioCtx.sampleRate * 0.5, buf = audioCtx.createBuffer(1, bufSz, audioCtx.sampleRate), data = buf.getChannelData(0); for (var i = 0; i < bufSz; i++) data[i] = (Math.random() * 2 - 1) * 0.3; var noise = audioCtx.createBufferSource(); noise.buffer = buf; noise.loop = true; var noiseGain = audioCtx.createGain(); noiseGain.gain.setValueAtTime(0.004 + LEVEL / 100 * 0.008, audioCtx.currentTime); var bpf = audioCtx.createBiquadFilter(); bpf.type = "bandpass"; bpf.frequency.value = FREQ * 1.8; bpf.Q.value = 2; noise.connect(bpf); bpf.connect(noiseGain); noiseGain.connect(gainNode); noise.start(); } catch (e) {} } function stopSound() { try { if (gainNode) gainNode.gain.linearRampToValueAtTime(0, (audioCtx ? audioCtx.currentTime : 0) + 0.3); setTimeout(function () { if (oscillator) { try { oscillator.disconnect(); } catch (e) {} oscillator = null; } if (gainNode) { try { gainNode.disconnect(); } catch (e) {} gainNode = null; } }, 350); } catch (e) {} } function getVibPattern() { let basePulse = Math.max(40, Math.min(180, Math.round(4000 / FREQ))); let intensityFactor = LEVEL / 50; let pulse = Math.min(200, Math.round(basePulse * intensityFactor)); if (TURBO) pulse = Math.min(250, pulse * 1.8); let pause = 25; let repeats = TURBO ? 8 : 5; let pattern = []; for (let i = 0; i < repeats; i++) { pattern.push(pulse, pause); } pattern.pop(); return pattern; } function startVib() { stopVib(); if (!navigator.vibrate || !ON) return; navigator.vibrate(getVibPattern()); vibInterval = setInterval(() => { if (ON && navigator.vibrate) { navigator.vibrate(getVibPattern()); } else { stopVib(); } }, 2500); } function restartVib() { if (ON) { stopVib(); startVib(); } } function stopVib() { clearInterval(vibInterval); vibInterval = null; if (navigator.vibrate) navigator.vibrate(0); } function updateLEDs() { var n = 22, lit = Math.round((LEVEL / 100) * n); for (var i = 0; i < n; i++) { var d = document.getElementById("ld" + i); d.style.background = "rgba(0,0,0,0.08)"; d.style.boxShadow = "none"; if (ON && i < lit) { if (i < n * 0.38) { d.style.background = "#00ee80"; d.style.boxShadow = "0 0 5px #00ee80"; } else if (i < n * 0.72) { d.style.background = "#ffc030"; d.style.boxShadow = "0 0 5px #ffc030"; } else { d.style.background = "#ff3030"; d.style.boxShadow = "0 0 5px #ff3030"; } } } } var heatT = 0, heatRafId = null; function heatPulse() { if (!ON) { heatRafId = null; return; } heatT += 0.07; var pulse = 0.75 + Math.sin(heatT) * 0.25; document.getElementById("mouthHeat").setAttribute("opacity", pulse.toFixed(3)); var ha = document.getElementById("heatAmbientOuter"); ha.setAttribute("opacity", ((TURBO ? 0.85 : 0.4 + LEVEL / 200) * pulse).toFixed(3)); heatRafId = requestAnimationFrame(heatPulse); } function applyStateWithHeat() { if (ON && navigator.vibrate) navigator.vibrate([80, 40, 80, 40, 120]); applyState(); if (ON && !heatRafId) { heatRafId = requestAnimationFrame(heatPulse); } else if (!ON && heatRafId) { cancelAnimationFrame(heatRafId); heatRafId = null; } } ' title="Hair Dryer 3D Pro" scrolling="auto" allow="autoplay" sandbox="allow-scripts allow-same-origin allow-modals allow-popups" allowfullscreen >