Kepa Alonso
Kepa Alonso
  • Видео 181
  • Просмотров 503 969
Microorganism in a drop of water
In a drop of water taken from a pond or any natural source, it's common to find a wide variety of microorganisms. One of the most common is the Paramecium, a ciliated protozoan. The Paramecium has an oval shape and is covered with cilia, small hair-like structures that it uses to move and capture food. This microorganism feeds on bacteria and other small organisms, and its transparent body allows us to observe its contractile vacuoles, which regulate the water content inside.
Another microorganism you might observe is the Amoeba, a unicellular organism known for its ability to change shape. The amoeba moves and feeds through pseudopods, which are temporary extensions of its cytoplasm. It's...
Просмотров: 15

Видео

Measure DC Motor Speed with PC Audio Input
Просмотров 9716 часов назад
You can find the detailed HTML code in the comments of the video. This code creates an interactive web page that measures and displays RPM (Revolutions Per Minute) based on audio input. It visualizes the RPM on a circular gauge with a needle that moves according to the calculated RPM value. The user can control various parameters like buffer duration, update interval, and FFT size using sliders.
Measure Motor Speed with a Webcam - Speed Control with USB Relay - DIY Tachometer
Просмотров 3814 дней назад
Measure Motor Speed with a Webcam - Speed Control with USB Relay - DIY Tachometer
Create a Security System with Your Webcam: HTML Code & Motion Detection Tutorial
Просмотров 24Месяц назад
Create a Security System with Your Webcam: HTML Code & Motion Detection Tutorial
The Incredible Process of Filling a Huge Dam
Просмотров 889Месяц назад
The Incredible Process of Filling a Huge Dam
Generator Rotor Removal
Просмотров 272Месяц назад
Generator Rotor Removal
Fascinating World War II Aerosan History
Просмотров 26Месяц назад
Fascinating World War II Aerosan History
3D Transformer Disassembly
Просмотров 91Месяц назад
3D Transformer Disassembly
The Revolutionary Renault FT 17 Tank Explained
Просмотров 227Месяц назад
The Revolutionary Renault FT 17 Tank Explained
Morse Machine Controlled by PC via USB Port #printer #morse #telegraph #diy
Просмотров 972 месяца назад
Morse Machine Controlled by PC via USB Port #printer #morse #telegraph #diy
Power Dam Discharge
Просмотров 762 месяца назад
Power Dam Discharge
Amazing Projects Around The World
Просмотров 302 месяца назад
Amazing Projects Around The World
Fractal Art: Beauty and Mathematics #fractal #art
Просмотров 1252 месяца назад
Fractal Art: Beauty and Mathematics #fractal #art
Huge Dam Construction Time lapse #dam #timelapse
Просмотров 7503 месяца назад
Huge Dam Construction Time lapse #dam #timelapse
Modeling a Power Plant in SP3D: A Journey From Start to Finish
Просмотров 354 месяца назад
Modeling a Power Plant in SP3D: A Journey From Start to Finish
Athletic Bilbao 1984 - 2024. Jo ta ke, irabazi arte.
Просмотров 1204 месяца назад
Athletic Bilbao 1984 - 2024. Jo ta ke, irabazi arte.
The Ultimate Mercedes-Benz Build [TAMIYA] Mercedes-Benz L4500R Maultier #L4500R #Maultier
Просмотров 1715 месяцев назад
The Ultimate Mercedes-Benz Build [TAMIYA] Mercedes-Benz L4500R Maultier #L4500R #Maultier
From the Battlefield to Your Shelf: Soviet Union Tank Scale Models
Просмотров 6 тыс.11 месяцев назад
From the Battlefield to Your Shelf: Soviet Union Tank Scale Models
Recreating History: Building the Somua S-35 French Tank Model #tamiya #somua
Просмотров 1,9 тыс.11 месяцев назад
Recreating History: Building the Somua S-35 French Tank Model #tamiya #somua
Shocking T-62A Tank Model Revealed #T62A
Просмотров 4,1 тыс.Год назад
Shocking T-62A Tank Model Revealed #T62A
Introduction to Web Applications: Exploring the World of HTML, CSS, and JavaScript with Chat GPT
Просмотров 1,5 тыс.Год назад
Introduction to Web Applications: Exploring the World of HTML, CSS, and JavaScript with Chat GPT
Advanced USB Relay Control #pc #relay #control
Просмотров 831Год назад
Advanced USB Relay Control #pc #relay #control
Mastering Scale 1:35 Models - Horch Type 1a [TAMIYA]
Просмотров 1,8 тыс.Год назад
Mastering Scale 1:35 Models - Horch Type 1a [TAMIYA]
Hydroelectric Power Plant Construction Unveiled in Breathtaking Timelapse #HydroelectricTurbine
Просмотров 8 тыс.Год назад
Hydroelectric Power Plant Construction Unveiled in Breathtaking Timelapse #HydroelectricTurbine
Master Your PC: Take Control of a USB Relay in Windows
Просмотров 7 тыс.2 года назад
Master Your PC: Take Control of a USB Relay in Windows
Discover the Hidden Secrets of the Renault FT-17 Scale 1/35 RPM 35060 Pz.Kpfw. FT-31(f) #ft17
Просмотров 2,9 тыс.2 года назад
Discover the Hidden Secrets of the Renault FT-17 Scale 1/35 RPM 35060 Pz.Kpfw. FT-31(f) #ft17
Jaw-Dropping Footage of Epic Dam Construction #dam #GreenGrowth #construction
Просмотров 7 тыс.2 года назад
Jaw-Dropping Footage of Epic Dam Construction #dam #GreenGrowth #construction
Huge Pipe, #Pipeline - Awesome Installation #construction
Просмотров 2,6 тыс.2 года назад
Huge Pipe, #Pipeline - Awesome Installation #construction
The Legendary Soviet ZiS-5: A Masterpiece of Engineering
Просмотров 2,1 тыс.2 года назад
The Legendary Soviet ZiS-5: A Masterpiece of Engineering
Witness the Epic Transformation: Dam Construction Time-lapse #dam #timelapse
Просмотров 62 тыс.2 года назад
Witness the Epic Transformation: Dam Construction Time-lapse #dam #timelapse

