1.2.1 三角不等式演示

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>三角不等式动态演示:||x|-|a|| ≤ |x-a|</title>
    <style>
        canvas { background: #f8f9fa; border: 1px solid #ccc; display: block; margin: 20px auto; }
        .controls { text-align: center; font-family: Arial, sans-serif; }
        input { width: 300px; cursor: pointer; }
        p { font-size: 18px; }
        .note { color: #555; font-size: 14px; }
    </style>
</head>
<body>
<div class="controls">
    <h3>📐 三角不等式:||x| - |a|| ≤ |x - a|</h3>
    <p>
        a = <span id="a_val">0</span> &nbsp;&nbsp;&nbsp;
        x = <span id="x_val">0</span>
    </p>
    <p>
        <span style="color:red;">红色长度 = ||x| - |a|| = <span id="d1">0</span></span><br>
        <span style="color:blue;">蓝色长度 = |x - a| = <span id="d2">0</span></span><br>
        <strong>✅ 红色 ≤ 蓝色 永远成立</strong>
    </p>
    <p>
        <label>拖动 a 的值:</label>
        <input type="range" id="a_slider" min="-5" max="5" step="0.1" value="2">
    </p>
    <p>
        <label>拖动 x 的值:</label>
        <input type="range" id="x_slider" min="-5" max="5" step="0.1" value="-2">
    </p>
    <p class="note">
        💡 观察:当 a 和 x 在原点同侧时,红蓝长度相等;<br>
        &nbsp;&nbsp;&nbsp;&nbsp;当 a 和 x 在原点异侧时,红色长度小于蓝色长度。
    </p>
</div>
<canvas id="canvas" width="800" height="300"></canvas>

<script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    const width = 800, height = 300;
    canvas.width = width; canvas.height = height;

    // 坐标映射:数轴范围 -6 到 6,画布 x 范围 100 到 700
    function toX(value) {
        return 100 + (value + 6) / 12 * 600;
    }

    // 获取 DOM 元素
    const aSlider = document.getElementById('a_slider');
    const xSlider = document.getElementById('x_slider');
    const aValSpan = document.getElementById('a_val');
    const xValSpan = document.getElementById('x_val');
    const d1Span = document.getElementById('d1');
    const d2Span = document.getElementById('d2');

    function draw() {
        let a = parseFloat(aSlider.value);
        let x = parseFloat(xSlider.value);

        // 更新数值显示
        aValSpan.innerText = a.toFixed(2);
        xValSpan.innerText = x.toFixed(2);

        let absA = Math.abs(a);
        let absX = Math.abs(x);
        let d1 = Math.abs(absX - absA);
        let d2 = Math.abs(x - a);
        d1Span.innerText = d1.toFixed(3);
        d2Span.innerText = d2.toFixed(3);

        // 清空画布
        ctx.clearRect(0, 0, width, height);

        // 绘制数轴
        ctx.beginPath();
        ctx.moveTo(50, height/2);
        ctx.lineTo(width-50, height/2);
        ctx.strokeStyle = '#aaa';
        ctx.stroke();

        // 绘制刻度
        for (let val = -6; val <= 6; val += 1) {
            let xc = toX(val);
            ctx.beginPath();
            ctx.moveTo(xc, height/2 - 5);
            ctx.lineTo(xc, height/2 + 5);
            ctx.stroke();
            ctx.fillStyle = '#333';
            ctx.fillText(val, xc-5, height/2 - 10);
        }
        // 原点标注
        ctx.fillStyle = 'black';
        ctx.fillText("0", toX(0)-5, height/2 - 10);

        // 画 a 点(蓝色)
        let ax = toX(a);
        ctx.beginPath();
        ctx.arc(ax, height/2, 8, 0, 2*Math.PI);
        ctx.fillStyle = 'blue';
        ctx.fill();
        ctx.fillStyle = 'white';
        ctx.font = 'bold 14px Arial';
        ctx.fillText("a", ax-4, height/2+4);

        // 画 x 点(红色)
        let xx = toX(x);
        ctx.beginPath();
        ctx.arc(xx, height/2, 8, 0, 2*Math.PI);
        ctx.fillStyle = 'red';
        ctx.fill();
        ctx.fillStyle = 'white';
        ctx.fillText("x", xx-4, height/2+4);

        // 画 |a| 点(浅蓝色,位于正半轴)
        let absAx = toX(absA);
        ctx.beginPath();
        ctx.arc(absAx, height/2 - 40, 6, 0, 2*Math.PI);
        ctx.fillStyle = '#66c2ff';
        ctx.fill();
        ctx.fillStyle = 'black';
        ctx.fillText("|a|", absAx-8, height/2 - 45);

        // 画 |x| 点(浅红色,位于正半轴)
        let absXx = toX(absX);
        ctx.beginPath();
        ctx.arc(absXx, height/2 - 40, 6, 0, 2*Math.PI);
        ctx.fillStyle = '#ff9999';
        ctx.fill();
        ctx.fillStyle = 'black';
        ctx.fillText("|x|", absXx-8, height/2 - 45);

        // 绘制蓝色线段:a 到 x(实际距离)
        ctx.beginPath();
        ctx.moveTo(ax, height/2);
        ctx.lineTo(xx, height/2);
        ctx.strokeStyle = 'blue';
        ctx.lineWidth = 3;
        ctx.stroke();

        // 绘制红色线段:|a| 到 |x|(绝对值距离)
        ctx.beginPath();
        ctx.moveTo(absAx, height/2 - 40);
        ctx.lineTo(absXx, height/2 - 40);
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 3;
        ctx.stroke();

        // 可选:从 a 和 x 到它们绝对值点的虚线(展示翻折效果)
        ctx.beginPath();
        ctx.moveTo(ax, height/2);
        ctx.lineTo(absAx, height/2 - 40);
        ctx.strokeStyle = 'gray';
        ctx.lineWidth = 1;
        ctx.setLineDash([5, 5]);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(xx, height/2);
        ctx.lineTo(absXx, height/2 - 40);
        ctx.stroke();
        ctx.setLineDash([]); // 恢复实线

        // 标注长度
        ctx.font = '14px Arial';
        ctx.fillStyle = 'blue';
        let midX = (ax + xx)/2;
        ctx.fillText("|x-a|", midX, height/2 - 15);

        ctx.fillStyle = 'red';
        let midAbsX = (absAx + absXx)/2;
        ctx.fillText("||x|-|a||", midAbsX, height/2 - 55);

        // 额外文字提示比较
        if (d1 <= d2) {
            ctx.fillStyle = 'green';
            ctx.font = 'bold 16px Arial';
            ctx.fillText("✓ 不等式成立", width-150, 50);
        }
    }

    aSlider.addEventListener('input', draw);
    xSlider.addEventListener('input', draw);
    draw();
</script>
</body>
</html>
相关推荐
布局呆星1 小时前
Vue Router :基础使用与嵌套路由实战
前端·javascript·vue.js
小码哥_常7 小时前
安卓开发秘籍:解锁10大性能优化秘诀
前端
谁呛我名字8 小时前
JavaScript 类型转换与运算规则
javascript
try2find8 小时前
打印ascii码报错问题
java·linux·前端
郑州光合科技余经理8 小时前
同城O2O海外版二次开发实战:从支付网关到配送算法
开发语言·前端·后端·算法·架构·uni-app·php
冰暮流星9 小时前
javascript事件案例-全选框案例
服务器·前端·javascript
Dillon Dong9 小时前
【系列主题】Next.js 16 + Turbopack 的暗礁:深入剖析 Tailwind v4 的 CSS 模块解析陷阱
javascript·css·容器·turbopack
Csvn9 小时前
前端性能优化实战指南
前端
Moment10 小时前
2026 年,AI 全栈时代到了,前端简历别再只写前端技术了 🫠🫠🫠
前端·后端·面试
糯米团子74910 小时前
Web Worker
开发语言·前端·javascript