电子排布图

作者

松原苏打

代码
import json
from mendeleev import element
from IPython.display import display, HTML
代码
%%time
# 生成元素数据字典
ELEMENT_DATA = {}
for i in range(1, 119):
    el = element(i)
    ELEMENT_DATA[i] = {"symbol": el.symbol, "conf": str(el.ec)}
js_data = json.dumps(ELEMENT_DATA)
CPU times: total: 26.6 s
Wall time: 28.1 s
代码
HTML(f'''
<script>
    window.ELEMENT_DATA = {js_data};
</script>
''')

请输入原子序数

代码
html_symbol = f'''
<div style="display: flex; gap: 12px; flex-direction: column;">
    <div>
        <label for="atomicNumber">
            输入原子序数:
        </label>
        <input 
            type="number" 
            id="atomicNumber" 
            min="1" 
            max="118" 
            value="1" 
        />
        <button type="button" id="decrementBtn" style="width: 64px;">-</button>
        <button type="button" id="incrementBtn" style="width: 64px;">+</button>
        <script>
            (function() {{
                var input = document.getElementById('atomicNumber');
                var decrementBtn = document.getElementById('decrementBtn');
                var incrementBtn = document.getElementById('incrementBtn');
                decrementBtn.addEventListener('click', function() {{
                    var val = parseInt(input.value, 10) || 1;
                    if (val > 1) {{
                        input.value = val - 1;
                        input.dispatchEvent(new Event('input'));
                    }}
                }});
                incrementBtn.addEventListener('click', function() {{
                    var val = parseInt(input.value, 10) || 1;
                    if (val < 118) {{
                        input.value = val + 1;
                        input.dispatchEvent(new Event('input'));
                    }}
                }});
            }})();
        </script>
    </div>
    <div id="output">
        元素符号为: H, 电子排布为: 1s1
    </div>
    
    <script>
    (() => {{
        const input = document.getElementById('atomicNumber');
        const output = document.getElementById('output');

        function updateOutput() {{
            const atomicNumber = parseInt(input.value);
            const data = ELEMENT_DATA[atomicNumber];
            const symbol = data ? data.symbol : '无效序数';
            const conf = data ? data.conf : '无效序数';
            output.textContent = `元素符号为: ${{symbol}}, 电子排布为: ${{conf}}`;
        }}

        input.addEventListener('input', updateOutput);
    }})();
    </script>
</div>
'''