Комментарии

  • @KepaAlonso
    @KepaAlonso 7 дней назад

    <!DOCTYPE html> <html> <head> <title>Medidor de RPM</title> <style> body { background-color: black; color: white; text-align: center; font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: center; height: 100vh; } input[type=range] { -webkit-appearance: none; width: 80%; margin: 10px; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 8.4px; cursor: pointer; animate: 0.2s; background: #3071a9; border-radius: 1.3px; box-shadow: 0px 0px 0.9px #000000; } input[type=range]::-webkit-slider-thumb { border: 1px solid #000000; height: 36px; width: 16px; border-radius: 3px; background: #ffffff; cursor: pointer; -webkit-appearance: none; margin-top: -14px; } .slider-container { display: flex; flex-direction: column; align-items: center; margin-top: 20px; } canvas { border: none; margin-top: 20px; } .rpm-container { position: relative; top: -120px; transform: translateY(-50%); width: 100px; display: flex; flex-direction: column; align-items: center; background-color: gray; padding: 10px; border-radius: 5px; } .rpm-number { font-size: 24px; font-weight: bold; } .rpm-text { font-size: 16px; } </style> </head> <body> <canvas id="rpmGauge" width="600" height="600"></canvas> <div class="rpm-container"> <div class="rpm-number" id="rpm">0</div> <div class="rpm-text">RPM</div> </div> <select id="microphoneSelect"></select> <p><button onclick="startRecording()">Iniciar</button></p> <div class="slider-container"> <label for="bufferDuration">Duración del buffer (ms): </label> <input type="range" id="bufferDuration" name="bufferDuration" min="20" max="1000" value="20" oninput="updateBufferDuration(this.value)"> <span id="bufferDurationValue">20</span> <p></p> <label for="updateInterval">Intervalo de actualización (ms): </label> <input type="range" id="updateInterval" name="updateInterval" min="20" max="1000" value="20" oninput="updateUpdateInterval(this.value)"> <span id="updateIntervalValue">20</span> <p></p> <label for="fftSize">FFT Size: </label> <input type="range" id="fftSize" name="fftSize" min="32" max="32768" value="2048" step="32" oninput="updateFftSize(this.value)"> <span id="fftSizeValue">2048</span> <p></p> </div> <script> // Inicialización del contexto de audio y el analizador let audioContext = new (window.AudioContext || window.webkitAudioContext)(); let analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; let bufferLength = analyser.frequencyBinCount; let dataArray = new Uint8Array(bufferLength); let mediaStreamSource; // Configuración inicial const sampleRate = audioContext.sampleRate; let updateInterval = 20; // Intervalo de actualización en milisegundos let frequencyBuffer = []; let bufferDuration = 20; // Duración inicial del buffer en milisegundos let maxBufferLength = Math.floor(bufferDuration / updateInterval); let intervalId; let rpm = 0; let targetRpm = 0; let lastRpm = 0; let lastUpdateTime = 0; let rpmStabilityThreshold = 2; // Umbral de cambio de RPM para considerar velocidad cero let stableTimeThreshold = 100; // Tiempo en ms para considerar RPM estable y poner a cero let smoothingFactor = 0.1; // Factor de suavizado para la EMA // Inicialización del canvas y su contexto var canvas = document.getElementById("rpmGauge"); var context = canvas.getContext("2d"); var centerX = canvas.width / 2; var centerY = canvas.height / 2; var radius = 250; var startAngle = -230 * Math.PI / 180; // Posición inicial del medidor var endAngle = 50 * Math.PI / 180; // Posición final del medidor // Función para dibujar el medidor function drawGauge() { context.clearRect(0, 0, canvas.width, canvas.height); context.fillStyle = "black"; context.fillRect(0, 0, canvas.width, canvas.height); context.beginPath(); context.arc(centerX, centerY, radius, startAngle, endAngle, false); context.fillStyle = "black"; context.fill(); context.lineWidth = 5; context.strokeStyle = "white"; context.stroke(); // Dibujar los números de las RPM context.fillStyle = "white"; context.font = "bold 16px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; for (var i = 0; i <= 12; i++) { var angle = startAngle + (i * (endAngle - startAngle) / 12); var x = centerX + (radius - 60) * Math.cos(angle); var y = centerY + (radius - 60) * Math.sin(angle); context.fillText(i * 100, x, y); } // Dibujar las líneas de las marcas y subdivisiones context.lineWidth = 2; for (var i = 0; i <= 120; i += 10) { var angle = startAngle + (i * (endAngle - startAngle) / 120); var x1 = centerX + (radius - 20) * Math.cos(angle); var y1 = centerY + (radius - 20) * Math.sin(angle); var x2 = centerX + (radius - 30) * Math.cos(angle); var y2 = centerY + (radius - 30) * Math.sin(angle); context.beginPath(); context.moveTo(x1, y1); context.lineTo(x2, y2); context.strokeStyle = "white"; context.stroke(); } // Dibujar subdivisiones más pequeñas context.lineWidth = 1; for (var i = 0; i <= 120; i += 2) { var angle = startAngle + (i * (endAngle - startAngle) / 120); var x1 = centerX + (radius - 20) * Math.cos(angle); var y1 = centerY + (radius - 20) * Math.sin(angle); var x2 = centerX + (radius - 25) * Math.cos(angle); var y2 = centerY + (radius - 25) * Math.sin(angle); context.beginPath(); context.moveTo(x1, y1); context.lineTo(x2, y2); context.strokeStyle = "white"; context.stroke(); } } // Función para dibujar la aguja del medidor function drawNeedle() { var angle = startAngle + (rpm * (endAngle - startAngle) / 12000); var x = centerX + (radius - 50) * Math.cos(angle); var y = centerY + (radius - 50) * Math.sin(angle); context.beginPath(); context.moveTo(centerX, centerY); context.lineTo(x, y); context.strokeStyle = "red"; context.lineWidth = 5; context.stroke(); } // Función para calcular la Media Móvil Exponencial (EMA) function calculateEMA(currentValue, previousEMA, smoothingFactor) { return (currentValue * smoothingFactor) + (previousEMA * (1 - smoothingFactor)); } // Función para iniciar la grabación del audio function startRecording() { let selectedDeviceId = document.getElementById('microphoneSelect').value; let constraints = { audio: { deviceId: selectedDeviceId ? { exact: selectedDeviceId } : undefined } }; navigator.mediaDevices.getUserMedia(constraints) .then(stream => { mediaStreamSource = audioContext.createMediaStreamSource(stream); mediaStreamSource.connect(analyser); intervalId = setInterval(analyze, updateInterval); }) .catch(err => { console.error('Error accessing audio stream', err); }); }

    • @KepaAlonso
      @KepaAlonso 7 дней назад

      // Función para analizar los datos de audio function analyze() { analyser.getByteFrequencyData(dataArray); let maxVal = 0; let maxIndex = 0; for (let i = 0; i < bufferLength; i++) { if (dataArray[i] > maxVal) { maxVal = dataArray[i]; maxIndex = i; } } let frequency = maxIndex * sampleRate / analyser.fftSize; frequencyBuffer.push(frequency); // Mantener el buffer dentro de la longitud máxima if (frequencyBuffer.length > maxBufferLength) { frequencyBuffer.shift(); } // Calcular la frecuencia media let sumFrequency = frequencyBuffer.reduce((sum, freq) => sum + freq, 0); let avgFrequency = sumFrequency / frequencyBuffer.length; // Convertir la frecuencia media a RPM let newTargetRpm = avgFrequency * 10; // Aplicar la suavización mediante EMA targetRpm = calculateEMA(newTargetRpm, targetRpm, smoothingFactor); let currentTime = Date.now(); if (Math.abs(targetRpm - lastRpm) <= rpmStabilityThreshold) { if (currentTime - lastUpdateTime > stableTimeThreshold) { targetRpm = 0; } } else { lastUpdateTime = currentTime; } lastRpm = targetRpm; document.getElementById('rpm').innerText = isNaN(targetRpm) ? '0' : Math.round(targetRpm / 10); // Dibujar el medidor y la aguja drawGauge(); drawNeedle(); } // Actualizar la duración del buffer function updateBufferDuration(value) { bufferDuration = parseInt(value); maxBufferLength = Math.floor(bufferDuration / updateInterval); document.getElementById('bufferDurationValue').innerText = value; frequencyBuffer = []; // Limpiar el buffer al cambiar la duración } // Actualizar el intervalo de actualización function updateUpdateInterval(value) { updateInterval = parseInt(value); clearInterval(intervalId); intervalId = setInterval(analyze, updateInterval); maxBufferLength = Math.floor(bufferDuration / updateInterval); document.getElementById('updateIntervalValue').innerText = value; } // Actualizar el tamaño de la FFT function updateFftSize(value) { analyser.fftSize = parseInt(value); bufferLength = analyser.frequencyBinCount; dataArray = new Uint8Array(bufferLength); document.getElementById('fftSizeValue').innerText = value; } // Animar la aguja del medidor function animateNeedle() { if (Math.abs(rpm - targetRpm) > 1) { rpm += (targetRpm - rpm) * 0.05; drawGauge(); drawNeedle(); } requestAnimationFrame(animateNeedle); } // Población de la lista de micrófonos disponibles function populateMicrophoneList() { navigator.mediaDevices.enumerateDevices() .then(devices => { let microphoneSelect = document.getElementById('microphoneSelect'); devices.forEach(device => { if (device.kind === 'audioinput') { let option = document.createElement('option'); option.value = device.deviceId; option.text = device.label || `Microphone ${microphoneSelect.length + 1}`; microphoneSelect.appendChild(option); } }); }) .catch(err => { console.error('Error enumerating devices', err); }); } // Inicializar la lista de micrófonos al cargar la página populateMicrophoneList(); // Dibujar el medidor y la aguja al cargar la página drawGauge(); drawNeedle(); animateNeedle(); </script> </body> </html>

  • @haiduy7627
    @haiduy7627 7 дней назад

    🌺🌸🌾💕💯🌹🌻❤

  • @haiduy7627
    @haiduy7627 7 дней назад

    👍💪🌾💕💯🌹

  • @haiduy7627
    @haiduy7627 7 дней назад

    😊❤

  • @rubenkvz4673
    @rubenkvz4673 8 дней назад

    😮 Which 3D, CAD software is ?

    • @KepaAlonso
      @KepaAlonso 8 дней назад

      Intregraph SmartPlant 3D

  • @user-mp4ht9qf7c
    @user-mp4ht9qf7c 10 дней назад

    please give me 1 second auto on off code

  • @Jay-yz7wm
    @Jay-yz7wm 22 дня назад

    So cool, where is this?

  • @tharki_insaan699
    @tharki_insaan699 26 дней назад

    3D PRINTED DAM😂😂😂😂

  • @KepaAlonso
    @KepaAlonso Месяц назад

    Html code to control cam and relay: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; background-color: #f0f0f0; margin: 0; color: #333; } h1 { color: #333; } .container { background: #fff; border-radius: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); padding: 20px; width: 60%; max-width: 1000px; text-align: center; border: 1px solid #ccc; } button { margin: 10px; padding: 10px 20px; font-size: 16px; cursor: pointer; border: none; border-radius: 5px; transition: background-color 0.3s; } button:disabled { background-color: #ccc; cursor: not-allowed; } #connectButton { background-color: #007bff; color: white; } #detectButton { background-color: #ccc; } input[type="range"] { width: 100%; } video, canvas { margin: 10px; border: 1px solid #ccc; } .status { font-size: 18px; margin: 5px 0; } #popup { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #ff0000; color: #fff; padding: 40px; border-radius: 10px; z-index: 1000; text-align: center; animation: blink 1.5s infinite; } #popup img { width: 100px; height: 100px; } #popup p { font-size: 48px; font-weight: bold; text-transform: uppercase; } #popup button { margin-top: 20px; background-color: #007bff; color: white; padding: 10px 20px; font-size: 16px; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } } #log { margin-top: 20px; background: #fff; border: 1px solid #ccc; border-radius: 10px; padding: 0px; width: 100%; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } #log table { width: 100%; border-collapse: collapse; } #log th, #log td { border: 1px solid #ccc; padding: 5px; text-align: left; } #exportButton, #clearButton { background-color: #007bff; color: white; } footer { margin-top: 20px; } a { color: #007bff; text-decoration: none; font-weight: bold; } </style> </head> <body> <div class="container"> <button id="connectButton">Conectar</button> <br> <input type="range" id="sensitivitySlider" min="0" max="100" value="50"> <div class="status">Sensibilidad: <span id="sensitivityValue">50</span></div> <br> <button id="detectButton" disabled>Activar Deteccion de Movimiento</button> <br> <video id="video" width="960" height="720" autoplay></video> <canvas id="canvas" width="960" height="720" style="display:none;"></canvas> <div id="popup"> <img src="img.icons8.com/color/96/000000/error.png" alt="Alerta"> <p>INTRUSO DETECTADO!</p> <button id="dismissButton">Desactivar Alarma</button> </div> <div id="log"> <table> <thead> <tr> <th>Fecha</th> <th>Hora</th> <th>Video</th> </tr> </thead> <tbody id="logBody"> </tbody> </table> <button id="exportButton">Exportar</button> <button id="clearButton">Borrar Datos</button> </div> </div> <script> let port; let isRunning = false; let video = document.getElementById('video'); let canvas = document.getElementById('canvas'); let sensitivity = 50; let prevFrame = null; let threshold = 6000000; let intruderDetected = false; let mediaRecorder; let recordedChunks = []; let currentTimestamp; let downloadDirectory; let downloadDirectoryPath; document.getElementById('connectButton').addEventListener('click', async () => { try { port = await navigator.serial.requestPort(); await port.open({ baudRate: 9600 }); document.getElementById('detectButton').disabled = false; document.getElementById('connectButton').disabled = true; console.log('Conectado al puerto serial'); startCamera(); } catch (error) { console.error('Error al conectar al puerto serial:', error); alert('Error al conectar al puerto serial. Verifique que el dispositivo esté conectado y vuelva a intentarlo.'); } });

    • @KepaAlonso
      @KepaAlonso Месяц назад

      function startCamera() { navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { video.srcObject = stream; video.play(); mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) { recordedChunks.push(event.data); } }; mediaRecorder.onstop = () => { saveRecording(); }; }) .catch(error => { console.error('Error al acceder a la cámara:', error); alert('Error al acceder a la cámara. Verifique que la cámara esté conectada y vuelva a intentarlo.'); }); } function captureFrame() { let context = canvas.getContext('2d'); context.drawImage(video, 0, 0, canvas.width, canvas.height); return context.getImageData(0, 0, canvas.width, canvas.height); } function calculateDifference(frame1, frame2) { let diff = 0; for (let i = 0; i < frame1.data.length; i += 4) { let r = Math.abs(frame1.data[i] - frame2.data[i]); let g = Math.abs(frame1.data[i + 1] - frame2.data[i + 1]); let b = Math.abs(frame1.data[i + 2] - frame2.data[i + 2]); diff += r + g + b; } return diff; } async function monitorMovement() { if (!prevFrame) { prevFrame = captureFrame(); return; } let currentFrame = captureFrame(); let diff = calculateDifference(prevFrame, currentFrame); let changedPixels = diff; threshold = 3000000 + sensitivity * 240000; if (changedPixels > threshold && !intruderDetected) { intruderDetected = true; currentTimestamp = new Date().getTime(); document.getElementById('popup').style.display = 'block'; sendCommand([0xA0, 0x01, 0x01, 0xA2]); mediaRecorder.start(); logAlert(currentTimestamp); } prevFrame = currentFrame; } document.getElementById('sensitivitySlider').addEventListener('input', (event) => { sensitivity = event.target.value; document.getElementById('sensitivityValue').innerText = sensitivity; }); async function sendCommand(command) { try { const writer = port.writable.getWriter(); const data = new Uint8Array(command); await writer.write(data); writer.releaseLock(); } catch (error) { console.error('Error al enviar comando:', error); alert('Error al enviar comando. Verifique la conexión.'); } } document.getElementById('detectButton').addEventListener('click', () => { isRunning = !isRunning; if (isRunning) { document.getElementById('detectButton').style.backgroundColor = 'lightgreen'; monitorMovementLoop(); } else { document.getElementById('detectButton').style.backgroundColor = 'lightgray'; } }); function monitorMovementLoop() { if (isRunning) { monitorMovement(); requestAnimationFrame(monitorMovementLoop); } } document.getElementById('dismissButton').addEventListener('click', () => { document.getElementById('popup').style.display = 'none'; intruderDetected = false; isRunning = false; document.getElementById('detectButton').disabled = true; document.getElementById('detectButton').style.backgroundColor = 'lightgray'; sendCommand([0xA0, 0x01, 0x00, 0xA1]); mediaRecorder.stop(); setTimeout(() => { document.getElementById('detectButton').disabled = false; }, 2000); }); function logAlert(timestamp) { const now = new Date(); const date = now.toLocaleDateString(); const time = now.toLocaleTimeString(); const row = `<tr><td>${date}</td><td>${time}</td><td id="video-link-${timestamp}"></td></tr>`; document.getElementById('logBody').insertAdjacentHTML('beforeend', row); } async function saveRecording() { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const now = new Date(currentTimestamp); const fileName = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}_${now.getHours()}-${now.getMinutes()}-${now.getSeconds()}.webm`; // Create the file handle const fileHandle = await downloadDirectory.getFileHandle(fileName, { create: true }); // Create a writable stream for the file const writableStream = await fileHandle.createWritable(); // Write the contents of the blob to the file await writableStream.write(blob); // Close the file and release the writable stream await writableStream.close(); // Generate the file path using the downloadDirectoryPath const filePath = `${downloadDirectoryPath}/${fileName}`; // Update the table cell with the file link const videoCell = document.getElementById(`video-link-${currentTimestamp}`); videoCell.innerHTML = `<a href="${filePath}" target="_blank">${fileName}</a>`; // Clear the recorded chunks recordedChunks = []; } document.getElementById('exportButton').addEventListener('click', () => { const rows = Array.from(document.querySelectorAll('#log table tr')); const csvContent = rows.map(row => { const cells = Array.from(row.querySelectorAll('th, td')); return cells.map(cell => cell.innerText).join(','); }).join(' '); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'log_alertas.csv'; document.body.appendChild(a); a.click(); document.body.removeChild(a); }); document.getElementById('clearButton').addEventListener('click', () => { document.getElementById('logBody').innerHTML = ''; }); async function selectDownloadDirectory() { try { const directoryHandle = await window.showDirectoryPicker(); downloadDirectory = directoryHandle; downloadDirectoryPath = directoryHandle.name; // Save the directory path } catch (error) { console.error('Error al seleccionar el directorio de descarga:', error); alert('Error al seleccionar el directorio de descarga. Inténtelo de nuevo.'); } } document.getElementById('connectButton').insertAdjacentHTML('afterend', '<button id="selectDirectoryButton">Seleccionar Carpeta de Descargas</button>'); document.getElementById('selectDirectoryButton').addEventListener('click', selectDownloadDirectory); </script> </body> </html>

  • @michaelmejiamoreno5521
    @michaelmejiamoreno5521 Месяц назад

    Es posible utilizar la camara del Pc como activador de on / off? es decir cuando yo estoy frente al pc active el relay

    • @KepaAlonso
      @KepaAlonso Месяц назад

      es posible, tambien se podria usar el microfono y activar el rele si se detecta un ruido

  • @Srbrx
    @Srbrx Месяц назад

    Uhaa, esta interesante esto, gracias por compartir!

  • @KepaAlonso
    @KepaAlonso 2 месяца назад

    MORSE BEEP DECODER - HTML CODE <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>INTERPRETAR CODIGO MORSE</title> <style> body { font-family: Arial, sans-serif; text-align: center; margin: 50px; } canvas { border: 1px solid black; margin-top: 20px; } textarea { width: 80%; height: 100px; margin-top: 20px; } .slider-container { margin-top: 20px; } </style> </head> <body> <h1>Interpretar Codigo Morse</h1> <button id="startButton">Iniciar</button> <button id="stopButton" disabled>Detener</button> <button id="convertButton" disabled>Convertir a Texto</button> <button id="clearButton">Borrar Texto</button> <div class="slider-container"> <label for="sensitivitySlider">Sensibilidad del Volumen: <span id="sensitivityValue">10</span></label> <input type="range" id="sensitivitySlider" min="0.01" max="0.2" step="0.01" value="10"> </div> <h2>Audio</h2> <canvas id="waveformCanvas" width="400" height="200"></canvas> <h2>Beep Detectado</h2> <canvas id="beepCanvas" width="1600" height="50"></canvas> <h2>Texto Interpretado:</h2> <textarea id="outputText" readonly></textarea> <script> const morseCode = { '.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G', '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N', '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R', '...': 'S', '-': 'T', '..-': 'U', '...-': 'V', '.--': 'W', '-..-': 'X', '-.--': 'Y', '--..': 'Z', '-----': '0', '.----': '1', '..---': '2', '...--': '3', '....-': '4', '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9' }; const startButton = document.getElementById('startButton'); const stopButton = document.getElementById('stopButton'); const convertButton = document.getElementById('convertButton'); const clearButton = document.getElementById('clearButton'); const outputText = document.getElementById('outputText'); const sensitivitySlider = document.getElementById('sensitivitySlider'); const sensitivityValue = document.getElementById('sensitivityValue'); const waveformCanvas = document.getElementById('waveformCanvas'); const waveformCtx = waveformCanvas.getContext('2d'); const beepCanvas = document.getElementById('beepCanvas'); const beepCtx = beepCanvas.getContext('2d'); let audioContext; let analyser; let microphone; let javascriptNode; let listening = false; let morseInput = ''; let lastSignalTime = 0; let capturingSymbol = false; let beepTimes = []; const dotDuration = 0.1; // 0.1 seconds (100 milliseconds) const dashDuration = 0.3; // 0.3 seconds (300 milliseconds) const symbolGap = 0.1; // 0.1 seconds (100 milliseconds) const characterPauseDuration = 0.6; // 0.6 seconds (600 milliseconds) const wordPauseDuration = 2.0; // 2.0 seconds (2000 milliseconds) let sensitivityThreshold = 10; sensitivitySlider.addEventListener('input', () => { sensitivityThreshold = parseFloat(sensitivitySlider.value); sensitivityValue.textContent = sensitivitySlider.value; }); startButton.addEventListener('click', () => { startButton.disabled = true; stopButton.disabled = false; convertButton.disabled = true; startListening(); }); stopButton.addEventListener('click', () => { startButton.disabled = false; stopButton.disabled = true; convertButton.disabled = false; stopListening(); }); convertButton.addEventListener('click', translateMorseToText); clearButton.addEventListener('click', () => { outputText.value = ''; }); function startListening() { audioContext = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; analyser.smoothingTimeConstant = 0.8; navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { microphone = audioContext.createMediaStreamSource(stream); javascriptNode = audioContext.createScriptProcessor(2048, 1, 1); microphone.connect(analyser); analyser.connect(javascriptNode); javascriptNode.connect(audioContext.destination); javascriptNode.onaudioprocess = processAudio; listening = true; drawWaveform(); drawBeepDetection(); }) .catch(error => { console.error('Error accessing microphone:', error); }); } function stopListening() { if (microphone) microphone.disconnect(); if (analyser) analyser.disconnect(); if (javascriptNode) javascriptNode.disconnect(); if (audioContext) audioContext.close(); listening = false; } function processAudio(event) { const buffer = new Float32Array(analyser.fftSize); analyser.getFloatTimeDomainData(buffer); const now = audioContext.currentTime; const signalDetected = buffer.some(sample => Math.abs(sample) > sensitivityThreshold); if (signalDetected) { if (!capturingSymbol) { capturingSymbol = true; lastSignalTime = now; } } else if (capturingSymbol) { capturingSymbol = false; const duration = now - lastSignalTime; if (duration < dotDuration * 1.5) { morseInput += '.'; beepTimes.push({ time: now, type: 'dot' }); } else if (duration >= dotDuration * 1.5 && duration < dashDuration * 1.5) { morseInput += '-'; beepTimes.push({ time: now, type: 'dash' }); } lastSignalTime = now; console.log(`Detected Morse Input: ${morseInput}`); } else { const silenceDuration = now - lastSignalTime; if (silenceDuration >= characterPauseDuration && silenceDuration < wordPauseDuration) { morseInput += ' '; lastSignalTime = now; console.log(`Character Pause Detected: ${morseInput}`); } else if (silenceDuration >= wordPauseDuration) { morseInput += ' '; lastSignalTime = now; console.log(`Word Pause Detected: ${morseInput}`); } } } function drawWaveform() { if (!listening) return; const buffer = new Float32Array(analyser.fftSize); analyser.getFloatTimeDomainData(buffer); waveformCtx.clearRect(0, 0, waveformCanvas.width, waveformCanvas.height); waveformCtx.beginPath(); const sliceWidth = waveformCanvas.width * 1.0 / buffer.length; let x = 0; for (let i = 0; i < buffer.length; i++) { const v = buffer[i] * 200.0; const y = waveformCanvas.height / 2 + v; if (i === 0) { waveformCtx.moveTo(x, y); } else { waveformCtx.lineTo(x, y); } x += sliceWidth; } waveformCtx.lineTo(waveformCanvas.width, waveformCanvas.height / 2); waveformCtx.stroke(); requestAnimationFrame(drawWaveform); } function drawBeepDetection() { if (!listening) return; beepCtx.clearRect(0, 0, beepCanvas.width, beepCanvas.height); beepCtx.beginPath(); beepTimes.forEach(beep => { const x = (beep.time % 30) / 30 * beepCanvas.width; // Escala ajustada beepCtx.moveTo(x, 0); beepCtx.lineTo(x, beep.type === 'dot' ? 10 : 30); }); beepCtx.stroke(); requestAnimationFrame(drawBeepDetection); } function translateMorseToText() { const words = morseInput.trim().split(' '); const text = words.map(word => { return word.split(' ').map(symbol => morseCode[symbol] || '').join(''); }).join(' '); outputText.value = text; console.log(`Translated Text: ${text}`); morseInput = ''; beepTimes = []; } </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso 2 месяца назад

    MORSE SENDER - POWERSELL USB CONTROL CODE: Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Crear formulario $form = New-Object System.Windows.Forms.Form $form.Text = 'USB RELAY CONTROL' $form.Size = New-Object System.Drawing.Size(400, 500) $form.StartPosition = 'CenterScreen' # Crear fuente para los cuadros de texto $fontTextBox = New-Object System.Drawing.Font("Arial", 14) # Crear etiqueta para puerto USB $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(15, 250) $label.Size = New-Object System.Drawing.Size(180, 40) $label.Text = 'NÚMERO DE PUERTO USB:' $form.Controls.Add($label) # Crear cuadro combinado para puerto USB $comboBox = New-Object System.Windows.Forms.ComboBox $comboBox.Location = New-Object System.Drawing.Point(200, 250) $comboBox.Size = New-Object System.Drawing.Size(160, 40) $ports = [System.IO.Ports.SerialPort]::getportnames() $comboBox.Items.AddRange($ports) $form.Controls.Add($comboBox) # Crear objeto para el puerto serie (se inicializará más tarde) $KEPAALONSORELAY = $null # Crear cuadro de texto para la entrada $inputBox = New-Object System.Windows.Forms.TextBox $inputBox.Location = New-Object System.Drawing.Point(15, 20) $inputBox.Size = New-Object System.Drawing.Size(360, 40) $inputBox.Font = $fontTextBox $form.Controls.Add($inputBox) # Crear botón para convertir y enviar código Morse $sendButton = New-Object System.Windows.Forms.Button $sendButton.Location = New-Object System.Drawing.Point(15, 70) $sendButton.Size = New-Object System.Drawing.Size(360, 40) $sendButton.Text = 'Enviar' $sendButton.Enabled = $true # Inicialmente habilitado $form.Controls.Add($sendButton) # Crear cuadro de texto para la salida de código Morse $outputBox = New-Object System.Windows.Forms.TextBox $outputBox.Location = New-Object System.Drawing.Point(15, 120) $outputBox.Size = New-Object System.Drawing.Size(360, 100) $outputBox.Multiline = $true $outputBox.Font = $fontTextBox $form.Controls.Add($outputBox) # Diccionario de código Morse $morseCode = @{ 'A' = '.-'; 'B' = '-...'; 'C' = '-.-.'; 'D' = '-..'; 'E' = '.'; 'F' = '..-.'; 'G' = '--.'; 'H' = '....'; 'I' = '..'; 'J' = '.---'; 'K' = '-.-'; 'L' = '.-..'; 'M' = '--'; 'N' = '-.'; 'O' = '---'; 'P' = '.--.'; 'Q' = '--.-'; 'R' = '.-.'; 'S' = '...'; 'T' = '-'; 'U' = '..-'; 'V' = '...-'; 'W' = '.--'; 'X' = '-..-'; 'Y' = '-.--'; 'Z' = '--..'; '1' = '.----'; '2' = '..---'; '3' = '...--'; '4' = '....-'; '5' = '.....'; '6' = '-....'; '7' = '--...'; '8' = '---..'; '9' = '----.'; '0' = '-----'; ' ' = ' ' # Espacio para separar palabras } # Función para enviar un solo carácter en código Morse a través del relé y pitido por altavoz function SendCharMorse { param ($char) $dotDuration = 100 # Duración del punto en milisegundos $dashDuration = $dotDuration * 3 $symbolGap = $dotDuration $char = $char.ToString().ToUpper().Trim() # Asegurarse de que el carácter esté en mayúsculas y sin espacios en blanco if ($morseCode.ContainsKey($char)) { $morse = $morseCode[$char] foreach ($symbol in $morse.ToCharArray()) { switch ($symbol) { '.' { $KEPAALONSORELAY.Write($ON, 0, $ON.Length) [System.Console]::Beep(1000, $dotDuration) # Pitido para punto Start-Sleep -Milliseconds $dotDuration $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) } '-' { $KEPAALONSORELAY.Write($ON, 0, $ON.Length) [System.Console]::Beep(1000, $dashDuration) # Pitido para raya Start-Sleep -Milliseconds $dashDuration $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) } } Start-Sleep -Milliseconds $symbolGap } Start-Sleep -Milliseconds ($symbolGap * 6) # Espacio entre letras } } $sendButton.Add_Click({ $text = $inputBox.Text.ToUpper() if ($comboBox.Text -ne "" -and $KEPAALONSORELAY -eq $null) { $KEPAALONSORELAY = New-Object System.IO.Ports.SerialPort $comboBox.Text, 9600, None, 8, One $KEPAALONSORELAY.Open() } $outputBox.Text = "" # Limpiar el cuadro de salida foreach ($char in $text.ToCharArray()) { $charString = $char.ToString().Trim() # Convertir el carácter a cadena y eliminar espacios en blanco if ($morseCode.ContainsKey($charString)) { $morse = $morseCode[$charString] $outputBox.AppendText($morse + " ") # Añadir el código Morse del carácter actual al cuadro de salida $form.Refresh() # Refrescar el formulario para actualizar la pantalla SendCharMorse -char $charString } } [System.Windows.Forms.MessageBox]::Show("MENSAJE ENVIADO") }) # Crear matrices de bytes para encender y apagar [BYTE[]] $ON = 0xA0, 0x01, 0x01, 0xA2 [BYTE[]] $OFF = 0xA0, 0x01, 0x00, 0xA1 # Crear LinkLabel para autor $LinkLabelAuthor = New-Object System.Windows.Forms.LinkLabel $LinkLabelAuthor.Location = New-Object System.Drawing.Point(75, 300) $LinkLabelAuthor.Size = New-Object System.Drawing.Size(250, 20) $LinkLabelAuthor.LinkColor = 'BLUE' $LinkLabelAuthor.ActiveLinkColor = 'RED' $LinkLabelAuthor.Text = 'KEPA ALONSO GOIKOETXEA' $LinkLabelAuthor.Add_Click({ [System.Diagnostics.Process]::Start('kalonso9.wixsite.com/kalo') }) $form.Controls.Add($LinkLabelAuthor) # Crear LinkLabel para Wikipedia $LinkLabelWiki = New-Object System.Windows.Forms.LinkLabel $LinkLabelWiki.Location = New-Object System.Drawing.Point(75, 330) $LinkLabelWiki.Size = New-Object System.Drawing.Size(250, 20) $LinkLabelWiki.LinkColor = 'BLUE' $LinkLabelWiki.ActiveLinkColor = 'RED' $LinkLabelWiki.Text = 'MORSE CODE' $LinkLabelWiki.Add_Click({ [System.Diagnostics.Process]::Start('en.wikipedia.org/wiki/Morse_code') }) $form.Controls.Add($LinkLabelWiki) # Mostrar el formulario $form.ShowDialog() # Cerrar el puerto serie si está abierto if ($KEPAALONSORELAY -ne $null -and $KEPAALONSORELAY.IsOpen) { $KEPAALONSORELAY.Write($OFF, 0, $OFF.Length) $KEPAALONSORELAY.Close() }

  • @RicardoTerrazav2
    @RicardoTerrazav2 2 месяца назад

    las matematicas por sí mismas y como tales son hermosas

  • @KepaAlonso
    @KepaAlonso 3 месяца назад

    Mandelbrot Set <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Conjunto de Mandelbrot</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight; let magnificationFactor = 300; // Factor de magnificación inicial const centerReal = -0.5; // Coordenada real del centro const centerImaginary = 0; // Coordenada imaginaria del centro const maxIterations = 1000; // Número máximo de iteraciones const animationDuration = 10000; // Duración de la animación en milisegundos (10 minutos) // Función para determinar si un punto pertenece al conjunto de Mandelbrot function mandelbrot(c_real, c_imaginary) { let real = 0; let imaginary = 0; for (let i = 0; i < maxIterations; i++) { const tempReal = real * real - imaginary * imaginary + c_real; const tempImaginary = 2 * real * imaginary + c_imaginary; real = tempReal; imaginary = tempImaginary; if (real * imaginary > 5) { return (i / maxIterations * 250); } } return 0; } // Función para dibujar el conjunto de Mandelbrot centrado en la pantalla function drawMandelbrot() { const offsetX = width / 2; const offsetY = height / 2; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { const c_real = (x - offsetX) / magnificationFactor + centerReal; const c_imaginary = (y - offsetY) / magnificationFactor + centerImaginary; const intensity = mandelbrot(c_real, c_imaginary); const color = intensity > 0 ? `hsl(0, 100%, ${intensity}%)` : 'black'; ctx.fillStyle = color; ctx.fillRect(x, y, 1, 1); } } } // Función para iniciar la animación function animate() { const startTime = Date.now(); function drawFrame() { const elapsedTime = Date.now() - startTime; ctx.clearRect(0, 0, width, height); const progress = Math.min(0.01, elapsedTime / animationDuration); magnificationFactor += progress * 30; // Aumentar el factor de magnificación gradualmente drawMandelbrot(); if (progress < 1) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar la animación después de un breve retraso setTimeout(animate, 10); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso 3 месяца назад

    Barnsley Fern <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Fractal tipo Ola</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth+20; const height = canvas.height = window.innerHeight; const scale = height / 10; // Escala para el tamaño del helecho (ajustado para cubrir la altura de la pantalla) const initialX = width / 2; const initialY = height / 2 + 380; // Coordenada inicial Y con una separación de 50 píxeles arriba const animationDuration = 600; // Duración de la animación en milisegundos (10 minutos) // Función para dibujar el helecho function drawFern(x, y, iterations) { for (let i = 0; i < iterations; i++) { const rand = Math.random(); let newX, newY; if (rand < 0.01) { newX = 0; newY = 0.16 * y; } else if (rand < 0.86) { newX = 0.85 * x + 0.04 * y; newY = -0.04 * x + 0.85 * y + 1.6; } else if (rand < 0.93) { newX = 0.2 * x - 0.26 * y; newY = 0.23 * x + 0.22 * y + 1.6; } else { newX = -0.15 * x + 0.28 * y; newY = 0.26 * x + 0.24 * y + 0.44; } ctx.fillStyle = 'green'; ctx.fillRect(initialX + newX * scale, initialY - newY * scale, 1, 1); x = newX; y = newY; } } // Función para iniciar la animación function animate() { const startTime = Date.now(); function drawFrame() { const elapsedTime = Date.now() - startTime; ctx.clearRect(0, 0, width, height); const progress = Math.min(0.1, elapsedTime / animationDuration); drawFern(0, 0, 1000000 * progress); // Incremento en el número de iteraciones if (progress < 1) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar la animación después de un breve retraso setTimeout(animate, 10); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso 3 месяца назад

    Julia Fractal <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Conjunto de Julia Animado</title> <style> body, html { margin: 0; padding: 0; overflow: hidden; } canvas { display: block; background-color: black; } </style> </head> <body> <canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; const height = canvas.height = window.innerHeight; const maxIterations = 1000; // Número inicial de iteraciones const maxTotalIterations = 1000; // Número máximo total de iteraciones let cx = -0.7; let cy = 0.27015; let totalIterations = 0; // Función para determinar si un punto pertenece al conjunto de Julia function julia(x, y, iterations) { let zx = x / width * 3.5 - 1.8; let zy = y / height * 2 - 1; for (let i = 0; i < iterations; i++) { let temp = zx * zx - zy * zy + cx; zy = 2 * zx * zy + cy; zx = temp; if (zx * zx + zy * zy > 4) { return i / iterations * 90; } } return 0; } // Función para dibujar el conjunto de Julia progresivamente function drawJulia() { const iterationsIncrement = 5; // Incremento en el número de iteraciones por cuadro const maxFrames = maxTotalIterations / iterationsIncrement; const frameTime = 1000; // Tiempo entre cuadros en milisegundos let currentIterations = 0; function drawFrame() { ctx.clearRect(0, 0, width, height); for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const intensity = julia(x, y, currentIterations); const color = intensity > 0 ? intensity * 2.55 : 0; // Convertir a valor de 0 a 255 ctx.fillStyle = `rgb(0, 0, ${color})`; ctx.fillRect(x, y, 1, 1); } } currentIterations += iterationsIncrement; if (currentIterations <= maxIterations) { requestAnimationFrame(drawFrame); } } drawFrame(); } // Iniciar el dibujo progresivo del conjunto de Julia drawJulia(); </script> </body> </html>

  • @ahmadabosrea8865
    @ahmadabosrea8865 3 месяца назад

    can be used to get a feedback signal from a sensor to the computer through the USB?

    • @KepaAlonso
      @KepaAlonso 3 месяца назад

      No, only digital output

  • @georhodiumgeo9827
    @georhodiumgeo9827 4 месяца назад

    Dam...

  • @KepaAlonso
    @KepaAlonso 4 месяца назад

    goo.gl/maps/mTK97bLx3eJiQGLZ9

  • @kylobensolo5655
    @kylobensolo5655 4 месяца назад

    Ich lade der mg-08/15 Ich höre Eindringlinge

  • @bill9540
    @bill9540 4 месяца назад

    Great work on the weathering and shading…very nice👍

  • @Blackcat-do7wo
    @Blackcat-do7wo 4 месяца назад

    Very nice 👏

  • @marccxxshammer6643
    @marccxxshammer6643 6 месяцев назад

  • @selimcelik3494
    @selimcelik3494 8 месяцев назад

    I'm guessing, like me, that most people were wondering if they started building in the water or if the water was diverted afterwards. I'm glad to know the answer now.

    • @KepaAlonso
      @KepaAlonso 7 месяцев назад

      Appreciate the observation. Initially, the flow was diverted before intercepting the channel. This unique process presented a distinctive challenge. Thanks for tuning in and showing interest.

  • @nazarbulatov2122
    @nazarbulatov2122 9 месяцев назад

    Что за цвет был использован при покраске кузова?!

    • @KepaAlonso
      @KepaAlonso 9 месяцев назад

      Дело в том, что я использую 5 банок акриловой краски основных цветов: белого, черного, красного, желтого и синего по 500 мл каждая. Путем их смешивания я получаю все необходимые цвета для моей модели. Затем я покрываю поверхность глянцевым лаком, наношу масляные краски и в завершение использую матовый лак.

    • @nazarbulatov2122
      @nazarbulatov2122 9 месяцев назад

      @@KepaAlonso спасибо за ответ! А военный автомобиль Зис5В . Покрытый только глянцевым лаком будет смотреться не очень?! И кстати салон двигатель и колеса надо покрывать лаком? И если да то по окончанию сборке? Задаю сразу все вопросы которые интересуют, так как новичок и это моя первая модель, а другие блогеры не отвечают;) Буду рад ответу!)

    • @nazarbulatov2122
      @nazarbulatov2122 9 месяцев назад

      Так то у меня ещё много вопросов, но на Ютубе точных ответов найти не могу)

    • @KepaAlonso
      @KepaAlonso 9 месяцев назад

      Перед началом покраски тщательно очистите модель мылом и водой. Важно, чтобы поверхность была чистой от жира, так как это обеспечит хорошее сцепление краски. Наношу базовый слой серой краски с добавлением нескольких капель жидкого мыла. Важно, чтобы краска хорошо зафиксировалась; если на модели есть следы жира, например, от рук, краска может плохо держаться. Глянцевый лак используется для того, чтобы при нанесении масляных красок с растворителем, такого как агуаррас, они хорошо распределялись, создавая различные оттенки. Это можно сделать кистью и ватными тампонами, а затем убрать излишки. Обязательно наносите глянцевый лак после покрытия разноцветными слоями краски, особенно если вы собираетесь использовать наклейки. Дайте несколько дней для полного высыхания перед применением масляных красок. Будьте осторожны с избыточным использованием растворителя при нанесении масляных красок, чтобы избежать поднятия глянцевого лака. Завершающий матовый слой придаст модели более реалистичный вид, что особенно подходит для моделей военной техники, таких как танки.

    • @KepaAlonso
      @KepaAlonso 9 месяцев назад

      Я новичок и провожу эксперименты с моделями, и, из всего, что я пробовал, наилучший, более удовлетворительный и реалистичный результат я получил, нанося масляные краски поверх акрила, как я вам говорю. Речь идет о моделях типа танков и военной техники; для самолетов и гражданских транспортных средств ситуация отличается.

  • @KiKi-pn7is
    @KiKi-pn7is 10 месяцев назад

    👍👍👍👍

  • @dvdw_graphics_crafts
    @dvdw_graphics_crafts 10 месяцев назад

    Love the dust effect, looking realistic! ; )

    • @KepaAlonso
      @KepaAlonso 7 месяцев назад

      Thank you! I'm glad you noticed and appreciate the dust effect. Achieving realism was a key goal, so I'm thrilled that it came across effectively. Your positive feedback means a lot! 😊

    • @dvdw_graphics_crafts
      @dvdw_graphics_crafts 7 месяцев назад

      dust and mud, that's also the most fun part :D​

  • @jimmytwizzle7836
    @jimmytwizzle7836 10 месяцев назад

    Hardly jaw dropping was it. In fact it was pretty uninteresting I thought. Thumbs down.

  • @MICHALMALACHOVSKY
    @MICHALMALACHOVSKY 10 месяцев назад

    WOW WOW WOW WOW WOW

  • @Hyper-Tv
    @Hyper-Tv 10 месяцев назад

    which dam it is

  • @slshusker
    @slshusker 10 месяцев назад

    Those are / were excellent f er uppers.

  • @SJR_Media_Group
    @SJR_Media_Group 10 месяцев назад

    Some of the best sites for dams are extremely challenging. Just site prep and getting roads and infrastructure to the site can be harder than building the actual dam.

    • @KepaAlonso
      @KepaAlonso 7 месяцев назад

      Absolutely! Site preparation and establishing infrastructure for dams can indeed pose significant challenges. Sometimes, the logistics and groundwork are as demanding, if not more, than the actual construction of the dam itself. It's a complex process, and your insight is spot on. Thanks for highlighting this crucial aspect of dam projects!

  • @SEO_Expert_BD
    @SEO_Expert_BD 11 месяцев назад

    Your video is very good, but it is not properly SEO and optimized. Due to which your video views are not coming as expected and your channel is not growing. Can I help you?

    • @KepaAlonso
      @KepaAlonso 11 месяцев назад

      Thank you for your feedback, @md.mizanurrahman005. I appreciate your kind words about my video. I'm always looking to improve and grow my channel, so I'm open to suggestions. Please feel free to share your expertise and any tips you have for optimizing SEO to boost video views. I'm eager to learn and make my content even better! Subscribe my channel

  • @kasturideraman7983
    @kasturideraman7983 11 месяцев назад

    reservoir?

  • @monkfishy6348
    @monkfishy6348 Год назад

    What's the point of building a dam when there's no water?

    • @DindoAlcantaraSerenade
      @DindoAlcantaraSerenade 10 месяцев назад

      They rerouted the water because building a dam with water still on it is just risky and almost impossible

    • @stevenpersinger6577
      @stevenpersinger6577 5 месяцев назад

      How do you reroute a whole river​@DindoAlcantaraSerenade

    • @scorpionsting47
      @scorpionsting47 3 месяца назад

      ​@@stevenpersinger6577 they usually drill a tunnel around the dam and then sometimes collapse it when the dam is finished.

    • @lisasmith9311
      @lisasmith9311 Месяц назад

      Maybe they direct the water to it when finished

    • @DanielWhite-bp9ek
      @DanielWhite-bp9ek 22 дня назад

      ​@@lisasmith9311 They do that so they cannot disturb the water flow (yet)

  • @KepaAlonso
    @KepaAlonso Год назад

    This is a simple introduction to web applications aimed at children and educational purposes: Exploring the world of HTML, CSS, and JavaScript, generated with ChatGPT. The objective is to cultivate children's interest in programming and the tools that currently facilitate code generation. In the following comments, you can find the code used.

  • @KepaAlonso
    @KepaAlonso Год назад

    7- Gravity Star: <!DOCTYPE html> <html> <head> <style> #container { width: 100%; height: 100vh; position: relative; overflow: hidden; } #star { width: 150px; height: 150px; background-color: red; position: absolute; top: 0; left: 50%; transform: translateX(-50%); clip-path: polygon( 50% 0%, 61.8% 35.3%, 95.1% 35.3%, 68.2% 57.2%, 79.4% 91.7%, 50% 70.9%, 20.6% 91.7%, 31.8% 57.2%, 4.9% 35.3%, 38.2% 35.3% ); } </style> </head> <body> <div id="container"> <div id="star"></div> </div> <script> document.addEventListener('DOMContentLoaded', () => { const container = document.getElementById('container'); const star = document.getElementById('star'); const containerHeight = container.clientHeight; const starHeight = star.clientHeight; const gravity = 1; const bounceHeightRatio = 0.9; const numBounces = 30; let position = 0; let velocity = 0; let bouncesCount = 0; function updateStar() { velocity += gravity; position += velocity; if (position + starHeight >= containerHeight) { position = containerHeight - starHeight; velocity = -velocity * bounceHeightRatio; bouncesCount++; } star.style.top = position + 'px'; if (bouncesCount < numBounces) { requestAnimationFrame(updateStar); } } updateStar(); }); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    6- Wave sound: <!DOCTYPE html> <html> <head> <title>Simulación de onda de audio</title> <style> canvas { border: 2px solid black; } </style> </head> <body> <canvas id="waveformCanvas" width="1000" height="400"></canvas> <script> // Obtener el contexto del lienzo var canvas = document.getElementById('waveformCanvas'); var context = canvas.getContext('2d'); // Tamaño de la onda var waveformWidth = canvas.width; var waveformHeight = canvas.height; // Función para dibujar la onda function drawWaveform(waveform) { context.clearRect(0, 0, waveformWidth, waveformHeight); context.beginPath(); context.moveTo(0, waveformHeight / 2); // Establecer el color de la onda context.strokeStyle = "red"; for (var i = 0; i < waveform.length; i++) { var x = i *(waveformWidth / waveform.length); var y = (waveform[i] * waveformHeight) + (waveformHeight / 2); context.lineTo(x, y); } context.stroke(); } // Obtener acceso al micrófono navigator.mediaDevices.getUserMedia({ audio: true }) .then(function (stream) { // Crear el contexto del audio var audioContext = new (window.AudioContext || window.webkitAudioContext)(); var source = audioContext.createMediaStreamSource(stream); var analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; // Conectar el micrófono al analizador source.connect(analyser); // Crear un búfer para almacenar los datos de la onda var bufferLength = analyser.frequencyBinCount; var waveform = new Float32Array(bufferLength); // Función de actualización de la onda function updateWaveform() { analyser.getFloatTimeDomainData(waveform); drawWaveform(waveform); // Volver a llamar a la función de actualización requestAnimationFrame(updateWaveform); } // Iniciar la actualización de la onda updateWaveform(); }) .catch(function (error) { console.error('Error al acceder al micrófono: ', error); }); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    5- Table tennis: <!DOCTYPE html> <html> <head> <title>Pong Game</title> <style> #pong { position: relative; width: 600px; height: 400px; border: 1px solid black; } #ball { position: absolute; top: 190px; left: 290px; width: 20px; height: 20px; border-radius: 50%; background-color: black; } .paddle { position: absolute; width: 10px; height: 60px; background-color: red; } #leftPaddle { left: 0; } #rightPaddle { right: 0; background-color: blue; } </style> </head> <body> <div id="pong"> <div id="ball"></div> <div class="paddle" id="leftPaddle"></div> <div class="paddle" id="rightPaddle"></div> </div> <div id="score"> <span id="leftScore">0</span> - <span id="rightScore">0</span> </div> <script> // Variables del juego var paddleSpeed = 5; // Velocidad de movimiento de las barras var ballSpeed = 2; // Velocidad de movimiento de la pelota var ballXSpeed = ballSpeed; // Velocidad de movimiento en el eje X de la pelota var ballYSpeed = ballSpeed; // Velocidad de movimiento en el eje Y de la pelota // Obtener elementos del DOM var pong = document.getElementById("pong"); var ball = document.getElementById("ball"); var leftPaddle = document.getElementById("leftPaddle"); var rightPaddle = document.getElementById("rightPaddle"); var leftScore = document.getElementById("leftScore"); var rightScore = document.getElementById("rightScore"); // Variables de estado var isGameStarted = false; var leftPaddleY = 160; var rightPaddleY = 160; var scoreLeft = 0; var scoreRight = 0; // Función para actualizar la posición de las barras function updatePaddles() { leftPaddle.style.top = leftPaddleY + "px"; rightPaddle.style.top = rightPaddleY + "px"; } // Función para actualizar la posición de la pelota function updateBall() { var ballX = ball.offsetLeft; var ballY = ball.offsetTop; // Comprobar colisiones con las barras if (ballX <= 20 && ballY + 20 >= leftPaddleY && ballY <= leftPaddleY + 60) { ballXSpeed = ballSpeed; } if (ballX + 20 >= 570 && ballY + 20 >= rightPaddleY && ballY <= rightPaddleY + 60) { ballXSpeed = -ballSpeed; } // Comprobar colisiones con los bordes if (ballY <= 0 || ballY >= 380) { ballYSpeed = -ballYSpeed; } // Comprobar colisión con los bordes laterales if (ballX <= 0) { // Rebote en el borde izquierdo ballXSpeed = ballSpeed; scoreRight++; // Incrementar contador de la derecha rightScore.textContent = scoreRight; // Actualizar marcador de la derecha } if (ballX + 20 >= 600) { // Rebote en el borde derecho ballXSpeed = -ballSpeed; scoreLeft++; // Incrementar contador de la izquierda leftScore.textContent = scoreLeft; // Actualizar marcador de la izquierda } // Actualizar posición de la pelota ball.style.left = ballX + ballXSpeed + "px"; ball.style.top = ballY + ballYSpeed + "px"; } // Función principal del juego function gameLoop() { if (isGameStarted) { updatePaddles(); updateBall(); } requestAnimationFrame(gameLoop); } // Eventos de teclado document.addEventListener("keydown", function(event) { if (event.key === "a") { // Mover la barra roja hacia arriba (letra 'A') if (leftPaddleY >= paddleSpeed) { leftPaddleY -= paddleSpeed; } } else if (event.key === "z") { // Mover la barra roja hacia abajo (letra 'Z') if (leftPaddleY <= 340 - paddleSpeed) { leftPaddleY += paddleSpeed; } } else if (event.key === "k") { // Mover la barra azul hacia arriba (tecla 'K') if (rightPaddleY >= paddleSpeed) { rightPaddleY -= paddleSpeed; } } else if (event.key === "m") { // Mover la barra azul hacia abajo (tecla 'M') if (rightPaddleY <= 340 - paddleSpeed) { rightPaddleY += paddleSpeed; } } else if (event.key === "q") { // Iniciar el partido (tecla 'Q') isGameStarted = true; gameLoop(); // Agregar esta línea para iniciar el bucle del juego } }); // Iniciar el bucle principal del juego gameLoop(); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    4- QWERTY keyboard: <!DOCTYPE html> <html> <head> <title>Teclado QWERTY</title> <style> .keyboard-container { display: flex; flex-direction: column; align-items: center; } .keyboard-row { display: flex; justify-content: center; margin-top: 10px; } .key-square { width: 50px; height: 50px; margin-right: 10px; border: 1px solid black; display: flex; justify-content: center; align-items: center; font-size: 20px; color: white; /* Color inicial del texto */ } .text-container { margin-top: 10px; text-align: center; } </style> </head> <body> <div class="keyboard-container"> <div class="keyboard-row"> <div class="key-square" data-key="81">Q</div> <div class="key-square" data-key="87">W</div> <div class="key-square" data-key="69">E</div> <div class="key-square" data-key="82">R</div> <div class="key-square" data-key="84">T</div> <div class="key-square" data-key="89">Y</div> <div class="key-square" data-key="85">U</div> <div class="key-square" data-key="73">I</div> <div class="key-square" data-key="79">O</div> <div class="key-square" data-key="80">P</div> </div> <div class="keyboard-row"> <div class="key-square" data-key="65">A</div> <div class="key-square" data-key="83">S</div> <div class="key-square" data-key="68">D</div> <div class="key-square" data-key="70">F</div> <div class="key-square" data-key="71">G</div> <div class="key-square" data-key="72">H</div> <div class="key-square" data-key="74">J</div> <div class="key-square" data-key="75">K</div> <div class="key-square" data-key="76">L</div> <div class="key-square" data-key="186">Ñ</div> </div> <div class="keyboard-row"> <div class="key-square" data-key="90">Z</div> <div class="key-square" data-key="88">X</div> <div class="key-square" data-key="67">C</div> <div class="key-square" data-key="86">V</div> <div class="key-square" data-key="66">B</div> <div class="key-square" data-key="78">N</div> <div class="key-square" data-key="77">M</div> <div class="key-square" data-key="188">,</div> <div class="key-square" data-key="190">.</div> </div> <div class="keyboard-row"> <div class="key-square" style="width: 350px;"></div> <!-- Espacio vacío para la barra espaciadora --> </div> </div> <div class="text-container"> <textarea id="typed-text" rows="5" style="width: 350px;"></textarea> </div> <script> var keySquares = document.querySelectorAll('.key-square'); var spaceSquare = document.querySelector('.keyboard-row:last-child .key-square:first-child'); var typedText = document.getElementById('typed-text'); // Obtener referencia al elemento <textarea> document.addEventListener("keydown", function(event) { var keyCode = event.keyCode; keySquares.forEach(function(square) { if (parseInt(square.getAttribute('data-key')) === keyCode) { square.style.color = 'black'; // Cambiar color del texto typedText.value += square.textContent; // Agregar el carácter pulsado al <textarea> // Restaurar color después de medio segundo setTimeout(function() { square.style.color = 'white'; }, 500); } }); // Detectar la barra espaciadora if (keyCode === 32) { spaceSquare.style.color = 'black'; spaceSquare.textContent = 'espacio'; typedText.value += ' '; // Agregar un espacio al <textarea> // Restaurar color después de medio segundo setTimeout(function() { spaceSquare.style.color = 'white'; }, 500); } }); // Agregar evento de pulsación para la coma y el punto var commaSquare = document.querySelector('.key-square[data-key="188"]'); var dotSquare = document.querySelector('.key-square[data-key="190"]'); commaSquare.addEventListener("mousedown", function() { commaSquare.style.color = 'black'; typedText.value += ','; // Agregar una coma al <textarea> w // Restaurar color después de medio segundo setTimeout(function() { commaSquare.style.color = 'white'; }, 500); }); dotSquare.addEventListener("mousedown", function() { dotSquare.style.color = 'black'; typedText.value += '.'; // Agregar un punto al <textarea> // Restaurar color después de medio segundo setTimeout(function() { dotSquare.style.color = 'white'; }, 500); }); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    3- Analogic Watch: <!DOCTYPE html> <html> <head> <title>Reloj JavaScript</title> <style> canvas { border: 5px solid black; } body { margin: 1; padding: 1; display: flex; justify-content: center; align-items: center; height: 100vh; } </style> </head> <body> <canvas id="reloj" width="1200" height="1200"></canvas> <script> var canvas = document.getElementById("reloj"); var context = canvas.getContext("2d"); var centerX = canvas.width / 2; var centerY = canvas.height / 2; var radius = 500; // Dibujar la esfera del reloj function drawClock() { context.fillStyle = "lightgray"; context.fillRect(0, 0, canvas.width, canvas.height); context.beginPath(); context.arc(centerX, centerY, radius, 0, 2 * Math.PI); context.lineWidth = 3; // Cambio del grosor a 10 pixeles context.strokeStyle = "black"; context.stroke(); // Dibujar los números de las horas context.fillStyle = "grey"; context.font = "bold 80px ArialBlack"; context.textAlign = "center"; context.textBaseline = "middle"; for (var i = 1; i <= 12; i++) { var angle = i * (Math.PI / 6); var x = centerX + (radius - 60) * Math.sin(angle); var y = centerY - (radius - 60) * Math.cos(angle); context.fillText(i, x, y); } } // Dibujar la manecilla de las horas function drawHourHand(hour, minute) { context.clearRect(0, 0, canvas.width, canvas.height); drawClock(); var angle = (hour % 12) * (Math.PI / 6) + (minute / 60) * (Math.PI / 6); var x = centerX + (radius - 300) * Math.sin(angle); var y = centerY - (radius - 300) * Math.cos(angle); context.font = "20px Arial"; context.beginPath(); context.moveTo(centerX, centerY); context.lineTo(x, y); context.strokeStyle = "grey"; context.lineWidth = 24; context.stroke(); } // Dibujar la manecilla de los minutos function drawMinuteHand(minute, second) { var angle = minute * (Math.PI / 30) + (second / 60) * (Math.PI / 30); var x = centerX + (radius - 100) * Math.sin(angle); var y = centerY - (radius - 100) * Math.cos(angle); context.beginPath(); context.moveTo(centerX, centerY); context.lineTo(x, y); context.strokeStyle = "darkgrey"; context.lineWidth = 10; context.stroke(); } // Dibujar la manecilla de los segundos function drawSecondHand(second) { var angle = second * (Math.PI / 30); var x = centerX + (radius - 800) * Math.sin(angle); var y = centerY - (radius - 800) * Math.cos(angle); context.beginPath(); context.moveTo(centerX, centerY); context.lineTo(x, y); context.strokeStyle = "darkgrey"; context.lineWidth = 4; context.stroke(); } // Actualizar el reloj cada segundo setInterval(function() { var date = new Date(); drawHourHand(date.getHours(), date.getMinutes()); drawMinuteHand(date.getMinutes(), date.getSeconds()); drawSecondHand(date.getSeconds()); }, 1000); </script> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    2- Rubik Cube: <!DOCTYPE html> <html> <head> <style> body { height: 100vh; display: flex; justify-content: center; align-items: center; } .cube { width: 200px; height: 200px; position: relative; transform-style: preserve-3d; animation: rotate 4s infinite linear; } .face { position: absolute; width: 200px; height: 200px; border: 2px solid black; background-color: rgba(0, 0, 0, 0.9); } .front { transform: translateZ(100px); background-color: red; } .back { transform: rotateX(180deg) translateZ(100px); background-color: orange; } .left { transform: rotateY(-90deg) translateZ(100px); background-color: blue; } .right { transform: rotateY(90deg) translateZ(100px); background-color: green; } .top { transform: rotateX(-90deg) translateZ(100px); background-color: yellow; } .bottom { transform: rotateX(90deg) translateZ(100px); background-color: white; } .line { position: absolute; background-color: black; } .line-horizontal { width: 100%; height: 2px; } .line-vertical { width: 2px; height: 100%; } @keyframes rotate { 0% { transform: rotate3d(1, 1, 0, 0deg); } 100% { transform: rotate3d(1, 1, 0, 360deg); } } </style> </head> <body> <div class="cube"> <div class="face front"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> <div class="face back"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> <div class="face left"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> <div class="face right"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> <div class="face top"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> <div class="face bottom"> <div class="line line-horizontal" style="top: 33.33%;"></div> <div class="line line-horizontal" style="top: 66.66%;"></div> <div class="line line-vertical" style="left: 33.33%;"></div> <div class="line line-vertical" style="left: 66.66%;"></div> </div> </div> </body> </html>

  • @KepaAlonso
    @KepaAlonso Год назад

    1 - Solar System: <!DOCTYPE html> <html> <head> <title>Sistema Solar</title> <style> body { background-color: black; margin: 0; overflow: hidden; } </style> </head> <body> <canvas id="solar-system"></canvas> <script> // Definir las propiedades de los planetas y sus órbitas const planets = [ { name: "Merkurio", distance: 100, diameter: 10, color: "gray", speed: 0.0001 }, { name: "Artizarra", distance: 150, diameter: 15, color: "orange", speed: 0.00008 }, { name: "Lurra", distance: 200, diameter: 20, color: "blue", speed: 0.00005 }, { name: "Marte", distance: 250, diameter: 18, color: "red", speed: 0.00003 }, { name: "Jupiter", distance: 350, diameter: 30, color: "brown", speed: 0.00002 }, { name: "Saturno", distance: 450, diameter: 28, color: "goldenrod", speed: 0.00001 }, { name: "Urano", distance: 550, diameter: 25, color: "lightblue", speed: 0.000008 }, { name: "Neptuno", distance: 650, diameter: 24, color: "darkblue", speed: 0.000005 } ]; // Obtener el elemento canvas const canvas = document.getElementById("solar-system"); const ctx = canvas.getContext("2d"); // Calcular el tamaño del canvas y centrarlo en la pantalla function calculateCanvasSize() { const canvasWidth = window.innerWidth; const canvasHeight = window.innerHeight; canvas.width = canvasWidth; canvas.height = canvasHeight; canvas.style.display = "block"; canvas.style.margin = "auto"; } // Calcular el centro del canvas function calculateCenter() { const centerX = canvas.width / 2; const centerY = canvas.height / 2; return { centerX, centerY }; } // Dibujar el sol con un degradado esférico en el relleno function drawSun(centerX, centerY) { const sunRadius = canvas.width * 0.02; const gradient = ctx.createRadialGradient( centerX, centerY, 0, centerX, centerY, sunRadius ); gradient.addColorStop(0, "yellow"); gradient.addColorStop(1, "black"); ctx.beginPath(); ctx.arc(centerX, centerY, sunRadius, 0, 2 * Math.PI); ctx.fillStyle = gradient; ctx.fill(); // Escribir "Sol" en el centro del sol ctx.fillStyle = "white"; ctx.font = "bold 12px Arial"; ctx.textAlign = "center"; ctx.fillText("Eguzkia", centerX, centerY+35); } // Dibujar los planetas con un degradado esférico en el relleno function drawPlanets(centerX, centerY) { planets.forEach(planet => { const { name, distance, diameter, color, speed } = planet; const semiMajorAxis = canvas.width * (distance / 1000) * 0.6; const semiMinorAxis = semiMajorAxis * 0.6; const angle = speed * Date.now(); const planetX = centerX + semiMajorAxis * Math.cos(angle); const planetY = centerY + semiMinorAxis * Math.sin(angle); const gradient = ctx.createRadialGradient( planetX, planetY, 0, planetX, planetY, diameter ); gradient.addColorStop(0, color); gradient.addColorStop(1, "black"); ctx.beginPath(); ctx.arc(planetX, planetY, diameter, 0, 2 * Math.PI); ctx.fillStyle = gradient; ctx.fill(); ctx.fillStyle = "white"; ctx.font = "12px Arial"; ctx.textAlign = "center"; ctx.fillText(name, planetX, planetY + diameter + 15); }); } // Dibujar las órbitas function drawOrbits(centerX, centerY) { planets.forEach(planet => { const { distance } = planet; const semiMajorAxis = canvas.width * (distance / 1000) * 0.6; const semiMinorAxis = semiMajorAxis * 0.6; ctx.beginPath(); ctx.ellipse(centerX, centerY, semiMajorAxis, semiMinorAxis, 0, 0, 2 * Math.PI); ctx.strokeStyle = "gray"; ctx.stroke(); }); } // Función para animar los planetas function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); const { centerX, centerY } = calculateCenter(); drawSun(centerX, centerY); drawOrbits(centerX, centerY); drawPlanets(centerX, centerY); requestAnimationFrame(animate); } // Calcular el tamaño del canvas inicialmente calculateCanvasSize(); // Iniciar la animación después de que se haya ajustado el tamaño del canvas window.addEventListener("resize", () => { calculateCanvasSize(); animate(); }); // Iniciar la animación animate(); </script> </body> </html>

  • @majasikic9985
    @majasikic9985 Год назад

    Milk truck 👍

  • @KepaAlonso
    @KepaAlonso Год назад

    You can find in this link code script improved with CHATGPT d44880c4-bb0a-4691-9323-aaed5fbd95a5.filesusr.com/archives/be4a96_ad2852048d5443eb94891ad3279b17a9.zip?dn=PC%20USB%20Relay%20%20-%20Toggle%20control.zip see this video ruclips.net/video/cSuowc4QfeM/видео.html

  • @KepaAlonso
    @KepaAlonso Год назад

    You can find the script "RELAY CONTROL DISPLAY.txt" on this link: d44880c4-bb0a-4691-9323-aaed5fbd95a5.filesusr.com/archives/be4a96_cea78cb2e0e94387b9602b86baaab831.zip?dn=RELAY%20CONTROL%20DISPLAY.zip

  • @nvbnvb2240
    @nvbnvb2240 Год назад

    How would this be usefull you didint even include the script or the link to it....

    • @KepaAlonso
      @KepaAlonso Год назад

      You can find the script "RELAY CONTROL DISPLAY.txt" on this link: d44880c4-bb0a-4691-9323-aaed5fbd95a5.filesusr.com/archives/be4a96_cea78cb2e0e94387b9602b86baaab831.zip?dn=RELAY%20CONTROL%20DISPLAY.zip

    • @nvbnvb2240
      @nvbnvb2240 Год назад

      @@KepaAlonso Thank you

    • @KepaAlonso
      @KepaAlonso Год назад

      You can find in this link code script improved with CHATGPT d44880c4-bb0a-4691-9323-aaed5fbd95a5.filesusr.com/archives/be4a96_ad2852048d5443eb94891ad3279b17a9.zip?dn=PC%20USB%20Relay%20%20-%20Toggle%20control.zip see this video ruclips.net/video/cSuowc4QfeM/видео.html

    • @KepaAlonso
      @KepaAlonso Год назад

      If you consider it useful, please share and subscribe to the channel

  • @acethebeast9971
    @acethebeast9971 Год назад

    Tbh I was just watching the crane spin at 1:00-1:34

  • @gsyt2356
    @gsyt2356 Год назад

    Fortnite sweats after hearing a bumblebee buzz 40 miles away: