{"id":1731,"date":"2025-12-05T16:17:46","date_gmt":"2025-12-05T13:17:46","guid":{"rendered":"https:\/\/kominikee.com\/?p=1731"},"modified":"2025-12-05T16:30:43","modified_gmt":"2025-12-05T13:30:43","slug":"testttt","status":"publish","type":"post","link":"https:\/\/kominikee.com\/en\/testttt\/","title":{"rendered":"testttt"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"1731\" class=\"elementor elementor-1731\" data-elementor-post-type=\"post\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-67f43ee elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"67f43ee\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-760a97f\" data-id=\"760a97f\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-aff3005 elementor-widget elementor-widget-html\" data-id=\"aff3005\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Hand-Tracking 3D Particles<\/title>\n    <!-- Load Tailwind CSS -->\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <!-- Load Three.js -->\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"><\/script>\n    <!-- Load MediaPipe Hands -->\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@mediapipe\/hands@0.4\/hands.js\"><\/script>\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@mediapipe\/camera_utils@0.3\/camera_utils.js\"><\/script>\n    <!-- HATA \u00c7\u00d6Z\u00dcM\u00dc: DrawingUtils art\u0131k gerekli de\u011fil. -->\n    <style>\n        body {\n            margin: 0;\n            overflow: hidden;\n            font-family: 'Inter', sans-serif;\n            background-color: #0d0d1f; \/* Dark background for the 3D scene *\/\n        }\n        #webgl-canvas {\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100vw;\n            height: 100vh;\n            z-index: 10;\n        }\n        \/* YEN\u0130: Kamera g\u00f6r\u00fcnt\u00fcs\u00fc i\u00e7in yerle\u015fim ve boyut *\/\n        #webcam-container {\n            position: fixed;\n            bottom: 10px;\n            right: 10px;\n            width: 160px; \/* K\u00fc\u00e7\u00fck \u00f6nizleme *\/\n            height: 90px;\n            z-index: 50; \/* Kontrollerin \u00fczerinde olsun *\/\n            border-radius: 8px;\n            overflow: hidden;\n            border: 2px solid rgba(59, 130, 246, 0.5);\n            opacity: 0.8;\n        }\n        #webcam-video {\n            \/* Video \u00f6\u011fesini gizli tutuyoruz, \u00e7izim i\u00e7in canvas kullanaca\u011f\u0131z. *\/\n            display: none; \n        }\n        \/* YEN\u0130: Video ak\u0131\u015f\u0131n\u0131 kopyalamak i\u00e7in gizli canvas *\/\n        #video-processing-canvas {\n            display: none;\n        }\n        #webcam-canvas-debug {\n            \/* Video \u00f6nizlemesi i\u00e7in kullanaca\u011f\u0131m\u0131z canvas. *\/\n            display: block; \n            width: 100%;\n            height: 100%;\n            transform: scaleX(-1); \/* G\u00f6r\u00fcnt\u00fcy\u00fc ayna gibi \u00e7evir *\/\n        }\n        #controls-panel {\n            z-index: 20;\n            backdrop-filter: blur(8px);\n            background-color: rgba(255, 255, 255, 0.1);\n        }\n        .control-button {\n            transition: all 0.2s;\n            cursor: pointer;\n        }\n        .control-button.active {\n            background-color: #3b82f6;\n            color: white;\n            box-shadow: 0 4px 6px rgba(59, 130, 246, 0.5);\n        }\n    <\/style>\n<\/head>\n<body class=\"text-gray-100\">\n\n    <!-- Three.js Canvas -->\n    <canvas id=\"webgl-canvas\"><\/canvas>\n\n    <!-- HATA AYIKLAMA: Kamera G\u00f6r\u00fcnt\u00fcs\u00fc ve MediaPipe Girdisi \u0130\u00e7in -->\n    <div id=\"webcam-container\">\n        <!-- Video ak\u0131\u015f\u0131 buraya aktar\u0131lacak (Gizli) -->\n        <video id=\"webcam-video\" autoplay playsinline><\/video>\n        <!-- \u00d6nizleme Canvas'\u0131 (G\u00f6r\u00fcn\u00fcr) -->\n        <canvas id=\"webcam-canvas-debug\"><\/canvas>\n    <\/div>\n    \n    <!-- YEN\u0130: MediaPipe'\u0131n as\u0131l girdi alaca\u011f\u0131 gizli canvas -->\n    <canvas id=\"video-processing-canvas\" width=\"1280\" height=\"720\"><\/canvas>\n    \n    <!-- Controls Panel -->\n    <div id=\"controls-panel\" class=\"fixed top-4 right-4 p-4 rounded-xl shadow-2xl max-w-xs w-full sm:w-80\">\n        <h1 class=\"text-xl font-bold mb-3 text-blue-300\">3D Particle Maestro<\/h1>\n        <p class=\"text-xs mb-4 text-gray-300\">Use your hand in the camera view to control particle dispersion (close your hand to expand).<\/p>\n\n        <!-- Shape Selector -->\n        <div class=\"mb-4\">\n            <label class=\"block text-sm font-medium mb-2 text-blue-200\">Particle Template<\/label>\n            <div id=\"shape-selector\" class=\"flex space-x-2\">\n                <button data-shape=\"Hearts\" class=\"control-button px-3 py-1 text-sm bg-gray-700 hover:bg-gray-600 rounded-full active\">Hearts<\/button>\n                <button data-shape=\"Saturn\" class=\"control-button px-3 py-1 text-sm bg-gray-700 hover:bg-gray-600 rounded-full\">Saturn<\/button>\n                <button data-shape=\"Fireworks\" class=\"control-button px-3 py-1 text-sm bg-gray-700 hover:bg-gray-600 rounded-full\">Fireworks<\/button>\n            <\/div>\n        <\/div>\n\n        <!-- Color Picker -->\n        <div class=\"mb-4\">\n            <label for=\"color-picker\" class=\"block text-sm font-medium mb-2 text-blue-200\">Particle Color<\/label>\n            <div class=\"flex items-center\">\n                <input type=\"color\" id=\"color-picker\" value=\"#ff66b2\" class=\"w-10 h-10 p-1 border-2 border-gray-700 rounded-lg bg-gray-800 cursor-pointer\">\n                <span class=\"ml-3 text-sm text-gray-300\">Dynamic Color<\/span>\n            <\/div>\n        <\/div>\n\n        <!-- Dispersion Indicator -->\n        <div class=\"mt-4\">\n            <label class=\"block text-sm font-medium mb-1 text-blue-200\">Hand Dispersion<\/label>\n            <div class=\"w-full bg-gray-700 rounded-full h-2.5\">\n                <div id=\"dispersion-bar\" class=\"bg-red-400 h-2.5 rounded-full transition-all duration-100 ease-linear\" style=\"width: 0%\"><\/div>\n            <\/div>\n        <\/div>\n\n        <!-- HATA AYIKLAMA DURUMU -->\n        <div class=\"mt-4 p-2 text-xs rounded\" id=\"debug-status\">\n            <span class=\"font-bold text-yellow-300\">Status:<\/span> Waiting for hand...\n        <\/div>\n    <\/div>\n\n    <!-- Message Box (Error\/Status) -->\n    <div id=\"message-box\" class=\"fixed bottom-4 left-1\/2 transform -translate-x-1\/2 p-3 bg-red-600 text-white rounded-lg shadow-lg hidden z-50\"><\/div>\n\n\n    <script type=\"module\">\n        \/\/ Global Constants and Configuration\n        const NUM_PARTICLES = 50000;\n        const PARTICLE_SIZE = 15.0;\n        const TARGET_MORPH_SPEED = 0.03;\n        \/\/ D\u00fczeltme: Parmak mesafesi alg\u0131lama aral\u0131\u011f\u0131 geni\u015fletildi.\n        const HAND_DISTANCE_MIN = 0.01; \/\/ Min distance (closed hand) - Normalle\u015ftirilmi\u015f 0-1 aral\u0131\u011f\u0131na uygun hale getirildi\n        const HAND_DISTANCE_MAX = 0.25; \/\/ Max distance (open hand) - Normalle\u015ftirilmi\u015f 0-1 aral\u0131\u011f\u0131na uygun hale getirildi\n\n        \/\/ Three.js Variables\n        let scene, camera, renderer, particles;\n        let initialPositions, targetPositions, initialColors; \n        let raycaster, mouse, INTERSECTED;\n\n        \/\/ MediaPipe Variables\n        const videoElement = document.getElementById('webcam-video');\n        const debugCanvas = document.getElementById('webcam-canvas-debug');\n        const debugCtx = debugCanvas.getContext('2d');\n\n        const processingCanvas = document.getElementById('video-processing-canvas');\n        const processingCtx = processingCanvas.getContext('2d');\n        \n        const canvasElement = document.getElementById('webgl-canvas');\n        const dispersionBar = document.getElementById('dispersion-bar');\n        const debugStatus = document.getElementById('debug-status');\n        let currentHandDispersion = 0.0; \/\/ 0.0 (closed) to 1.0 (open)\n        let isSetupComplete = false;\n        let morphFactor = 0.0;\n        let targetShape = 'Hearts';\n\n        \/\/ Helper function for message box (non-alert)\n        function showMessage(text, duration = 3000, isError = false) {\n            const msgBox = document.getElementById('message-box');\n            msgBox.textContent = text;\n            msgBox.className = `fixed bottom-4 left-1\/2 transform -translate-x-1\/2 p-3 text-white rounded-lg shadow-lg z-50 transition-opacity duration-300 ${isError ? 'bg-red-600' : 'bg-blue-600'} block`;\n            \n            setTimeout(() => {\n                msgBox.classList.add('hidden');\n            }, duration);\n        }\n\n        \/\/ --- 3D Shape Generation Functions ---\n\n        \/\/ Generates positions for a Heart shape using a polar equation\n        function createHeartPositions() {\n            const positions = new Float32Array(NUM_PARTICLES * 3);\n            const scale = 150;\n\n            for (let i = 0; i < NUM_PARTICLES; i++) {\n                const t = Math.random() * 2 * Math.PI;\n                const r = Math.random() * 0.5 + 0.5; \/\/ Randomize radius slightly\n\n                \/\/ Polar equation for heart shape: r = 16*sin^3(t), y = 13*cos(t) - 5*cos(2t) - 2*cos(3t) - cos(4t)\n                let x = scale * 16 * Math.pow(Math.sin(t), 3) * r;\n                let y = scale * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t)) * r;\n                let z = (Math.random() - 0.5) * 50; \/\/ Add some depth\n\n                positions[i * 3 + 0] = x;\n                positions[i * 3 + 1] = y - scale * 6; \/\/ Center the heart vertically\n                positions[i * 3 + 2] = z;\n            }\n            return positions;\n        }\n\n        \/\/ Generates positions for a Saturn-like ring\n        function createSaturnPositions() {\n            const positions = new Float32Array(NUM_PARTICLES * 3);\n            const radius = 250;\n            const ringThickness = 100;\n\n            for (let i = 0; i < NUM_PARTICLES; i++) {\n                const angle = Math.random() * Math.PI * 2;\n                const r = radius + Math.random() * ringThickness - (ringThickness \/ 2);\n                \n                \/\/ Position particles on a flat plane (XY)\n                const x = r * Math.cos(angle);\n                const y = r * Math.sin(angle);\n                const z = (Math.random() - 0.5) * 20; \/\/ Slight Z deviation for ring thickness\n\n                positions[i * 3 + 0] = x;\n                positions[i * 3 + 1] = y;\n                positions[i * 3 + 2] = z;\n            }\n            return positions;\n        }\n\n        \/\/ Generates random positions for a 'Fireworks' explosion (spherical dispersion)\n        function createFireworksPositions() {\n            const positions = new Float32Array(NUM_PARTICLES * 3);\n            const explosionRadius = 300;\n\n            for (let i = 0; i < NUM_PARTICLES; i++) {\n                \/\/ Spherical coordinates conversion\n                const u = Math.random(); \/\/ inclination\n                const v = Math.random(); \/\/ azimuth\n                const r = Math.pow(Math.random(), 1\/3) * explosionRadius; \/\/ Ensures even distribution\n\n                const theta = u * 2 * Math.PI;\n                const phi = Math.acos(2 * v - 1);\n\n                const x = r * Math.sin(phi) * Math.cos(theta);\n                const y = r * Math.sin(phi) * Math.sin(theta);\n                const z = r * Math.cos(phi);\n\n                positions[i * 3 + 0] = x;\n                positions[i * 3 + 1] = y;\n                positions[i * 3 + 2] = z;\n            }\n            return positions;\n        }\n\n        const templateGenerators = {\n            'Hearts': createHeartPositions,\n            'Saturn': createSaturnPositions,\n            'Fireworks': createFireworksPositions\n        };\n\n        \/\/ --- Three.js Setup and Core Logic ---\n\n        function initThree() {\n            \/\/ Scene\n            scene = new THREE.Scene();\n\n            \/\/ Camera (Perspective)\n            const aspect = window.innerWidth \/ window.innerHeight;\n            camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);\n            camera.position.z = 500;\n\n            \/\/ Renderer\n            renderer = new THREE.WebGLRenderer({ antialias: true, canvas: canvasElement, alpha: true });\n            renderer.setSize(window.innerWidth, window.innerHeight);\n            renderer.setPixelRatio(window.devicePixelRatio);\n            renderer.setClearColor(0x0d0d1f, 1);\n\n            \/\/ Initial Particle Setup (Start with Hearts)\n            initialPositions = templateGenerators['Hearts']();\n            targetPositions = new Float32Array(NUM_PARTICLES * 3); \/\/ Will be updated on shape change\n\n            \/\/ Initial Colors (White with alpha variation)\n            initialColors = new Float32Array(NUM_PARTICLES * 3);\n            for (let i = 0; i < NUM_PARTICLES; i++) {\n                initialColors[i * 3] = 1.0; \/\/ R\n                initialColors[i * 3 + 1] = 0.4; \/\/ G\n                initialColors[i * 3 + 2] = 0.7; \/\/ B (Pinkish initial color)\n            }\n\n            \/\/ Geometry\n            const geometry = new THREE.BufferGeometry();\n            geometry.setAttribute('position', new THREE.BufferAttribute(initialPositions, 3));\n            geometry.setAttribute('targetPosition', new THREE.BufferAttribute(initialPositions.slice(), 3));\n            geometry.setAttribute('color', new THREE.BufferAttribute(initialColors, 3));\n            geometry.setAttribute('pId', new THREE.BufferAttribute(new Float32Array(NUM_PARTICLES).map((_, i) => i \/ NUM_PARTICLES), 1));\n            \n            \/\/ Shader Material\n            const particleMaterial = new THREE.ShaderMaterial({\n                uniforms: {\n                    color: { value: new THREE.Color(0xff66b2) }, \/\/ Base color\n                    pointSize: { value: PARTICLE_SIZE },\n                    uTime: { value: 0.0 },\n                    uMorphFactor: { value: 0.0 }, \/\/ Factor from 0 to 1 for morphing\n                    uDispersion: { value: 0.0 } \/\/ Factor from 0 to 1 for hand control\n                },\n                vertexShader: `\n                    uniform float pointSize;\n                    uniform float uTime;\n                    uniform float uMorphFactor;\n                    uniform float uDispersion;\n\n                    attribute vec3 targetPosition;\n                    attribute vec3 color;\n                    attribute float pId;\n\n                    varying vec3 vColor;\n\n                    void main() {\n                        \/\/ Morphing between current (position) and target (targetPosition)\n                        vec3 morphedPosition = mix(position, targetPosition, uMorphFactor);\n\n                        \/\/ Apply dispersion based on hand input\n                        \/\/ We push particles away from the center (0,0,0) based on uDispersion\n                        float dispFactor = uDispersion * 400.0;\n                        morphedPosition += normalize(morphedPosition) * dispFactor * sin(pId * 10.0 + uTime * 0.5);\n\n                        vec4 mvPosition = modelViewMatrix * vec4(morphedPosition, 1.0);\n                        gl_PointSize = pointSize * (100.0 \/ -mvPosition.z);\n                        vColor = color;\n\n                        gl_Position = projectionMatrix * mvPosition;\n                    }\n                `,\n                fragmentShader: `\n                    uniform vec3 color;\n                    varying vec3 vColor;\n\n                    void main() {\n                        float r = 0.0;\n                        vec2 cxy = 2.0 * gl_PointCoord - 1.0;\n                        r = dot(cxy, cxy);\n\n                        \/\/ Soft point fade\n                        if (r > 1.0) discard;\n\n                        \/\/ Use attribute color blended with uniform color\n                        vec3 finalColor = mix(color, vColor, 0.5);\n\n                        gl_FragColor = vec4(finalColor, 1.0 - r);\n                    }\n                `,\n                blending: THREE.AdditiveBlending,\n                depthTest: false,\n                transparent: true\n            });\n\n            particles = new THREE.Points(geometry, particleMaterial);\n            scene.add(particles);\n\n            \/\/ Handle window resize\n            window.addEventListener('resize', onWindowResize, false);\n            onWindowResize();\n        }\n\n        function onWindowResize() {\n            camera.aspect = window.innerWidth \/ window.innerHeight;\n            camera.updateProjectionMatrix();\n            renderer.setSize(window.innerWidth, window.innerHeight);\n        }\n\n        \/\/ --- Particle System Control Functions ---\n\n        function setTargetShape(shapeName) {\n            \/\/ Guard clause to prevent TypeError if called before initThree completes\n            if (!particles || !particles.geometry) {\n                 console.warn(\"setTargetShape called before particles object was fully initialized.\");\n                 return;\n            }\n            \n            if (!templateGenerators[shapeName]) {\n                showMessage(`Shape template \"${shapeName}\" not found.`, 3000, true);\n                return;\n            }\n\n            \/\/ 1. Generate new target positions\n            const newTargetPositions = templateGenerators[shapeName]();\n            \n            \/\/ 2. Get current positions to use as the starting point for the new morph\n            const currentPositions = particles.geometry.attributes.position.array;\n            \n            \/\/ 3. Update the 'targetPosition' attribute in geometry\n            particles.geometry.attributes.targetPosition.array.set(newTargetPositions);\n            particles.geometry.attributes.targetPosition.needsUpdate = true;\n            \n            \/\/ 4. Set the current positions as the old positions and reset morphFactor to 0\n            \/\/ This ensures the morphing starts smoothly from the previous shape\n            particles.geometry.attributes.position.array.set(currentPositions);\n            particles.geometry.attributes.position.needsUpdate = true;\n\n            particles.material.uniforms.uMorphFactor.value = 0.0; \/\/ Reset morph factor\n            morphFactor = 0.0;\n            targetShape = shapeName;\n\n            showMessage(`Switched to ${shapeName} template.`, 1500);\n\n            \/\/ Update UI buttons\n            document.querySelectorAll('.control-button').forEach(btn => {\n                btn.classList.remove('active');\n                if (btn.dataset.shape === shapeName) {\n                    btn.classList.add('active');\n                }\n            });\n        }\n\n        \/\/ --- Main Animation Loop ---\n        function animate(time) {\n            requestAnimationFrame(animate);\n\n            \/\/ Three.js nesnelerinin olu\u015fup olu\u015fmad\u0131\u011f\u0131n\u0131 kontrol et\n            if (!particles || !particles.material) return;\n\n            \/\/ Update Time Uniform\n            particles.material.uniforms.uTime.value = time * 0.001;\n            \n            \/\/ Update Morphing\n            if (morphFactor < 1.0) {\n                morphFactor = Math.min(1.0, morphFactor + TARGET_MORPH_SPEED);\n                particles.material.uniforms.uMorphFactor.value = morphFactor;\n            }\n\n            \/\/ Update Dispersion Uniform (Controlled by MediaPipe)\n            \/\/ currentHandDispersion is 0.0 (open) to 1.0 (closed\/dispersed)\n            particles.material.uniforms.uDispersion.value = THREE.MathUtils.lerp(\n                particles.material.uniforms.uDispersion.value,\n                currentHandDispersion,\n                0.1\n            );\n\n            \/\/ Rotation (Automatic Spin)\n            particles.rotation.y += 0.0005;\n            particles.rotation.z += 0.0002;\n            \n            renderer.render(scene, camera);\n        }\n\n        \/\/ --- MediaPipe Hand Tracking Setup ---\n\n        \/\/ D\u00dcZELTME: locateFile yolu tam olarak belirtildi.\n        const BASE_PATH = 'https:\/\/cdn.jsdelivr.net\/npm\/@mediapipe\/hands@0.4\/';\n        const hands = new Hands({\n            locateFile: (file) => {\n                return BASE_PATH + file;\n            },\n            onLoaded: () => {\n                showMessage(\"MediaPipe Model Y\u00fcklendi. Kameray\u0131 kullan\u0131ma haz\u0131r!\", 5000, false);\n            }\n        });\n\n        hands.setOptions({\n            maxNumHands: 1,\n            modelComplexity: 1,\n            minDetectionConfidence: 0.5, \n            minTrackingConfidence: 0.3\n        });\n\n        \/\/ Calculate hand tension based on landmark distance\n        function calculateDispersion(landmarks) {\n            if (!landmarks || landmarks.length < 21) return 0.0;\n\n            \/\/ Ba\u015fparmak ucu (4) ve \u0130\u015faret parma\u011f\u0131 ucu (8) normalle\u015ftirilmi\u015f koordinatlar (0.0 - 1.0)\n            const thumbTip = landmarks[4];\n            const indexTip = landmarks[8];\n            \n            \/\/ Normalle\u015ftirilmi\u015f koordinat sistemi i\u00e7inde \u00d6klid mesafesini hesaplay\u0131n.\n            const dx = thumbTip.x - indexTip.x;\n            const dy = thumbTip.y - indexTip.y;\n            const dist = Math.sqrt(dx * dx + dy * dy); \n\n            \/\/ Map distance to a 0.0 to 1.0 dispersion factor\n            let normalized = (dist - HAND_DISTANCE_MIN) \/ (HAND_DISTANCE_MAX - HAND_DISTANCE_MIN);\n            normalized = 1.0 - THREE.MathUtils.clamp(normalized, 0.0, 1.0); \/\/ Invert: 1.0 is max dispersion (kapal\u0131 el)\n\n            \/\/ Update UI indicator\n            dispersionBar.style.width = `${normalized * 100}%`;\n            \n            \/\/ HATA AYIKLAMA: Durum mesaj\u0131n\u0131 g\u00fcncelle\n            const barColor = normalized > 0.8 ? 'bg-red-500' : normalized > 0.3 ? 'bg-yellow-500' : 'bg-green-500';\n            debugStatus.className = `mt-4 p-2 text-xs rounded ${barColor}`;\n            \/\/ DEBUG: Ger\u00e7ek normalle\u015ftirilmi\u015f mesafeyi g\u00f6ster\n            debugStatus.innerHTML = `<span class=\"font-bold text-gray-800\">Status:<\/span> Hand detected. Distance: ${dist.toFixed(3)}. Dispersion: ${(normalized * 100).toFixed(0)}% (Close thumb and index finger!)`;\n\n\n            return normalized;\n        }\n\n\n        hands.onResults = (results) => {\n            if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) {\n                const landmarks = results.multiHandLandmarks[0];\n                currentHandDispersion = calculateDispersion(landmarks);\n            } else {\n                \/\/ El alg\u0131lanmad\u0131\u011f\u0131nda\n                currentHandDispersion = THREE.MathUtils.lerp(currentHandDispersion, 0.0, 0.05);\n                dispersionBar.style.width = `${currentHandDispersion * 100}%`;\n                \n                debugStatus.className = `mt-4 p-2 text-xs rounded bg-gray-600`;\n                debugStatus.innerHTML = `<span class=\"font-bold text-gray-200\">Status:<\/span> Waiting for hand...`;\n            }\n        };\n        \n        \/\/ YEN\u0130 \u0130\u015eLEME D\u00d6NG\u00dcS\u00dc: Video ak\u0131\u015f\u0131n\u0131 manuel olarak canvas'a \u00e7izin ve MediaPipe'a g\u00f6nderin.\n        async function processVideo() {\n            if (videoElement.readyState < 2 || !isSetupComplete) {\n                requestAnimationFrame(processVideo);\n                return;\n            }\n\n            \/\/ Video karesini gizli i\u015fleme canvas'\u0131na \u00e7izin (d\u00f6nd\u00fcrme veya \u00e7evirme gerekirse burada yap\u0131l\u0131r)\n            processingCtx.save();\n            processingCtx.scale(-1, 1); \/\/ Yatay \u00e7evirme\n            processingCtx.drawImage(videoElement, 0, 0, processingCanvas.width * -1, processingCanvas.height);\n            processingCtx.restore();\n\n            \/\/ \u00d6nizleme canvas'\u0131na da ak\u0131\u015f\u0131 \u00e7izin (kullan\u0131c\u0131n\u0131n ne g\u00f6rd\u00fc\u011f\u00fcn\u00fc g\u00f6sterir)\n            debugCtx.save();\n            debugCtx.scale(-1, 1);\n            debugCtx.drawImage(videoElement, 0, 0, debugCanvas.width * -1, debugCanvas.height);\n            debugCtx.restore();\n            \n            \/\/ MediaPipe'a i\u015flenmi\u015f canvas'\u0131 g\u00f6nderin\n            await hands.send({ image: processingCanvas });\n\n            requestAnimationFrame(processVideo);\n        }\n\n        \/\/ Initialize Camera and Start Video Processing\n        function startCameraAndProcessing() {\n            navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720 } })\n                .then(stream => {\n                    videoElement.srcObject = stream;\n                    videoElement.onloadedmetadata = () => {\n                        videoElement.play();\n                        processingCanvas.width = videoElement.videoWidth;\n                        processingCanvas.height = videoElement.videoHeight;\n                        debugCanvas.width = videoElement.videoWidth;\n                        debugCanvas.height = videoElement.videoHeight;\n\n                        if (!isSetupComplete) {\n                            initThree();\n                            animate(0); \/\/ Animasyon d\u00f6ng\u00fcs\u00fcn\u00fc ba\u015flat\n                            isSetupComplete = true;\n                            setTargetShape('Hearts'); \n                            showMessage(\"Webcam started. Model y\u00fckleniyor...\", 6000);\n                        }\n                        \/\/ MediaPipe yerine kendi i\u015fleme d\u00f6ng\u00fcm\u00fcz\u00fc ba\u015flat\u0131n\n                        requestAnimationFrame(processVideo);\n                    };\n                })\n                .catch(error => {\n                    console.error('Failed to start webcam:', error);\n                    const errorMessage = error.name === 'NotAllowedError' \n                        ? 'Kamera eri\u015fimi reddedildi (Permission Denied). L\u00fctfen taray\u0131c\u0131 izinlerini kontrol edin.'\n                        : 'Webcam ba\u015flat\u0131lamad\u0131. \u0130zinleri kontrol edin veya taray\u0131c\u0131n\u0131z\u0131n HTTPS kulland\u0131\u011f\u0131ndan emin olun.';\n                    showMessage(`Hata: ${errorMessage}`, 8000, true);\n                });\n        }\n        \n        window.onload = function() {\n            \/\/ Camera yard\u0131mc\u0131 program\u0131 yerine kendi ba\u015flatma fonksiyonumuzu \u00e7a\u011f\u0131r\u0131n\n            startCameraAndProcessing();\n        };\n\n\n        \/\/ --- UI Event Listeners ---\n\n        \/\/ Shape Selector\n        document.getElementById('shape-selector').addEventListener('click', (e) => {\n            if (e.target.matches('.control-button') && e.target.dataset.shape) {\n                setTargetShape(e.target.dataset.shape);\n            }\n        });\n\n        \/\/ Color Picker\n        document.getElementById('color-picker').addEventListener('input', (e) => {\n            if (particles && particles.material) {\n                const hexColor = e.target.value;\n                particles.material.uniforms.color.value.set(hexColor);\n            }\n        });\n        \n    <\/script>\n<\/body>\n<\/html>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Hand-Tracking 3D Particles 3D Particle Maestro Use your hand in the camera view to control particle dispersion (close your hand to expand). Particle Template Hearts Saturn Fireworks Particle Color Dynamic Color Hand Dispersion Status: Waiting for hand&#8230;<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"elementor_canvas","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1731","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/posts\/1731","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/comments?post=1731"}],"version-history":[{"count":10,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/posts\/1731\/revisions"}],"predecessor-version":[{"id":1741,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/posts\/1731\/revisions\/1741"}],"wp:attachment":[{"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/media?parent=1731"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/categories?post=1731"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kominikee.com\/en\/wp-json\/wp\/v2\/tags?post=1731"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}