HTML(html_symbol)
元素符号为: H, 电子排布为: 1s1
代码
html_conf = r'''
<div class="container">
    <div class="grid">
        <!-- 1 到 400 自动生成 -->
        <script>
            const grid = document.currentScript.parentElement;
            for (let i = 1; i <= 380; i++) {
                const div = document.createElement('div');
                div.id = String(i);
                const p = document.createElement('p');
                p.textContent = "";
                div.appendChild(p);
                grid.appendChild(div);
            }
        </script>
    </div>
</div>

<style>
    .container {
        width: 100%;
        height: 100%;
    }

    .grid {
        display: grid;
        row-gap: 4px;
        column-gap: 0px;
        grid-template-columns: 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px 32px;
    }

    .grid>div {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 32px;
        width: 32px;
    }

    .grid>div>p {
        margin: 0;
        padding: 0;
    }
</style>

<script>
    const aufbauPrinciple = Object.freeze(['1s', '2s', '2p', '3s', '3p', '4s', '3d', '4p', '5s', '4d', '5p', '6s', '4f', '5d', '6p', '7s', '5f', '6d', '7p']);
    const aufbauMap = {
        "1s": 361,
        "2s": 341,
        "2p": 323,
        "3s": 301,
        "3p": 283,
        "4s": 261,
        "3d": 247,
        "4p": 223,
        "5s": 201,
        "4d": 187,
        "5p": 163,
        "6s": 141,
        "4f": 133,
        "5d": 107,
        "6p": 83,
        "7s": 61,
        "5f": 53,
        "6d": 27,
        "7p": 3,
    };
    const hundsRule = {
        "s1": ["↿"],
        "s2": ["⥮"],
        "p1": ["↿", "", ""],
        "p2": ["↿", "↿", ""],
        "p3": ["↿", "↿", "↿"],
        "p4": ["⥮", "↿", "↿"],
        "p5": ["⥮", "⥮", "↿"],
        "p6": ["⥮", "⥮", "⥮"],
        "d1": ["↿", "", "", "", ""],
        "d2": ["↿", "↿", "", "", ""],
        "d3": ["↿", "↿", "↿", "", ""],
        "d4": ["↿", "↿", "↿", "↿", ""],
        "d5": ["↿", "↿", "↿", "↿", "↿"],
        "d6": ["⥮", "↿", "↿", "↿", "↿"],
        "d7": ["⥮", "⥮", "↿", "↿", "↿"],
        "d8": ["⥮", "⥮", "⥮", "↿", "↿"],
        "d9": ["⥮", "⥮", "⥮", "⥮", "↿"],
        "d10": ["⥮", "⥮", "⥮", "⥮", "⥮"],
        "f1": ["↿", "", "", "", "", "", ""],
        "f2": ["↿", "↿", "", "", "", "", ""],
        "f3": ["↿", "↿", "↿", "", "", "", ""],
        "f4": ["↿", "↿", "↿", "↿", "", "", ""],
        "f5": ["↿", "↿", "↿", "↿", "↿", "", ""],
        "f6": ["↿", "↿", "↿", "↿", "↿", "↿", ""],
        "f7": ["↿", "↿", "↿", "↿", "↿", "↿", "↿"],
        "f8": ["⥮", "↿", "↿", "↿", "↿", "↿", "↿"],
        "f9": ["⥮", "⥮", "↿", "↿", "↿", "↿", "↿"],
        "f10": ["⥮", "⥮", "⥮", "↿", "↿", "↿", "↿"],
        "f11": ["⥮", "⥮", "⥮", "⥮", "↿", "↿", "↿"],
        "f12": ["⥮", "⥮", "⥮", "⥮", "⥮", "↿", "↿"],
        "f13": ["⥮", "⥮", "⥮", "⥮", "⥮", "⥮", "↿"],
        "f14": ["⥮", "⥮", "⥮", "⥮", "⥮", "⥮", "⥮"],
    };

    // 清空所有 div 的 border 样式和 p 的内容
    function resetGrid() {
        for (let i = 1; i <= 380; i++) {
            const cell = document.getElementById(String(i));
            cell.style.border = '';  // 一次性清空所有 border
            const p = cell.querySelector('p');
            p.textContent = '';
            p.style.fontSize = '24px';
        }
    }

    // 填充表格
    function fillGrid(atomicNumber) {
        const conf = ELEMENT_DATA[atomicNumber].conf;
        const orbitals = conf.split(' ');

        // 调试信息
        // console.log(conf);
        // console.log(orbitals);

        orbitals.forEach(nlm => {
            const match = nlm.match(/(\d+)([spdf])(\d+)/);

            const n = match[1]; // 主量子数
            const lType = match[2]; // 轨道类型 (s, p, d, f)
            const electronCount = match[3]; //电子数

            const aufbauValue = aufbauMap[n + lType];
            const hundsValue = hundsRule[lType + electronCount];

            // 调试信息
            // console.log(aufbauValue);
            // console.log(hundsValue);

            // 设置轨道标签
            const labelCell = document.getElementById(aufbauValue);
            labelCell.querySelector('p').textContent = n + lType;
            labelCell.style.borderTop = '1px solid transparent';
            labelCell.style.borderRight = '1px solid #000';
            labelCell.style.borderBottom = '1px solid transparent';
            labelCell.style.borderLeft = '1px solid transparent';

            // 设置电子符号
            for (let i = 0; i < hundsValue.length; i++) {
                const cell = document.getElementById(aufbauValue + 1 + i);
                cell.querySelector('p').textContent = hundsValue[i];
                cell.querySelector('p').style.fontSize = '32px';
                cell.style.borderTop = '1px solid #000';
                cell.style.borderRight = '1px solid #000';
                cell.style.borderBottom = '1px solid #000';
                cell.style.borderLeft = '1px solid transparent';
            }
        });
    }

    // resetGrid();
    // fillGrid(118);

    // 添加事件监听器
    const input = document.getElementById('atomicNumber');

    function updateGrid() {
        const atomicNumber = parseInt(input.value);
        resetGrid();
        fillGrid(atomicNumber);
    }
    
    input.addEventListener('input', updateGrid);

    updateGrid();
</script>
'''

HTML(html_conf)

Aufbau Principle

Aufbau_Principle-lab.learnbin.net

Aufbau_Principle-lab.learnbin.net