{"id":2318,"date":"2025-12-09T09:07:02","date_gmt":"2025-12-09T08:07:02","guid":{"rendered":"https:\/\/kemiformler.dk\/?page_id=2318"},"modified":"2025-12-09T09:54:03","modified_gmt":"2025-12-09T08:54:03","slug":"maengdeberegning","status":"publish","type":"page","link":"https:\/\/kemiformler.dk\/index.php\/maengdeberegning\/","title":{"rendered":"M\u00e6ngdeberegning"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2318\" class=\"elementor elementor-2318\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3c1ae8b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3c1ae8b\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4cded14\" data-id=\"4cded14\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0f23914 elementor-widget elementor-widget-html\" data-id=\"0f23914\" data-element_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=\"da\">\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>Kemi-Animation: R\/S Isomeri (Ball & Stick V5)<\/title>\r\n    <style>\r\n        :root {\r\n            --bg-color: #1a1a2e;\r\n            --text-color: #e0e0e0;\r\n            --panel-bg: #252542;\r\n            --accent: #4a90e2;\r\n            --accent-hover: #357abd;\r\n            --danger: #e74c3c;\r\n        }\r\n        body {\r\n            margin: 0;\r\n            padding: 0;\r\n            font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\r\n            background-color: var(--bg-color);\r\n            color: var(--text-color);\r\n            display: flex;\r\n            flex-direction: column;\r\n            height: 100vh;\r\n            overflow: hidden;\r\n        }\r\n        #canvas-container {\r\n            flex: 1; \r\n            position: relative;\r\n            background: radial-gradient(circle at center, #2a2a4a 0%, #1a1a2e 100%);\r\n            overflow: hidden;\r\n        }\r\n        canvas {\r\n            display: block;\r\n            width: 100%;\r\n            height: 100%;\r\n            cursor: grab;\r\n        }\r\n        canvas:active {\r\n            cursor: grabbing;\r\n        }\r\n        \r\n        \/* UI OVERLAY *\/\r\n        #status-panel {\r\n            position: absolute;\r\n            top: 15px;\r\n            left: 15px;\r\n            background: rgba(20, 20, 30, 0.75); \r\n            backdrop-filter: blur(6px);\r\n            padding: 15px;\r\n            border-radius: 8px;\r\n            border: 1px solid rgba(255,255,255,0.1);\r\n            pointer-events: none;\r\n            user-select: none;\r\n            max-width: 300px;\r\n        }\r\n        #molecule-name {\r\n            font-size: 1.1rem; \r\n            font-weight: 600;\r\n            margin-bottom: 5px;\r\n            color: #fff;\r\n        }\r\n        #config-state {\r\n            font-size: 1.4rem; \r\n            font-weight: bold;\r\n            color: #f1c40f;\r\n            margin-bottom: 10px;\r\n            line-height: 1.2;\r\n        }\r\n        \r\n        .legend {\r\n            font-size: 0.85rem;\r\n            display: flex;\r\n            flex-wrap: wrap;\r\n            gap: 12px;\r\n            padding-top: 8px;\r\n            border-top: 1px solid rgba(255,255,255,0.1);\r\n        }\r\n        .legend-item {\r\n            display: flex;\r\n            align-items: center;\r\n        }\r\n        .legend-item i {\r\n            display: inline-block;\r\n            width: 12px;\r\n            height: 12px;\r\n            border-radius: 50%;\r\n            margin-right: 6px;\r\n            border: 1px solid rgba(255,255,255,0.3);\r\n        }\r\n\r\n        \/* CONTROLS *\/\r\n        #controls {\r\n            background-color: var(--panel-bg);\r\n            padding: 12px 20px;\r\n            display: flex;\r\n            flex-wrap: wrap;\r\n            gap: 12px;\r\n            justify-content: center;\r\n            align-items: center;\r\n            border-top: 1px solid #3a3a5e;\r\n            z-index: 10;\r\n            box-shadow: 0 -4px 10px rgba(0,0,0,0.2);\r\n        }\r\n        .control-group {\r\n            display: flex;\r\n            gap: 8px;\r\n            align-items: center;\r\n            background: rgba(0,0,0,0.2);\r\n            padding: 6px 12px;\r\n            border-radius: 4px;\r\n            font-size: 0.9rem;\r\n        }\r\n        button {\r\n            background-color: var(--accent);\r\n            color: white;\r\n            border: none;\r\n            padding: 10px 16px;\r\n            border-radius: 4px;\r\n            cursor: pointer;\r\n            font-size: 0.95rem;\r\n            transition: all 0.2s;\r\n            font-weight: 600;\r\n        }\r\n        button:hover {\r\n            background-color: var(--accent-hover);\r\n            transform: translateY(-1px);\r\n        }\r\n        button:active {\r\n            transform: scale(0.98);\r\n        }\r\n        button.secondary {\r\n            background-color: transparent;\r\n            border: 1px solid var(--accent);\r\n        }\r\n        button.secondary:hover {\r\n            background-color: rgba(74, 144, 226, 0.1);\r\n        }\r\n        button#resetBtn {\r\n            background-color: var(--danger);\r\n        }\r\n        button#resetBtn:hover {\r\n            background-color: #c0392b;\r\n        }\r\n    <\/style>\r\n<\/head>\r\n<body>\r\n\r\n<div id=\"canvas-container\">\r\n    <canvas id=\"moleculeCanvas\"><\/canvas>\r\n    <div id=\"status-panel\">\r\n        <div id=\"molecule-name\">Bromchlorfluormethan<\/div>\r\n        <div id=\"config-state\">Konfiguration: Ukendt<\/div>\r\n        <div class=\"legend\">\r\n            <div class=\"legend-item\"><i style=\"background:#333;\"><\/i>C<\/div>\r\n            <div class=\"legend-item\"><i style=\"background:#a52a2a;\"><\/i>Br (1)<\/div>\r\n            <div class=\"legend-item\"><i style=\"background:#2ecc71;\"><\/i>Cl (2)<\/div>\r\n            <div class=\"legend-item\"><i style=\"background:#3498db;\"><\/i>F (3)<\/div>\r\n            <div class=\"legend-item\"><i style=\"background:#ecf0f1;\"><\/i>H (4)<\/div>\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<div id=\"controls\">\r\n    <div class=\"control-group\">\r\n        <label for=\"showPriorities\" style=\"cursor:pointer; display:flex; align-items:center;\">\r\n            <span style=\"margin-right:8px;\">Vis Tal (CIP)<\/span>\r\n            <input type=\"checkbox\" id=\"showPriorities\" checked>\r\n        <\/label>\r\n    <\/div>\r\n    <button id=\"switchEnantiomerBtn\" class=\"secondary\">\u2194 Skift Enantiomer<\/button>\r\n    <button id=\"autoOrientBtn\">\ud83d\udc41\ufe0f Auto-Orienter (Vis R\/S)<\/button>\r\n    <button id=\"resetBtn\">\u21ba<\/button>\r\n<\/div>\r\n\r\n<script>\r\n\/\/ --- KONSTANTER & GLOBALE VARIABLER ---\r\nconst canvas = document.getElementById('moleculeCanvas');\r\nconst ctx = canvas.getContext('2d');\r\nlet width, height;\r\n\r\n\/\/ Atomdata\r\nconst ATOM_DATA = {\r\n    'C': { color: '#333333', radius: 25, z: 6, name: 'Carbon' }, \r\n    'H': { color: '#ecf0f1', radius: 14, z: 1, name: 'Hydrogen' },\r\n    'Br':{ color: '#a52a2a', radius: 26, z: 35, name: 'Brom' },\r\n    'Cl':{ color: '#2ecc71', radius: 24, z: 17, name: 'Chlor' },\r\n    'F': { color: '#3498db', radius: 20, z: 9, name: 'Fluor' }\r\n};\r\n\r\n\/\/ Tilstandsvariabler\r\nlet gameState = {\r\n    isRConfiguration: true,\r\n    showPriorities: true,\r\n    isAutoOriented: false,\r\n    rotation: { x: 0.3, y: 0.3, z: 0 },\r\n    targetRotation: null,\r\n    animating: false\r\n};\r\n\r\n\/\/ 3D Motor Variabler\r\nlet atoms = [];\r\nlet bonds = [];\r\nconst BOND_LENGTH = 170; \r\nlet focalLength = 900;\r\nlet mouse = { x: 0, y: 0, down: false, lastX: 0, lastY: 0 };\r\n\r\nconst PRIORITY_SYMBOLS = ['\u2460', '\u2461', '\u2462', '\u2463'];\r\n\r\n\/\/ --- KLASSER ---\r\nclass Atom {\r\n    constructor(symbol, x, y, z, id) {\r\n        this.symbol = symbol;\r\n        this.pos = { x, y, z };\r\n        this.origPos = { x, y, z };\r\n        this.data = ATOM_DATA[symbol];\r\n        this.id = id;\r\n        this.priority = 0; \r\n        this.screenPos = { x: 0, y: 0, scale: 0 };\r\n    }\r\n\r\n    project() {\r\n        let scale = focalLength \/ (focalLength + this.pos.z);\r\n        this.screenPos.x = width \/ 2 + this.pos.x * scale;\r\n        this.screenPos.y = height \/ 2 + this.pos.y * scale;\r\n        this.screenPos.scale = scale;\r\n    }\r\n\r\n    draw() {\r\n        let scale = this.screenPos.scale;\r\n        let r = this.data.radius * scale;\r\n        \r\n        \/\/ Simuler 3D kugle med radial gradient\r\n        let grad = ctx.createRadialGradient(\r\n            this.screenPos.x - r\/3, this.screenPos.y - r\/3, r\/10,\r\n            this.screenPos.x, this.screenPos.y, r\r\n        );\r\n        grad.addColorStop(0, lighten(this.data.color, 40));\r\n        grad.addColorStop(1, this.data.color);\r\n\r\n        ctx.beginPath();\r\n        ctx.arc(this.screenPos.x, this.screenPos.y, r, 0, Math.PI * 2);\r\n        ctx.fillStyle = grad;\r\n        ctx.fill();\r\n        ctx.strokeStyle = \"rgba(0,0,0,0.4)\";\r\n        ctx.lineWidth = 1 * scale;\r\n        ctx.stroke();\r\n\r\n        ctx.fillStyle = this.data.z === 1 || this.data.z === 6 ? '#000' : '#fff';\r\n        if (this.data.z === 6) ctx.fillStyle = '#fff';\r\n        ctx.font = `bold ${16 * scale}px Arial`;\r\n        ctx.textAlign = 'center';\r\n        ctx.textBaseline = 'middle';\r\n        ctx.fillText(this.symbol, this.screenPos.x, this.screenPos.y);\r\n\r\n        if (gameState.showPriorities && this.priority > 0) {\r\n            ctx.font = `bold ${28 * scale}px 'Segoe UI Symbol', Arial`;\r\n            ctx.fillStyle = '#f1c40f'; \r\n            ctx.shadowColor = \"rgba(0,0,0,0.9)\";\r\n            ctx.shadowBlur = 4;\r\n            ctx.fillText(PRIORITY_SYMBOLS[this.priority-1], this.screenPos.x + r*0.8, this.screenPos.y - r*0.8);\r\n            ctx.shadowBlur = 0;\r\n        }\r\n    }\r\n}\r\n\r\n\/\/ --- HJ\u00c6LPEFUNKTIONER ---\r\nfunction lighten(color, percent) {\r\n    var num = parseInt(color.replace(\"#\",\"\"),16),\r\n    amt = Math.round(2.55 * percent),\r\n    R = (num >> 16) + amt,\r\n    B = ((num >> 8) & 0x00ff) + amt,\r\n    G = (num & 0x0000ff) + amt;\r\n    return \"#\" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (B<255?B<1?0:B:255)*0x100 + (G<255?G<1?0:G:255)).toString(16).slice(1);\r\n}\r\n\r\nfunction rotateX(pos, angle) {\r\n    let y = pos.y * Math.cos(angle) - pos.z * Math.sin(angle);\r\n    let z = pos.y * Math.sin(angle) + pos.z * Math.cos(angle);\r\n    return { x: pos.x, y: y, z: z };\r\n}\r\nfunction rotateY(pos, angle) {\r\n    let x = pos.x * Math.cos(angle) + pos.z * Math.sin(angle);\r\n    let z = -pos.x * Math.sin(angle) + pos.z * Math.cos(angle);\r\n    return { x: x, y: pos.y, z: z };\r\n}\r\n\r\n\/\/ --- MOLEKYLE KONSTRUKTION ---\r\nfunction createMolecule() {\r\n    atoms = [];\r\n    bonds = [];\r\n    \/\/ 0: Central Carbon\r\n    atoms.push(new Atom('C', 0, 0, 0, 0));\r\n\r\n    \/\/ Geometri for Tetraeder\r\n    const a = BOND_LENGTH * Math.sqrt(8\/9); \r\n    const b = BOND_LENGTH * Math.sqrt(1\/9); \r\n    \r\n    \/\/ 1: H (lavest prioritet)\r\n    atoms.push(new Atom('H', 0, 0, BOND_LENGTH, 1)); \r\n    \r\n    \/\/ Positioner for de tre andre (foran)\r\n    let sub2Pos = { x: a, y: 0, z: -b };\r\n    let sub3Pos = { x: -a\/2, y: a*Math.sqrt(3)\/2, z: -b };\r\n    \r\n    \/\/ VIGTIGT: For at skifte R\/S bytter vi to grupper\r\n    if (!gameState.isRConfiguration) {\r\n        [sub2Pos, sub3Pos] = [sub3Pos, sub2Pos];\r\n    }\r\n\r\n    atoms.push(new Atom('Br', sub2Pos.x, sub2Pos.y, sub2Pos.z, 2));\r\n    atoms.push(new Atom('Cl', sub3Pos.x, sub3Pos.y, sub3Pos.z, 3));\r\n    atoms.push(new Atom('F', -a\/2, -a*Math.sqrt(3)\/2, -b, 4));\r\n\r\n    for (let i = 1; i < atoms.length; i++) {\r\n        bonds.push({ from: 0, to: i });\r\n    }\r\n\r\n    assignPriorities();\r\n    updateStatusText();\r\n}\r\n\r\nfunction assignPriorities() {\r\n    let substituents = atoms.filter(a => a.id !== 0);\r\n    substituents.sort((a, b) => b.data.z - a.data.z);\r\n    substituents.forEach((atom, index) => {\r\n        atom.priority = index + 1;\r\n    });\r\n}\r\n\r\nfunction determineCurrentConfig() {\r\n    let hAtom = atoms.find(a => a.priority === 4);\r\n    let p1 = atoms.find(a => a.priority === 1);\r\n    let p2 = atoms.find(a => a.priority === 2);\r\n    let p3 = atoms.find(a => a.priority === 3);\r\n\r\n    if (hAtom.pos.z > 20 && gameState.isAutoOriented) {\r\n        let v1x = p2.screenPos.x - p1.screenPos.x;\r\n        let v1y = p2.screenPos.y - p1.screenPos.y;\r\n        let v2x = p3.screenPos.x - p2.screenPos.x;\r\n        let v2y = p3.screenPos.y - p2.screenPos.y;\r\n\r\n        let crossZ = v1x * v2y - v1y * v2x;\r\n        return crossZ > 0 ? 'R (Med Uret)' : 'S (Mod Uret)';\r\n    }\r\n    return \"Orienter H bagud...\";\r\n}\r\n\r\n\/\/ --- RENDERING ---\r\nfunction init() {\r\n    window.addEventListener('resize', resizeCanvas);\r\n    resizeCanvas();\r\n    setupControls();\r\n    createMolecule();\r\n    requestAnimationFrame(animate);\r\n}\r\n\r\nfunction resizeCanvas() {\r\n    width = canvas.width = canvas.offsetWidth;\r\n    height = canvas.height = canvas.offsetHeight;\r\n    focalLength = Math.min(width, height) * 0.9;\r\n}\r\n\r\nfunction updatePhysics() {\r\n    if (gameState.animating && gameState.targetRotation) {\r\n        let dx = gameState.targetRotation.x - gameState.rotation.x;\r\n        let dy = gameState.targetRotation.y - gameState.rotation.y;\r\n        \r\n        gameState.rotation.x += dx * 0.1;\r\n        gameState.rotation.y += dy * 0.1;\r\n\r\n        if (Math.abs(dx) < 0.005 && Math.abs(dy) < 0.005) {\r\n            gameState.rotation.x = gameState.targetRotation.x;\r\n            gameState.rotation.y = gameState.targetRotation.y;\r\n            gameState.animating = false;\r\n            gameState.isAutoOriented = true;\r\n            updateStatusText();\r\n        }\r\n    }\r\n\r\n    atoms.forEach(atom => {\r\n        let pos = rotateY(atom.origPos, gameState.rotation.y);\r\n        pos = rotateX(pos, gameState.rotation.x);\r\n        atom.pos = pos;\r\n    });\r\n}\r\n\r\n\/\/ V5 NY FUNKTION: Tegner stregen, men stopper VED kanten af atomerne\r\nfunction drawSingleBond(bond) {\r\n    let a1 = atoms[bond.from];\r\n    let a2 = atoms[bond.to];\r\n    \r\n    let avgZ = (a1.pos.z + a2.pos.z) \/ 2;\r\n    let scale = focalLength \/ (focalLength + avgZ);\r\n    \r\n    \/\/ MEGET tyndere streger (v5 \u00e6ndring)\r\n    let lineWidth = 6 * scale; \r\n\r\n    \/\/ Beregn retningsvektor mellem de to atomer p\u00e5 sk\u00e6rmen\r\n    let dx = a2.screenPos.x - a1.screenPos.x;\r\n    let dy = a2.screenPos.y - a1.screenPos.y;\r\n    let dist = Math.sqrt(dx*dx + dy*dy);\r\n\r\n    if (dist < 1) return; \/\/ Undg\u00e5 division med 0\r\n\r\n    \/\/ Normaliser vektor\r\n    let nx = dx \/ dist;\r\n    let ny = dy \/ dist;\r\n\r\n    \/\/ Hent radius for atomerne (skaleret)\r\n    let r1 = a1.data.radius * a1.screenPos.scale;\r\n    let r2 = a2.data.radius * a2.screenPos.scale;\r\n\r\n    \/\/ Start og slut punkter justeret s\u00e5 de starter ved atomets kant\r\n    \/\/ Vi tr\u00e6kker lidt fra radius (0.8) for at sikre de \"r\u00f8rer\" ved visuel overlap\r\n    let startX = a1.screenPos.x + nx * (r1 * 0.9);\r\n    let startY = a1.screenPos.y + ny * (r1 * 0.9);\r\n    let endX = a2.screenPos.x - nx * (r2 * 0.9);\r\n    let endY = a2.screenPos.y - ny * (r2 * 0.9);\r\n\r\n    ctx.beginPath();\r\n    ctx.moveTo(startX, startY);\r\n    ctx.lineTo(endX, endY);\r\n    \r\n    let shade = Math.floor(60 * scale); \r\n    shade = Math.max(30, Math.min(100, shade)); \r\n    \r\n    ctx.strokeStyle = `rgb(${shade},${shade},${shade})`; \/\/ M\u00f8rkegr\u00e5\r\n    ctx.lineWidth = lineWidth;\r\n    ctx.lineCap = 'round';\r\n    ctx.stroke();\r\n}\r\n\r\nfunction drawRSArc() {\r\n    if (!gameState.isAutoOriented) return;\r\n\r\n    let p1 = atoms.find(a => a.priority === 1);\r\n    let p2 = atoms.find(a => a.priority === 2);\r\n    let p3 = atoms.find(a => a.priority === 3);\r\n    let center = atoms[0];\r\n\r\n    if (!p1 || !p2 || !p3) return;\r\n\r\n    ctx.save();\r\n    let configStr = determineCurrentConfig();\r\n    let isR = configStr.startsWith('R');\r\n    let color = isR ? '#2ecc71' : '#3498db';\r\n\r\n    \/\/ Pil stil\r\n    ctx.strokeStyle = color;\r\n    ctx.fillStyle = color;\r\n    ctx.lineWidth = 8;\r\n    ctx.setLineDash([20, 10]);\r\n\r\n    \/\/ Bue fra 1 -> 2 -> 3\r\n    ctx.beginPath();\r\n    ctx.moveTo(p1.screenPos.x, p1.screenPos.y);\r\n    let ctrlX = p2.screenPos.x + (p2.screenPos.x - center.screenPos.x)*0.6;\r\n    let ctrlY = p2.screenPos.y + (p2.screenPos.y - center.screenPos.y)*0.6;\r\n    ctx.quadraticCurveTo(ctrlX, ctrlY, p3.screenPos.x, p3.screenPos.y);\r\n    ctx.stroke();\r\n\r\n    \/\/ Pilspids ved 3\r\n    let angle = Math.atan2(p3.screenPos.y - ctrlY, p3.screenPos.x - ctrlX);\r\n    let headlen = 25;\r\n    ctx.beginPath();\r\n    ctx.setLineDash([]);\r\n    ctx.moveTo(p3.screenPos.x, p3.screenPos.y);\r\n    ctx.lineTo(p3.screenPos.x - headlen * Math.cos(angle - Math.PI \/ 6), p3.screenPos.y - headlen * Math.sin(angle - Math.PI \/ 6));\r\n    ctx.lineTo(p3.screenPos.x - headlen * Math.cos(angle + Math.PI \/ 6), p3.screenPos.y - headlen * Math.sin(angle + Math.PI \/ 6));\r\n    ctx.fill();\r\n    \r\n    \/\/ Tekst R\/S\r\n    ctx.font = 'bold 100px Arial';\r\n    ctx.textAlign = 'center';\r\n    ctx.globalAlpha = 0.9;\r\n    ctx.shadowColor = \"rgba(0,0,0,0.6)\";\r\n    ctx.shadowBlur = 15;\r\n    ctx.fillText(isR ? 'R' : 'S', center.screenPos.x, center.screenPos.y + 15);\r\n    \r\n    ctx.restore();\r\n}\r\n\r\nfunction render() {\r\n    ctx.clearRect(0, 0, width, height);\r\n    \r\n    atoms.forEach(atom => atom.project());\r\n    \r\n    let renderList = [];\r\n\r\n    atoms.forEach(atom => {\r\n        renderList.push({\r\n            type: 'atom',\r\n            z: atom.pos.z, \r\n            obj: atom\r\n        });\r\n    });\r\n\r\n    bonds.forEach(bond => {\r\n        let a1 = atoms[bond.from];\r\n        let a2 = atoms[bond.to];\r\n        let midZ = (a1.pos.z + a2.pos.z) \/ 2;\r\n        \r\n        renderList.push({\r\n            type: 'bond',\r\n            z: midZ, \r\n            obj: bond\r\n        });\r\n    });\r\n\r\n    \/\/ Sorter: L\u00e6ngst v\u00e6k f\u00f8rst\r\n    renderList.sort((a, b) => b.z - a.z);\r\n\r\n    renderList.forEach(item => {\r\n        if (item.type === 'atom') {\r\n            item.obj.draw();\r\n        } else {\r\n            drawSingleBond(item.obj);\r\n        }\r\n    });\r\n\r\n    drawRSArc();\r\n}\r\n\r\nfunction animate() {\r\n    updatePhysics();\r\n    render();\r\n    requestAnimationFrame(animate);\r\n}\r\n\r\n\/\/ --- INTERAKTION ---\r\nfunction setupControls() {\r\n    const handleStart = (x, y) => {\r\n        mouse.down = true;\r\n        mouse.lastX = x;\r\n        mouse.lastY = y;\r\n        gameState.isAutoOriented = false;\r\n        updateStatusText();\r\n    };\r\n    \r\n    const handleMove = (x, y) => {\r\n        if (!mouse.down) return;\r\n        let deltaX = x - mouse.lastX;\r\n        let deltaY = y - mouse.lastY;\r\n        gameState.rotation.y += deltaX * 0.005;\r\n        gameState.rotation.x += deltaY * 0.005;\r\n        mouse.lastX = x;\r\n        mouse.lastY = y;\r\n    };\r\n\r\n    canvas.addEventListener('mousedown', e => handleStart(e.clientX, e.clientY));\r\n    window.addEventListener('mouseup', () => mouse.down = false);\r\n    window.addEventListener('mousemove', e => handleMove(e.clientX, e.clientY));\r\n\r\n    canvas.addEventListener('touchstart', e => {\r\n        handleStart(e.touches[0].clientX, e.touches[0].clientY);\r\n        e.preventDefault();\r\n    }, {passive: false});\r\n    window.addEventListener('touchend', () => mouse.down = false);\r\n    window.addEventListener('touchmove', e => {\r\n        handleMove(e.touches[0].clientX, e.touches[0].clientY);\r\n        e.preventDefault();\r\n    }, {passive: false});\r\n\r\n    document.getElementById('showPriorities').addEventListener('change', (e) => {\r\n        gameState.showPriorities = e.target.checked;\r\n    });\r\n\r\n    document.getElementById('resetBtn').addEventListener('click', () => {\r\n        gameState.rotation = { x: 0.3, y: 0.3, z: 0 };\r\n        gameState.isAutoOriented = false;\r\n        gameState.animating = false;\r\n        updateStatusText();\r\n    });\r\n\r\n    document.getElementById('switchEnantiomerBtn').addEventListener('click', () => {\r\n        gameState.isRConfiguration = !gameState.isRConfiguration;\r\n        createMolecule(); \r\n        gameState.isAutoOriented = false;\r\n        updateStatusText();\r\n        const btn = document.getElementById('switchEnantiomerBtn');\r\n        btn.textContent = gameState.isRConfiguration ? \"\u2194 Skift til S\" : \"\u2194 Skift til R\";\r\n    });\r\n\r\n    document.getElementById('autoOrientBtn').addEventListener('click', () => {\r\n        gameState.targetRotation = { x: 0, y: 0, z: 0 }; \r\n        gameState.animating = true;\r\n    });\r\n}\r\n\r\nfunction updateStatusText() {\r\n    const configStateDiv = document.getElementById('config-state');\r\n    const molNameDiv = document.getElementById('molecule-name');\r\n    \r\n    let prefix = gameState.isRConfiguration ? '(R)-' : '(S)-';\r\n    molNameDiv.textContent = prefix + 'Bromchlorfluormethan';\r\n\r\n    if (gameState.isAutoOriented) {\r\n        configStateDiv.textContent = determineCurrentConfig();\r\n        configStateDiv.style.color = gameState.isRConfiguration ? '#2ecc71' : '#3498db';\r\n    } else {\r\n        configStateDiv.textContent = \"Drej molekylet s\u00e5 H peger bagud\";\r\n        configStateDiv.style.color = '#f1c40f';\r\n    }\r\n}\r\n\r\ninit();\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-6f3c3f9e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6f3c3f9e\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5146b445\" data-id=\"5146b445\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1ca9b851 elementor-widget elementor-widget-heading\" data-id=\"1ca9b851\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Animationer til M\u00e6ngdeberegning C<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-73d373ff elementor-widget__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"73d373ff\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Nedenfor findes f\u00f8lgende animationer. Brug linksene i overskriften<\/p><p>1) <a href=\"#anchor1\" rel=\"noopener\">Afrunding, betydende cifre og decimaler<\/a><br \/>L\u00e6r at afrunde korrekt i dit endelige facit<\/p><p>2)\u00a0<a href=\"#anchor2\" rel=\"noopener\">Stofm\u00e6ngde og masse.<\/a><br \/>L\u00e6r forskellen p\u00e5 at\u00a0<\/p><p>3)\u00a0<a href=\"#anchor3\" rel=\"noopener\">Syntese-spillet<\/a><br \/>Brug din viden om organisk syntese til\u00a0at lave en forretning ud af det.<\/p><p>4)\u00a0<a href=\"#anchor4\">Geometrisk Isomeri &#8211; animation og spil<\/a><br \/>Brug animationen til at forst\u00e5 E\/Z-isomeri &#8211; og tr\u00e6n din forst\u00e5else med et spil.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1e87cc52 elementor-widget elementor-widget-spacer\" data-id=\"1e87cc52\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5cc294af elementor-widget elementor-widget-menu-anchor\" data-id=\"5cc294af\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor1\"><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-614965ac elementor-widget elementor-widget-html\" data-id=\"614965ac\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe \r\n    src=\"https:\/\/kemiformler.dk\/animationer\/intermolekyl%C3%A6rt_ethanol.html\" \r\n    width=\"100%\" \r\n    height=\"900px\" \r\n    frameborder=\"0\" \r\n    style=\"border: none; overflow: hidden; min-height: 900px;\" \r\n><\/iframe>\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-6b5aaed3 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6b5aaed3\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5652282d\" data-id=\"5652282d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-138d5704 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"138d5704\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\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-ab58d12 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ab58d12\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-71446a3a\" data-id=\"71446a3a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-1fbc7a0 elementor-widget elementor-widget-menu-anchor\" data-id=\"1fbc7a0\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor2\"><\/div>\n\t\t\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-77498fb7 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"77498fb7\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-321b9d23\" data-id=\"321b9d23\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2c5ae63f elementor-widget elementor-widget-html\" data-id=\"2c5ae63f\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe \n    src=\"https:\/\/kemiformler.dk\/animationer\/estersyntese.html\" \n    width=\"100%\" \n    height=\"900px\" \n    frameborder=\"0\" \n    style=\"border: none; overflow: hidden; min-height: 900px;\" \n><\/iframe>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7862af75 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"7862af75\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-28efb7e9 elementor-widget elementor-widget-menu-anchor\" data-id=\"28efb7e9\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor3\"><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2f132c44 elementor-widget elementor-widget-html\" data-id=\"2f132c44\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe \n    src=\"https:\/\/kemiformler.dk\/animationer\/kemikalieindk\u00f8b_kemiB.html\" \n    width=\"100%\" \n    height=\"900px\" \n    frameborder=\"0\" \n    style=\"border: none; overflow: hidden; min-height: 900px;\" \n><\/iframe>\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-643d2d71 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"643d2d71\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-62ca6cce\" data-id=\"62ca6cce\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7ae82586 elementor-widget elementor-widget-menu-anchor\" data-id=\"7ae82586\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor4\"><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7c80dec1 elementor-widget elementor-widget-html\" data-id=\"7c80dec1\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe \n    src=\"https:\/\/kemiformler.dk\/animationer\/geometrisk_isomeri.html\" \n    width=\"100%\" \n    height=\"900px\" \n    frameborder=\"0\" \n    style=\"border: none; overflow: hidden; min-height: 900px;\" \n><\/iframe>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-13de0827 elementor-widget elementor-widget-menu-anchor\" data-id=\"13de0827\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor5\"><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-60c80321 elementor-widget elementor-widget-menu-anchor\" data-id=\"60c80321\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor6\"><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6779acb0 elementor-widget elementor-widget-menu-anchor\" data-id=\"6779acb0\" data-element_type=\"widget\" data-widget_type=\"menu-anchor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-menu-anchor\" id=\"anchor7\"><\/div>\n\t\t\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-320449e elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"320449e\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-869b05e\" data-id=\"869b05e\" data-element_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>Kemi-Animation: R\/S Isomeri (Ball &#038; Stick V5) Bromchlorfluormethan Konfiguration: Ukendt C Br (1) Cl (2) F (3) H (4) Vis Tal (CIP) \u2194 Skift Enantiomer \ud83d\udc41\ufe0f Auto-Orienter (Vis R\/S) \u21ba Animationer til M\u00e6ngdeberegning C Nedenfor findes f\u00f8lgende animationer. Brug linksene i overskriften 1) Afrunding, betydende cifre og decimalerL\u00e6r at afrunde korrekt i dit endelige facit&hellip;&nbsp;<a href=\"https:\/\/kemiformler.dk\/index.php\/maengdeberegning\/\" class=\"\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">M\u00e6ngdeberegning<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"class_list":["post-2318","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/pages\/2318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/comments?post=2318"}],"version-history":[{"count":8,"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/pages\/2318\/revisions"}],"predecessor-version":[{"id":2334,"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/pages\/2318\/revisions\/2334"}],"wp:attachment":[{"href":"https:\/\/kemiformler.dk\/index.php\/wp-json\/wp\/v2\/media?parent=2318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}