分页: 17 / 17

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 16:56
ejsoon
大功告成?

當前代碼:
ejtileanimate202511131655.7z
(23.62 KiB) 已下载 1 次

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 18:53
ejsoon
出現bug:當repeat/freeze切換時,set會壞掉。
ejtileAnimationsvg_20251113_185045.7z
(974 Bytes) 尚未被下载

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 19:09
ejsoon
做一個js+html頁面,計算兩條直線的交點坐標。每條直線由所經過的兩個點的坐標定義,或者由y=ax+b的a和b定義。

結果默認保留三位小數,可自定義保留n位小數。

代码: 全选

<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>兩直線交點計算器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 30px auto;
            padding: 20px;
            background-color: #f9f9f9;
            line-height: 1.6;
        }
        h1 {
            text-align: center;
            color: #333;
        }
        .container {
            background: white;
            padding: 25px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        .input-mode {
            text-align: center;
            margin-bottom: 20px;
        }
        .input-mode button {
            padding: 8px 16px;
            margin: 0 5px;
            cursor: pointer;
        }
        .input-mode button.active {
            background-color: #007bff;
            color: white;
        }
        .line-input {
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 8px;
            display: none;
        }
        .line-input.active {
            display: block;
        }
        .line-title {
            font-weight: bold;
            margin-bottom: 10px;
            color: #555;
            font-size: 1.1em;
        }
        .point-input {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
            align-items: center;
        }
        .point-input label {
            width: 30px;
        }
        .point-input input {
            width: 80px;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .param-input {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
            align-items: center;
        }
        .param-input label {
            width: 20px;
        }
        .param-input input {
            width: 80px;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .controls {
            text-align: center;
            margin: 20px 0;
        }
        button.calculate {
            background-color: #28a745;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 1em;
        }
        button.calculate:hover {
            background-color: #218838;
        }
        .decimal-control {
            margin: 15px 0;
            text-align: center;
        }
        .decimal-control input {
            width: 60px;
            padding: 5px;
            text-align: center;
        }
        .result {
            margin-top: 20px;
            padding: 15px;
            background-color: #e9f7ef;
            border-radius: 8px;
            text-align: center;
            font-size: 1.2em;
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .error {
            background-color: #f8d7da;
            color: #721c24;
        }
        .footer {
            text-align: center;
            margin-top: 30px;
            color: #666;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>兩直線交點計算器</h1>
        
        <div class="input-mode">
            <button id="mode-points" class="active">兩點定義</button>
            <button id="mode-params">參數方程 (y = ax + b)</button>
        </div>

        <!-- 兩點定義模式 -->
        <div id="input-points" class="line-input active">
            <div class="line-title">直線 1:經過兩點</div>
            <div class="point-input">
                <label>P1:</label>
                <input type="number" step="any" id="p1x1" placeholder="x" value="-2">
                <span>,</span>
                <input type="number" step="any" id="p1y1" placeholder="y" value="3">
            </div>
            <div class="point-input">
                <label>P2:</label>
                <input type="number" step="any" id="p1x2" placeholder="x" value="4">
                <span>,</span>
                <input type="number" step="any" id="p1y2" placeholder="y" value="-1">
            </div>

            <div class="line-title" style="margin-top: 20px;">直線 2:經過兩點</div>
            <div class="point-input">
                <label>P3:</label>
                <input type="number" step="any" id="p2x1" placeholder="x" value="-1">
                <span>,</span>
                <input type="number" step="any" id="p2y1" placeholder="y" value="5">
            </div>
            <div class="point-input">
                <label>P4:</label>
                <input type="number" step="any" id="p2x2" placeholder="x" value="3">
                <span>,</span>
                <input type="number" step="any" id="p2y2" placeholder="y" value="1">
            </div>
        </div>

        <!-- 參數方程模式 -->
        <div id="input-params" class="line-input">
            <div class="line-title">直線 1:y = ax + b</div>
            <div class="param-input">
                <label>a:</label>
                <input type="number" step="any" id="a1" placeholder="斜率" value="1">
                <span style="margin-left: 10px;">b:</span>
                <input type="number" step="any" id="b1" placeholder="截距" value="1">
            </div>

            <div class="line-title" style="margin-top: 20px;">直線 2:y = ax + b</div>
            <div class="param-input">
                <label>a:</label>
                <input type="number" step="any" id="a2" placeholder="斜率" value="-1">
                <span style="margin-left: 10px;">b:</span>
                <input type="number" step="any" id="b2" placeholder="截距" value="3">
            </div>
        </div>

        <div class="decimal-control">
            <label>小數位數:</label>
            <input type="number" id="decimal-places" min="0" max="10" value="3">
        </div>

        <div class="controls">
            <button class="calculate" onclick="calculateIntersection()">計算交點</button>
        </div>

        <div id="result" class="result">
            請輸入直線參數並點擊「計算交點」
        </div>
    </div>

    <div class="footer">
        支持兩種輸入方式:兩點定義或 y = ax + b 形式<br>
        結果預設保留 3 位小數,可自定義 0~10 位
    </div>

    <script>
        // 切換輸入模式
        document.getElementById('mode-points').addEventListener('click', function() {
            document.getElementById('input-points').classList.add('active');
            document.getElementById('input-params').classList.remove('active');
            this.classList.add('active');
            document.getElementById('mode-params').classList.remove('active');
        });

        document.getElementById('mode-params').addEventListener('click', function() {
            document.getElementById('input-params').classList.add('active');
            document.getElementById('input-points').classList.remove('active');
            this.classList.add('active');
            document.getElementById('mode-points').classList.remove('active');
        });

        // 計算交點
        function calculateIntersection() {
            const resultDiv = document.getElementById('result');
            resultDiv.className = 'result';
            
            try {
                let x, y;
                const decimals = parseInt(document.getElementById('decimal-places').value) || 3;
                if (decimals < 0 || decimals > 10) throw new Error("小數位數請輸入 0~10");

                const isPointsMode = document.getElementById('input-points').classList.contains('active');
                
                if (isPointsMode) {
                    // 兩點定義模式
                    const p1 = {
                        x1: parseFloat(document.getElementById('p1x1').value),
                        y1: parseFloat(document.getElementById('p1y1').value),
                        x2: parseFloat(document.getElementById('p1x2').value),
                        y2: parseFloat(document.getElementById('p1y2').value)
                    };
                    const p2 = {
                        x1: parseFloat(document.getElementById('p2x1').value),
                        y1: parseFloat(document.getElementById('p2y1').value),
                        x2: parseFloat(document.getElementById('p2x2').value),
                        y2: parseFloat(document.getElementById('p2y2').value)
                    };

                    // 檢查點是否重合
                    if (isNaN(p1.x1) || isNaN(p1.y1) || isNaN(p1.x2) || isNaN(p1.y2) ||
                        isNaN(p2.x1) || isNaN(p2.y1) || isNaN(p2.x2) || isNaN(p2.y2)) {
                        throw new Error("請輸入完整的坐標值");
                    }

                    if (p1.x1 === p1.x2 && p1.y1 === p1.y2) {
                        throw new Error("直線1的兩個點相同,無法定義直線");
                    }
                    if (p2.x1 === p2.x2 && p2.y1 === p2.y2) {
                        throw new Error("直線2的兩個點相同,無法定義直線");
                    }

                    // 計算兩直線的參數 a, b
                    const a1 = (p1.y2 - p1.y1) / (p1.x2 - p1.x1);
                    const b1 = p1.y1 - a1 * p1.x1;
                    const a2 = (p2.y2 - p2.y1) / (p2.x2 - p2.x1);
                    const b2 = p2.y1 - a2 * p2.x1;

                    // 檢查是否平行
                    if (Math.abs(a1 - a2) < 1e-10) {
                        if (Math.abs(b1 - b2) < 1e-10) {
                            throw new Error("兩直線重合(無限多交點)");
                        } else {
                            throw new Error("兩直線平行(無交點)");
                        }
                    }

                    // 計算交點
                    x = (b2 - b1) / (a1 - a2);
                    y = a1 * x + b1;

                } else {
                    // 參數方程模式
                    const a1 = parseFloat(document.getElementById('a1').value);
                    const b1 = parseFloat(document.getElementById('b1').value);
                    const a2 = parseFloat(document.getElementById('a2').value);
                    const b2 = parseFloat(document.getElementById('b2').value);

                    if (isNaN(a1) || isNaN(b1) || isNaN(a2) || isNaN(b2)) {
                        throw new Error("請輸入完整的參數值");
                    }

                    // 檢查是否平行
                    if (Math.abs(a1 - a2) < 1e-10) {
                        if (Math.abs(b1 - b2) < 1e-10) {
                            throw new Error("兩直線重合(無限多交點)");
                        } else {
                            throw new Error("兩直線平行(無交點)");
                        }
                    }

                    // 計算交點
                    x = (b2 - b1) / (a1 - a2);
                    y = a1 * x + b1;
                }

                // 格式化結果
                const format = (num) => Number(num.toFixed(decimals));
                resultDiv.innerHTML = `<strong>交點坐標:(${format(x)}, ${format(y)})</strong>`;
                
            } catch (error) {
                resultDiv.className = 'result error';
                resultDiv.textContent = '錯誤:' + error.message;
            }
        }

        // 按 Enter 鍵也觸發計算
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Enter') {
                calculateIntersection();
            }
        });
    </script>
</body>
</html>

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 19:19
ejsoon
兩直線交點計算器(進階版)

代码: 全选

<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>兩直線交點計算器(進階版)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 30px auto;
            padding: 20px;
            background-color: #f9f9f9;
            line-height: 1.6;
        }
        h1 {
            text-align: center;
            color: #333;
        }
        .container {
            background: white;
            padding: 25px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        .line-section {
            margin-bottom: 25px;
            padding: 18px;
            border: 1px solid #ddd;
            border-radius: 8px;
            background-color: #fdfdfd;
        }
        .line-title {
            font-weight: bold;
            margin-bottom: 12px;
            color: #444;
            font-size: 1.1em;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .mode-selector {
            display: flex;
            gap: 8px;
        }
        .mode-selector button {
            padding: 5px 10px;
            font-size: 0.9em;
            cursor: pointer;
            border: 1px solid #ccc;
            border-radius: 4px;
            background: #f0f0f0;
        }
        .mode-selector button.active {
            background-color: #007bff;
            color: white;
            border-color: #007bff;
        }
        .input-group {
            display: none;
            margin-top: 12px;
        }
        .input-group.active {
            display: block;
        }
        .point-input {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
        }
        .point-input label {
            display: flex;
            align-items: center;
            gap: 5px;
            min-width: 160px;
        }
        .point-input input {
            width: 140px;
            padding: 6px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-family: monospace;
        }
        .param-input {
            display: flex;
            gap: 15px;
            align-items: center;
            flex-wrap: wrap;
        }
        .param-input label {
            display: flex;
            align-items: center;
            gap: 5px;
            min-width: 80px;
        }
        .param-input input {
            width: 100px;
            padding: 6px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .decimal-control {
            margin: 20px 0;
            text-align: center;
        }
        .decimal-control input {
            width: 60px;
            padding: 5px;
            text-align: center;
        }
        .controls {
            text-align: center;
            margin: 25px 0;
        }
        button.calculate {
            background-color: #28a745;
            color: white;
            padding: 12px 28px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 1.1em;
            font-weight: bold;
        }
        button.calculate:hover {
            background-color: #218838;
        }
        .result {
            margin-top: 20px;
            padding: 18px;
            background-color: #e9f7ef;
            border-radius: 8px;
            text-align: center;
            font-size: 1.3em;
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }
        .error {
            background-color: #f8d7da;
            color: #721c24;
        }
        .footer {
            text-align: center;
            margin-top: 30px;
            color: #666;
            font-size: 0.9em;
        }
        .example {
            font-size: 0.85em;
            color: #666;
            font-style: italic;
            margin-top: 4px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>兩直線交點計算器(進階版)</h1>

        <!-- 直線 1 -->
        <div class="line-section">
            <div class="line-title">
                <span>直線 1</span>
                <div class="mode-selector">
                    <button class="active" data-line="1" data-mode="points">兩點定義</button>
                    <button data-line="1" data-mode="params">y = ax + b</button>
                </div>
            </div>
            <div id="line1-points" class="input-group active">
                <div class="point-input">
                    <label>
                        點1:<input type="text" id="l1p1" placeholder="x1,y1" value="-2,3">
                    </label>
                    <label>
                        點2:<input type="text" id="l1p2" placeholder="x2,y2" value="4,-1">
                    </label>
                </div>
                <div class="example">範例:-2,3 或 1.5,0</div>
            </div>
            <div id="line1-params" class="input-group">
                <div class="param-input">
                    <label>a:<input type="number" step="any" id="l1a" value="1"></label>
                    <label>b:<input type="number" step="any" id="l1b" value="1"></label>
                </div>
            </div>
        </div>

        <!-- 直線 2 -->
        <div class="line-section">
            <div class="line-title">
                <span>直線 2</span>
                <div class="mode-selector">
                    <button class="active" data-line="2" data-mode="points">兩點定義</button>
                    <button data-line="2" data-mode="params">y = ax + b</button>
                </div>
            </div>
            <div id="line2-points" class="input-group active">
                <div class="point-input">
                    <label>
                        點1:<input type="text" id="l2p1" placeholder="x1,y1" value="-1,5">
                    </label>
                    <label>
                        點2:<input type="text" id="l2p2" placeholder="x2,y2" value="3,1">
                    </label>
                </div>
                <div class="example">範例:0,0 或 2.5,-3</div>
            </div>
            <div id="line2-params" class="input-group">
                <div class="param-input">
                    <label>a:<input type="number" step="any" id="l2a" value="-1"></label>
                    <label>b:<input type="number" step="any" id="l2b" value="3"></label>
                </div>
            </div>
        </div>

        <div class="decimal-control">
            <label>小數位數:</label>
            <input type="number" id="decimal-places" min="0" max="10" value="3">
        </div>

        <div class="controls">
            <button class="calculate" onclick="calculateIntersection()">計算交點</button>
        </div>

        <div id="result" class="result">
            請輸入直線參數並點擊「計算交點」
        </div>
    </div>

    <div class="footer">
        每條直線可獨立選擇「兩點定義」或「y = ax + b」<br>
        兩點格式:x,y(逗號分隔)<br>
        結果保留 0~10 位小數,預設 3 位
    </div>

    <script>
        // 切換模式
        document.querySelectorAll('.mode-selector button').forEach(btn => {
            btn.addEventListener('click', function() {
                const line = this.dataset.line;
                const mode = this.dataset.mode;
                const selector = `.mode-selector button[data-line="${line}"]`;
                document.querySelectorAll(selector).forEach(b => b.classList.remove('active'));
                this.classList.add('active');

                document.getElementById(`line${line}-points`).classList.toggle('active', mode === 'points');
                document.getElementById(`line${line}-params`).classList.toggle('active', mode === 'params');
            });
        });

        // 解析 x,y 字串
        function parsePoint(str) {
            if (!str || !str.trim()) return null;
            const parts = str.trim().split(',');
            if (parts.length !== 2) return null;
            const x = parseFloat(parts[0]);
            const y = parseFloat(parts[1]);
            return (isNaN(x) || isNaN(y)) ? null : { x, y };
        }

        // 計算交點
        function calculateIntersection() {
            const resultDiv = document.getElementById('result');
            resultDiv.className = 'result';

            try {
                const decimals = Math.max(0, Math.min(10, parseInt(document.getElementById('decimal-places').value) || 3));

                let a1, b1, a2, b2;

                // 讀取直線 1
                const mode1 = document.querySelector(`.mode-selector button[data-line="1"].active`).dataset.mode;
                if (mode1 === 'points') {
                    const p1 = parsePoint(document.getElementById('l1p1').value);
                    const p2 = parsePoint(document.getElementById('l1p2').value);
                    if (!p1 || !p2) throw new Error("直線1:請輸入正確的兩點格式(x,y)");
                    if (p1.x === p2.x && p1.y === p2.y) throw new Error("直線1:兩點相同,無法定義直線");

                    const dx = p2.x - p1.x;
                    if (Math.abs(dx) < 1e-10) throw new Error("直線1:垂直線無法用 y=ax+b 表示");
                    a1 = (p2.y - p1.y) / dx;
                    b1 = p1.y - a1 * p1.x;
                } else {
                    a1 = parseFloat(document.getElementById('l1a').value);
                    b1 = parseFloat(document.getElementById('l1b').value);
                    if (isNaN(a1) || isNaN(b1)) throw new Error("直線1:請輸入完整的 a 和 b");
                }

                // 讀取直線 2
                const mode2 = document.querySelector(`.mode-selector button[data-line="2"].active`).dataset.mode;
                if (mode2 === 'points') {
                    const p1 = parsePoint(document.getElementById('l2p1').value);
                    const p2 = parsePoint(document.getElementById('l2p2').value);
                    if (!p1 || !p2) throw new Error("直線2:請輸入正確的兩點格式(x,y)");
                    if (p1.x === p2.x && p1.y === p2.y) throw new Error("直線2:兩點相同,無法定義直線");

                    const dx = p2.x - p1.x;
                    if (Math.abs(dx) < 1e-10) throw new Error("直線2:垂直線無法用 y=ax+b 表示");
                    a2 = (p2.y - p1.y) / dx;
                    b2 = p1.y - a2 * p1.x;
                } else {
                    a2 = parseFloat(document.getElementById('l2a').value);
                    b2 = parseFloat(document.getElementById('l2b').value);
                    if (isNaN(a2) || isNaN(b2)) throw new Error("直線2:請輸入完整的 a 和 b");
                }

                // 檢查平行或重合
                const slopeDiff = a1 - a2;
                if (Math.abs(slopeDiff) < 1e-10) {
                    if (Math.abs(b1 - b2) < 1e-10) {
                        throw new Error("兩直線重合(無限多交點)");
                    } else {
                        throw new Error("兩直線平行(無交點)");
                    }
                }

                // 計算交點
                const x = (b2 - b1) / slopeDiff;
                const y = a1 * x + b1;

                const format = (num) => Number(num.toFixed(decimals));
                resultDiv.innerHTML = `<strong>交點坐標:(${format(x)}, ${format(y)})</strong>`;

            } catch (error) {
                resultDiv.className = 'result error';
                resultDiv.textContent = '錯誤:' + error.message;
            }
        }

        // Enter 鍵觸發
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Enter') calculateIntersection();
        });
    </script>
</body>
</html>

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 19:41
ejsoon
修bug:
ejtilemo.7z
(1014 Bytes) 已下载 1 次

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 20:39
ejsoon
修好一個bug,set 不再被加入兩次。

當前代碼:
ejtileanimatejs202511132036.7z
(23.64 KiB) 尚未被下载

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 20:43
ejsoon
然後又修複了轉回ejtile刪動畫刪不乾淨的問題。

當前代碼:
ejtileanimatejs202511132043.7z
(23.64 KiB) 已下载 1 次

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 13日 21:47
ejsoon
做三角七分之一動畫:

M 0,-181.867 L 70,-60.623 L 140,60.621 L 210,181.867 L 70,181.867 L -70,181.867 L -210,181.867 L -140,60.623 L -70,-60.621 Z


第一組交點:
-60, 129.904
90, 77.942
-30, -25.98


第二組交點:
0,181.867
105, 0
-105, 0

Re: 正在做etani,ejtile的動畫套件

发表于 : 2025年 11月 14日 00:18
ejsoon
好像bug修好了,當前代碼:
ejtileanimatejs202511140015.7z
(23.65 KiB) 尚未被下载