{"id":5986,"date":"2026-03-09T12:14:15","date_gmt":"2026-03-09T15:14:15","guid":{"rendered":"https:\/\/fisica2.fica.unsl.edu.ar\/?page_id=5986"},"modified":"2026-03-09T18:16:15","modified_gmt":"2026-03-09T21:16:15","slug":"campo_magnetico_fuentes","status":"publish","type":"page","link":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/","title":{"rendered":"campo_magnetico_fuentes"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"5986\" class=\"elementor elementor-5986\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-122a6be elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"122a6be\" data-element_type=\"section\" data-e-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-125c8ff\" data-id=\"125c8ff\" data-element_type=\"column\" data-e-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-d61aea7 elementor-widget elementor-widget-html\" data-id=\"d61aea7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>Laboratorio de F\u00edsica: Campo Magn\u00e9tico<\/title>\r\n    <style>\r\n        \/* --- ESTILOS MEJORADOS --- *\/\r\n        :root {\r\n            --bg-app: #08080a;\r\n            --panel-bg: rgba(12, 12, 18, 0.98);\r\n            --text-main: #e0e6ed;\r\n            --text-dim: #5a6270;\r\n            --accent-cyan: #00d2ff;\r\n            --accent-pink: #ff3366;\r\n            --accent-yellow: #ffd93d;\r\n            --accent-green: #00ff9d;\r\n        }\r\n        * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', system-ui, sans-serif; }\r\n        body { background-color: var(--bg-app); color: var(--text-main); overflow: hidden; height: 100vh; display: flex; }\r\n\r\n        \/* Panel *\/\r\n        #controls {\r\n            width: 300px; height: 100vh;\r\n            background: var(--panel-bg);\r\n            border-right: 1px solid rgba(255,255,255,0.05);\r\n            display: flex; flex-direction: column;\r\n            z-index: 10; padding: 25px;\r\n            overflow-y: auto; flex-shrink: 0;\r\n        }\r\n        h1 { font-size: 1.1rem; color: var(--accent-cyan); margin-bottom: 5px; letter-spacing: 0.5px; }\r\n        .subtitle { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 30px; }\r\n\r\n        .section { margin-bottom: 30px; }\r\n        .section-title {\r\n            font-size: 0.65rem; text-transform: uppercase;\r\n            color: var(--text-dim); letter-spacing: 1.5px;\r\n            border-bottom: 1px solid rgba(255,255,255,0.05);\r\n            padding-bottom: 8px; margin-bottom: 15px;\r\n        }\r\n\r\n        \/* Tabs *\/\r\n        .tabs { display: flex; gap: 8px; margin-bottom: 20px; }\r\n        .tab-btn {\r\n            flex: 1; padding: 12px 5px;\r\n            background: rgba(255,255,255,0.03);\r\n            border: none; color: var(--text-dim);\r\n            border-radius: 6px; cursor: pointer;\r\n            font-size: 0.75rem; transition: 0.2s;\r\n        }\r\n        .tab-btn.active { background: var(--accent-cyan); color: #000; font-weight: bold; box-shadow: 0 0 10px rgba(0, 210, 255, 0.3); }\r\n\r\n        \/* Sliders *\/\r\n        .control-group { margin-bottom: 20px; }\r\n        .slider-header { display: flex; justify-content: space-between; font-size: 0.85rem; margin-bottom: 10px; }\r\n        .val { color: var(--accent-yellow); font-family: monospace; }\r\n        input[type=range] { width: 100%; background: #1a1a24; height: 4px; -webkit-appearance: none; border-radius: 2px; outline: none; }\r\n        input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; background: #fff; border-radius: 50%; cursor: pointer; }\r\n\r\n        \/* Toggle *\/\r\n        .toggle-row { display: flex; justify-content: space-between; align-items: center; margin: 12px 0; font-size: 0.85rem; }\r\n        .switch { width: 32px; height: 16px; background: #1a1a24; border-radius: 8px; cursor: pointer; position: relative; transition: 0.2s; }\r\n        .switch.active { background: var(--accent-green); }\r\n        .switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; background: white; border-radius: 50%; transition: 0.2s; }\r\n        .switch.active::after { transform: translateX(16px); }\r\n\r\n        .formula { font-family: 'Times New Roman', serif; font-style: italic; color: var(--text-dim); background: rgba(0,0,0,0.2); padding: 10px; border-radius: 4px; text-align: center; margin-top: 5px; font-size: 0.9rem; }\r\n\r\n        \/* Canvas Area *\/\r\n        #sim-area { flex: 1; position: relative; background: #000; overflow: hidden; }\r\n        canvas { display: block; cursor: crosshair; }\r\n\r\n        \/* Floating UI *\/\r\n        .ui-btn {\r\n            position: absolute; top: 20px; left: 20px;\r\n            background: rgba(0,0,0,0.8); border: 1px solid var(--accent-pink);\r\n            color: var(--accent-pink); padding: 8px 15px;\r\n            border-radius: 4px; cursor: pointer; z-index: 30;\r\n            font-size: 0.75rem; transition: 0.2s; font-weight: bold;\r\n        }\r\n        .ui-btn:hover { background: var(--accent-pink); color: #000; }\r\n\r\n        #sensor-info {\r\n            position: absolute; top: 20px; right: 20px;\r\n            background: rgba(0,0,0,0.85); border: 1px solid var(--accent-green);\r\n            padding: 15px; border-radius: 8px; width: 220px;\r\n            z-index: 30; box-shadow: 0 0 15px rgba(0, 255, 157, 0.1);\r\n        }\r\n        #sensor-info h4 { color: var(--accent-green); margin-bottom: 8px; font-size: 0.8rem; }\r\n        .data-row { display: flex; justify-content: space-between; font-size: 0.85rem; margin-bottom: 4px; font-family: monospace; }\r\n\r\n        .instr { position: absolute; bottom: 20px; width: 100%; text-align: center; color: rgba(255,255,255,0.3); font-size: 0.7rem; pointer-events: none; user-select: none; }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n\r\n<div id=\"controls\">\r\n    <h1>CAMPO MAGN\u00c9TICO<\/h1>\r\n    <div class=\"subtitle\">Simulaci\u00f3n Interactiva 2D\/3D<\/div>\r\n\r\n    <div class=\"section\">\r\n        <div class=\"section-title\">Sistema F\u00edsico<\/div>\r\n        <div class=\"tabs\">\r\n            <button class=\"tab-btn active\" onclick=\"setMode('wire')\">Conductor<\/button>\r\n            <button class=\"tab-btn\" onclick=\"setMode('loop')\">Espira<\/button>\r\n            <button class=\"tab-btn\" onclick=\"setMode('solenoid')\">Solenoide<\/button>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"section\">\r\n        <div class=\"section-title\">Par\u00e1metros<\/div>\r\n        \r\n        <div class=\"control-group\">\r\n            <div class=\"slider-header\"><span>Corriente (I)<\/span><span class=\"val\" id=\"val-i\">10.0 A<\/span><\/div>\r\n            <input type=\"range\" id=\"s-i\" min=\"-20\" max=\"20\" value=\"10\" step=\"0.5\">\r\n        <\/div>\r\n\r\n        <div id=\"opts-loop\" style=\"display:none;\">\r\n            <div class=\"control-group\">\r\n                <div class=\"slider-header\"><span>Radio (R)<\/span><span class=\"val\" id=\"val-r\">5.0 cm<\/span><\/div>\r\n                <input type=\"range\" id=\"s-r\" min=\"2\" max=\"10\" value=\"5\" step=\"0.1\">\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div id=\"opts-solenoid\" style=\"display:none;\">\r\n            <div class=\"control-group\">\r\n                <div class=\"slider-header\"><span>Espiras (N)<\/span><span class=\"val\" id=\"val-n\">10<\/span><\/div>\r\n                <input type=\"range\" id=\"s-n\" min=\"1\" max=\"30\" value=\"10\" step=\"1\">\r\n            <\/div>\r\n            <div class=\"control-group\">\r\n                <div class=\"slider-header\"><span>Longitud (L)<\/span><span class=\"val\" id=\"val-l\">20 cm<\/span><\/div>\r\n                <input type=\"range\" id=\"s-l\" min=\"5\" max=\"40\" value=\"20\" step=\"1\">\r\n            <\/div>\r\n        <\/div>\r\n        \r\n        <div class=\"control-group\">\r\n            <div class=\"slider-header\"><span>Escala Vectores<\/span><span class=\"val\" id=\"val-scale\">1.0x<\/span><\/div>\r\n            <input type=\"range\" id=\"s-scale\" min=\"0.2\" max=\"2\" value=\"1\" step=\"0.1\">\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"section\">\r\n        <div class=\"section-title\">Visualizaci\u00f3n<\/div>\r\n        <div class=\"toggle-row\">\r\n            <span>L\u00edneas de Inducci\u00f3n<\/span>\r\n            <div class=\"switch active\" id=\"tgl-lines\" onclick=\"toggle('lines')\"><\/div>\r\n        <\/div>\r\n        <div class=\"toggle-row\">\r\n            <span>Vectores de Campo<\/span>\r\n            <div class=\"switch active\" id=\"tgl-vec\" onclick=\"toggle('vec')\"><\/div>\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"formula-box\" class=\"formula\">B = (\u03bc\u2080 I) \/ (2\u03c0 r)<\/div>\r\n<\/div>\r\n\r\n<div id=\"sim-area\">\r\n    <button class=\"ui-btn\" onclick=\"toggleView()\">Vista 3D<\/button>\r\n    \r\n    <canvas id=\"c\"><\/canvas>\r\n    \r\n    <div id=\"sensor-info\">\r\n        <h4>SENSOR DE CAMPO B<\/h4>\r\n        <div class=\"data-row\"><span style=\"color:var(--text-dim)\">Posici\u00f3n:<\/span><span class=\"val\" id=\"d-pos\">0, 0 cm<\/span><\/div>\r\n        <div class=\"data-row\"><span style=\"color:var(--text-dim)\">Magnitud:<\/span><span class=\"val\" id=\"d-mag\" style=\"color:var(--accent-cyan)\">0.00 T<\/span><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"instr\">Arrastra el punto verde para medir. Click derecho mueve la vista. Scroll para zoom.<\/div>\r\n<\/div>\r\n\r\n<script>\r\n    \/\/ --- CONFIGURACI\u00d3N INICIAL ---\r\n    const U0 = 4 * Math.PI * 1e-7;\r\n    const canvas = document.getElementById('c');\r\n    const ctx = canvas.getContext('2d');\r\n    let W = 0, H = 0; \/\/ Dimensiones globales inicializadas en 0\r\n    \r\n    const state = {\r\n        mode: 'wire',\r\n        I: 10, R: 0.05, N: 10, L: 0.2,\r\n        scale: 1.0,\r\n        showLines: true,\r\n        showVec: true,\r\n        is3D: false,\r\n        time: 0\r\n    };\r\n\r\n    \/\/ C\u00e1mara y Sensor\r\n    let cam = { x: 0, y: 0, zoom: 1, dragging: false, lastX: 0, lastY: 0 };\r\n    let sensor = { x: 0, y: 0, dragging: false };\r\n    let initialized = false; \/\/ Bandera de seguridad\r\n\r\n    \/\/ INICIO SEGURO\r\n    window.onload = function() {\r\n        init();\r\n    };\r\n\r\n    function init() {\r\n        resize(); \/\/ Forzar c\u00e1lculo de tama\u00f1o\r\n        if(W === 0) { \/\/ Fallback extremo\r\n            W = 800; H = 600;\r\n            canvas.width = W; canvas.height = H;\r\n        }\r\n        \r\n        window.addEventListener('resize', resize);\r\n        \r\n        \/\/ Eventos\r\n        canvas.addEventListener('mousedown', onMouseDown);\r\n        window.addEventListener('mousemove', onMouseMove);\r\n        window.addEventListener('mouseup', onMouseUp);\r\n        canvas.addEventListener('wheel', onWheel, { passive: false });\r\n        \r\n        bindUI();\r\n        initialized = true;\r\n        requestAnimationFrame(loop);\r\n    }\r\n\r\n    function resize() {\r\n        const parent = canvas.parentElement;\r\n        if(!parent) return;\r\n        W = parent.clientWidth;\r\n        H = parent.clientHeight;\r\n        canvas.width = W;\r\n        canvas.height = H;\r\n        \r\n        \/\/ Reposicionar sensor si es la primera vez\r\n        if(!initialized && W > 0) {\r\n            sensor.x = W\/2 + 100;\r\n            sensor.y = H\/2;\r\n        }\r\n    }\r\n\r\n    function onMouseDown(e) {\r\n        const rect = canvas.getBoundingClientRect();\r\n        const mx = e.clientX - rect.left;\r\n        const my = e.clientY - rect.top;\r\n        \r\n        const dx = mx - sensor.x;\r\n        const dy = my - sensor.y;\r\n        if (Math.sqrt(dx*dx + dy*dy) < 15) {\r\n            sensor.dragging = true;\r\n        } else {\r\n            cam.dragging = true;\r\n            cam.lastX = mx;\r\n            cam.lastY = my;\r\n        }\r\n    }\r\n\r\n    function onMouseMove(e) {\r\n        const rect = canvas.getBoundingClientRect();\r\n        const mx = e.clientX - rect.left;\r\n        const my = e.clientY - rect.top;\r\n        \r\n        if (sensor.dragging) {\r\n            sensor.x = mx;\r\n            sensor.y = my;\r\n        } else if (cam.dragging) {\r\n            cam.x += (mx - cam.lastX);\r\n            cam.y += (my - cam.lastY);\r\n            cam.lastX = mx;\r\n            cam.lastY = my;\r\n        }\r\n    }\r\n\r\n    function onMouseUp() { sensor.dragging = false; cam.dragging = false; }\r\n    \r\n    function onWheel(e) {\r\n        e.preventDefault();\r\n        cam.zoom *= e.deltaY > 0 ? 0.9 : 1.1;\r\n        cam.zoom = Math.max(0.3, Math.min(cam.zoom, 5));\r\n    }\r\n\r\n    \/\/ --- F\u00cdSICA ---\r\n    function calcB(px, py) {\r\n        let Bx = 0, By = 0;\r\n        const I = state.I;\r\n        \r\n        if (state.mode === 'wire') {\r\n            const r = Math.sqrt(px*px + py*py);\r\n            if (r < 0.005) return {x:0, y:0, mag:0};\r\n            const Bmag = (U0 * Math.abs(I)) \/ (2 * Math.PI * r);\r\n            const theta = Math.atan2(py, px);\r\n            const sign = I > 0 ? 1 : -1;\r\n            Bx = -sign * Math.sin(theta) * Bmag;\r\n            By = sign * Math.cos(theta) * Bmag;\r\n            \r\n        } else if (state.mode === 'loop') {\r\n            const R = state.R;\r\n            const dist = Math.sqrt(px*px + py*py);\r\n            if (dist < 0.01) return {x:0, y:0, mag:0};\r\n            const m = I * Math.PI * R * R; \r\n            const r3 = dist*dist*dist;\r\n            const Bmag = (U0 * Math.abs(m)) \/ (4 * Math.PI * r3);\r\n            const angle = Math.atan2(px, py); \r\n            By = Bmag * Math.cos(angle * 2); \r\n            Bx = Bmag * Math.sin(angle * 2);\r\n            \/\/ Eje exacto\r\n            if (Math.abs(px) < 0.01) {\r\n                 By = (U0 * I * R*R) \/ (2 * Math.pow(R*R + py*py, 1.5));\r\n                 Bx = 0;\r\n            }\r\n        } else if (state.mode === 'solenoid') {\r\n            const halfL = state.L \/ 2;\r\n            const rInner = 0.05;\r\n            if (Math.abs(px) < halfL && Math.abs(py) < rInner) {\r\n                const Bmag = U0 * (state.N \/ state.L) * I;\r\n                Bx = Bmag;\r\n                By = 0;\r\n            }\r\n        }\r\n        return { x: Bx, y: By, mag: Math.sqrt(Bx*Bx + By*By) };\r\n    }\r\n\r\n    \/\/ --- RENDERIZADO ---\r\n    function draw() {\r\n        if(!initialized || W === 0) return;\r\n        \r\n        ctx.fillStyle = '#050508';\r\n        ctx.fillRect(0, 0, W, H);\r\n        \r\n        ctx.save();\r\n        ctx.translate(W\/2 + cam.x, H\/2 + cam.y);\r\n        ctx.scale(cam.zoom, cam.zoom);\r\n        \r\n        \/\/ Efecto 3D Isom\u00e9trico\r\n        if(state.is3D) {\r\n            ctx.transform(1, 0, -0.5, 1, 0, 0); \r\n            ctx.translate(0, 50); \/\/ Bajar un poco el origen\r\n        }\r\n        \r\n        drawGrid();\r\n        drawSystem();\r\n        if (state.showLines) drawFieldLines();\r\n        if (state.showVec) drawVectorGrid();\r\n        \r\n        ctx.restore();\r\n        drawSensor();\r\n    }\r\n\r\n    function drawGrid() {\r\n        ctx.strokeStyle = 'rgba(255,255,255,0.03)';\r\n        const step = 50;\r\n        for(let i=-2000; i<=2000; i+=step) {\r\n            ctx.beginPath(); ctx.moveTo(i, -2000); ctx.lineTo(i, 2000); ctx.stroke();\r\n            ctx.beginPath(); ctx.moveTo(-2000, i); ctx.lineTo(2000, i); ctx.stroke();\r\n        }\r\n    }\r\n\r\n    function drawSystem() {\r\n        const s = 100; \r\n        ctx.lineWidth = 2;\r\n        \r\n        if (state.mode === 'wire') {\r\n            ctx.fillStyle = state.I > 0 ? '#ff3366' : '#3366ff';\r\n            ctx.beginPath(); ctx.arc(0, 0, 10, 0, Math.PI*2); ctx.fill();\r\n            ctx.fillStyle = 'white';\r\n            ctx.font = 'bold 16px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';\r\n            ctx.fillText(state.I > 0 ? '\u2299' : '\u2297', 0, 1);\r\n            \r\n        } else if (state.mode === 'loop') {\r\n            const r = state.R * s;\r\n            ctx.strokeStyle = '#ff3366';\r\n            ctx.lineWidth = 4;\r\n            ctx.beginPath(); ctx.moveTo(0, -r); ctx.lineTo(0, r); ctx.stroke();\r\n            ctx.fillStyle = '#ff3366';\r\n            ctx.beginPath(); ctx.arc(0, -r, 5, 0, Math.PI*2); ctx.fill();\r\n            ctx.beginPath(); ctx.arc(0, r, 5, 0, Math.PI*2); ctx.stroke();\r\n            \r\n        } else if (state.mode === 'solenoid') {\r\n            const len = state.L * s \/ 2;\r\n            const h = 25;\r\n            ctx.strokeStyle = '#ff3366';\r\n            ctx.lineWidth = 3;\r\n            ctx.strokeRect(-len, -h, len*2, h*2);\r\n            ctx.lineWidth = 1;\r\n            ctx.strokeStyle = 'rgba(255, 51, 102, 0.3)';\r\n            for(let x = -len + 10; x < len; x += 15) {\r\n                ctx.beginPath(); ctx.moveTo(x, -h); ctx.lineTo(x, h); ctx.stroke();\r\n            }\r\n        }\r\n    }\r\n\r\n    function drawFieldLines() {\r\n        const I = state.I;\r\n        if (Math.abs(I) < 0.1) return;\r\n        ctx.strokeStyle = 'rgba(0, 210, 255, 0.4)';\r\n        ctx.lineWidth = 1;\r\n        \r\n        let numLines = Math.floor(Math.abs(I) \/ 1.5);\r\n        numLines = Math.max(4, Math.min(numLines, 18));\r\n        \r\n        if (state.mode === 'wire') {\r\n            for(let i=0; i<numLines; i++) {\r\n                const angle = (i\/numLines) * Math.PI * 2;\r\n                const a = angle + state.time * (I > 0 ? 1 : -1);\r\n                ctx.beginPath();\r\n                ctx.arc(0, 0, 400, a, a + (Math.PI*2\/numLines)*0.85);\r\n                ctx.stroke();\r\n                \r\n                const endA = a + (Math.PI*2\/numLines)*0.85;\r\n                const dir = I > 0 ? 1 : -1;\r\n                drawArrow(Math.cos(endA)*400, Math.sin(endA)*400, endA + Math.PI\/2 * dir, 8, '#00d2ff');\r\n            }\r\n        } else if (state.mode === 'loop') {\r\n            const dir = I > 0 ? -1 : 1;\r\n            for(let i=0; i<numLines; i++) {\r\n                const startX = ( (i\/(numLines-1)) - 0.5 ) * 50;\r\n                ctx.beginPath();\r\n                ctx.moveTo(startX, 0);\r\n                ctx.bezierCurveTo(startX + 100, -150 * dir, startX + 100, 150 * dir, -startX, 0);\r\n                ctx.stroke();\r\n            }\r\n        } else if (state.mode === 'solenoid') {\r\n            const len = state.L * s \/ 2;\r\n            const h = 25;\r\n            ctx.beginPath();\r\n            for(let y=-h+5; y<h; y+=10) {\r\n                ctx.moveTo(-len-10, y); ctx.lineTo(len+10, y);\r\n            }\r\n            ctx.stroke();\r\n            if (I !== 0) {\r\n                const offset = (state.time * 80 * (I > 0 ? 1 : -1)) % 40;\r\n                for(let x = -len + offset; x < len; x += 40) drawArrow(x, 0, 0, 6, '#00d2ff');\r\n            }\r\n        }\r\n    }\r\n\r\n    function drawVectorGrid() {\r\n        const s = 100;\r\n        const step = 80; \/\/ Espaciado \u00f3ptimo\r\n        for(let x = -W; x < W; x += step) {\r\n            for(let y = -H; y < H; y += step) {\r\n                \/\/ Convertir a metros\r\n                let wx = (x - W\/2 - cam.x) \/ cam.zoom;\r\n                let wy = (y - H\/2 - cam.y) \/ cam.zoom;\r\n                \r\n                \/\/ Ajuste inverso para 3D para que el mouse coincida aproximadamente\r\n                if(state.is3D) {\r\n                    \/\/ Aproximaci\u00f3n inversa simple\r\n                    wy *= 1.1; \r\n                    wx += wy * 0.5;\r\n                }\r\n\r\n                const px = wx \/ s;\r\n                const py = -wy \/ s;\r\n                const B = calcB(px, py);\r\n                \r\n                if (B.mag > 1e-6) {\r\n                    let len = B.mag * 12000 * state.scale; \r\n                    len = Math.max(4, Math.min(len, 35)); \r\n                    \r\n                    const angle = Math.atan2(-B.y, B.x);\r\n                    \r\n                    ctx.strokeStyle = '#ffd93d';\r\n                    ctx.lineWidth = 1.5;\r\n                    ctx.beginPath();\r\n                    ctx.moveTo(x, y);\r\n                    ctx.lineTo(x + Math.cos(angle)*len, y + Math.sin(angle)*len);\r\n                    ctx.stroke();\r\n                    \r\n                    ctx.fillStyle = '#ffd93d';\r\n                    drawArrow(x + Math.cos(angle)*len, y + Math.sin(angle)*len, angle, 3, '#ffd93d');\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    function drawSensor() {\r\n        const sx = sensor.x;\r\n        const sy = sensor.y;\r\n        \r\n        \/\/ Coordenadas f\u00edsicas\r\n        let wx = (sx - W\/2 - cam.x) \/ cam.zoom;\r\n        let wy = (sy - H\/2 - cam.y) \/ cam.zoom;\r\n        \r\n        if(state.is3D) {\r\n             wy *= 1.1; wx += wy * 0.5;\r\n        }\r\n        \r\n        const px = wx \/ 100;\r\n        const py = -wy \/ 100;\r\n        \r\n        ctx.strokeStyle = '#00ff9d';\r\n        ctx.lineWidth = 2;\r\n        ctx.beginPath();\r\n        ctx.arc(sx, sy, 12, 0, Math.PI*2);\r\n        ctx.moveTo(sx-18, sy); ctx.lineTo(sx+18, sy);\r\n        ctx.moveTo(sx, sy-18); ctx.lineTo(sx, sy+18);\r\n        ctx.stroke();\r\n        \r\n        const B = calcB(px, py);\r\n        \r\n        if (B.mag > 1e-6) {\r\n            const len = Math.min(B.mag * 20000 * state.scale, 80);\r\n            const angle = Math.atan2(-B.y, B.x);\r\n            \r\n            ctx.strokeStyle = '#00ff9d';\r\n            ctx.lineWidth = 3;\r\n            ctx.beginPath();\r\n            ctx.moveTo(sx, sy);\r\n            ctx.lineTo(sx + Math.cos(angle)*len, sy + Math.sin(angle)*len);\r\n            ctx.stroke();\r\n            ctx.fillStyle = '#00ff9d';\r\n            drawArrow(sx + Math.cos(angle)*len, sy + Math.sin(angle)*len, angle, 6, '#00ff9d');\r\n        }\r\n        \r\n        document.getElementById('sensor-info').style.display = 'block';\r\n        document.getElementById('d-pos').innerText = `${px.toFixed(2)}, ${py.toFixed(2)}`;\r\n        document.getElementById('d-mag').innerText = B.mag.toExponential(2) + \" T\";\r\n    }\r\n\r\n    function drawArrow(x, y, angle, size, color) {\r\n        ctx.save();\r\n        ctx.translate(x, y);\r\n        ctx.rotate(angle);\r\n        ctx.beginPath();\r\n        ctx.moveTo(0, 0);\r\n        ctx.lineTo(-size, -size\/2);\r\n        ctx.lineTo(-size, size\/2);\r\n        ctx.closePath();\r\n        ctx.fillStyle = color;\r\n        ctx.fill();\r\n        ctx.restore();\r\n    }\r\n\r\n    \/\/ --- UI & LOOP ---\r\n    function setMode(m) {\r\n        state.mode = m;\r\n        document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));\r\n        event.target.classList.add('active');\r\n        \r\n        document.getElementById('opts-loop').style.display = m === 'loop' ? 'block' : 'none';\r\n        document.getElementById('opts-solenoid').style.display = m === 'solenoid' ? 'block' : 'none';\r\n        \r\n        const box = document.getElementById('formula-box');\r\n        if (m === 'wire') box.innerText = \"B = (\u03bc\u2080 I) \/ (2\u03c0 r)\";\r\n        else if (m === 'loop') box.innerText = \"B = (\u03bc\u2080 I R\u00b2) \/ 2(R\u00b2+x\u00b2)^(3\/2)\";\r\n        else box.innerText = \"B = \u03bc\u2080 (N\/L) I\";\r\n    }\r\n\r\n    function toggle(type) {\r\n        const el = event.currentTarget;\r\n        el.classList.toggle('active');\r\n        if (type === 'lines') state.showLines = el.classList.contains('active');\r\n        if (type === 'vec') state.showVec = el.classList.contains('active');\r\n    }\r\n\r\n    function toggleView() {\r\n        state.is3D = !state.is3D;\r\n        const btn = document.querySelector('.ui-btn');\r\n        btn.innerText = state.is3D ? \"Vista 2D\" : \"Vista 3D\";\r\n        cam.x = 0; cam.y = 0;\r\n    }\r\n\r\n    function bindUI() {\r\n        document.getElementById('s-i').oninput = e => { state.I = parseFloat(e.target.value); document.getElementById('val-i').innerText = state.I.toFixed(1); };\r\n        document.getElementById('s-r').oninput = e => { state.R = parseFloat(e.target.value)\/100; document.getElementById('val-r').innerText = e.target.value; };\r\n        document.getElementById('s-n').oninput = e => { state.N = parseInt(e.target.value); document.getElementById('val-n').innerText = state.N; };\r\n        document.getElementById('s-l').oninput = e => { state.L = parseFloat(e.target.value)\/100; document.getElementById('val-l').innerText = e.target.value; };\r\n        document.getElementById('s-scale').oninput = e => { state.scale = parseFloat(e.target.value); document.getElementById('val-scale').innerText = state.scale.toFixed(1) + 'x'; };\r\n    }\r\n\r\n    function loop() {\r\n        state.time += 0.016;\r\n        draw();\r\n        requestAnimationFrame(loop);\r\n    }\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\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<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6de7fef elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6de7fef\" data-element_type=\"section\" data-e-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-cf31aaa\" data-id=\"cf31aaa\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\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>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Laboratorio de F\u00edsica: Campo Magn\u00e9tico CAMPO MAGN\u00c9TICO Simulaci\u00f3n Interactiva 2D\/3D Sistema F\u00edsico Conductor Espira Solenoide Par\u00e1metros Corriente (I)10.0 A Radio (R)5.0 cm Espiras (N)10 Longitud&hellip;<\/p>\n","protected":false},"author":7,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-5986","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>campo_magnetico_fuentes - F\u00edsica 2<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"campo_magnetico_fuentes - F\u00edsica 2\" \/>\n<meta property=\"og:description\" content=\"Laboratorio de F\u00edsica: Campo Magn\u00e9tico CAMPO MAGN\u00c9TICO Simulaci\u00f3n Interactiva 2D\/3D Sistema F\u00edsico Conductor Espira Solenoide Par\u00e1metros Corriente (I)10.0 A Radio (R)5.0 cm Espiras (N)10 Longitud&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/\" \/>\n<meta property=\"og:site_name\" content=\"F\u00edsica 2\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-09T21:16:15+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/campo_magnetico_fuentes\\\/\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/campo_magnetico_fuentes\\\/\",\"name\":\"campo_magnetico_fuentes - F\u00edsica 2\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#website\"},\"datePublished\":\"2026-03-09T15:14:15+00:00\",\"dateModified\":\"2026-03-09T21:16:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/campo_magnetico_fuentes\\\/#breadcrumb\"},\"inLanguage\":\"es-AR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/campo_magnetico_fuentes\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/index.php\\\/campo_magnetico_fuentes\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Inicio\",\"item\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"campo_magnetico_fuentes\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#website\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\",\"name\":\"F\u00edsica 2\",\"description\":\"FICA - UNSL\",\"publisher\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es-AR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#organization\",\"name\":\"SAC- Secretar\u00eda General FICA\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es-AR\",\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/SG-Logo.png\",\"contentUrl\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/wp-content\\\/uploads\\\/2021\\\/11\\\/SG-Logo.png\",\"width\":4483,\"height\":1231,\"caption\":\"SAC- Secretar\u00eda General FICA\"},\"image\":{\"@id\":\"https:\\\/\\\/fisica2.fica.unsl.edu.ar\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"campo_magnetico_fuentes - F\u00edsica 2","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/","og_locale":"es_ES","og_type":"article","og_title":"campo_magnetico_fuentes - F\u00edsica 2","og_description":"Laboratorio de F\u00edsica: Campo Magn\u00e9tico CAMPO MAGN\u00c9TICO Simulaci\u00f3n Interactiva 2D\/3D Sistema F\u00edsico Conductor Espira Solenoide Par\u00e1metros Corriente (I)10.0 A Radio (R)5.0 cm Espiras (N)10 Longitud&hellip;","og_url":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/","og_site_name":"F\u00edsica 2","article_modified_time":"2026-03-09T21:16:15+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/","url":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/","name":"campo_magnetico_fuentes - F\u00edsica 2","isPartOf":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#website"},"datePublished":"2026-03-09T15:14:15+00:00","dateModified":"2026-03-09T21:16:15+00:00","breadcrumb":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/#breadcrumb"},"inLanguage":"es-AR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/campo_magnetico_fuentes\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https:\/\/fisica2.fica.unsl.edu.ar\/"},{"@type":"ListItem","position":2,"name":"campo_magnetico_fuentes"}]},{"@type":"WebSite","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#website","url":"https:\/\/fisica2.fica.unsl.edu.ar\/","name":"F\u00edsica 2","description":"FICA - UNSL","publisher":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fisica2.fica.unsl.edu.ar\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es-AR"},{"@type":"Organization","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#organization","name":"SAC- Secretar\u00eda General FICA","url":"https:\/\/fisica2.fica.unsl.edu.ar\/","logo":{"@type":"ImageObject","inLanguage":"es-AR","@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#\/schema\/logo\/image\/","url":"https:\/\/fisica2.fica.unsl.edu.ar\/wp-content\/uploads\/2021\/11\/SG-Logo.png","contentUrl":"https:\/\/fisica2.fica.unsl.edu.ar\/wp-content\/uploads\/2021\/11\/SG-Logo.png","width":4483,"height":1231,"caption":"SAC- Secretar\u00eda General FICA"},"image":{"@id":"https:\/\/fisica2.fica.unsl.edu.ar\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5986","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/comments?post=5986"}],"version-history":[{"count":32,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5986\/revisions"}],"predecessor-version":[{"id":6019,"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/pages\/5986\/revisions\/6019"}],"wp:attachment":[{"href":"https:\/\/fisica2.fica.unsl.edu.ar\/index.php\/wp-json\/wp\/v2\/media?parent=5986"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}