欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

atomgit仓库地址: https://gitcode.com/m0_66062719/jinshidu

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、项目概述与设计理念

1.1 应用背景

近视已经成为影响青少年健康的重大问题。根据统计,中国近视患者已超过6亿人,近视低龄化趋势明显。很多近视患者对自己的视力状况缺乏直观认识,尤其是轻度近视患者往往忽视用眼健康。本应用通过技术手段模拟不同近视度数下的视觉效果,帮助用户:

┌─────────────────────────────────────────────────────┐
│  用户需求分析                                        │
│  ├─ 直观感受近视对视觉的影响                        │
│  ├─ 了解度数与视力的对应关系                        │
│  ├─ 增强护眼意识                                    │
│  ├─ 学习科学护眼知识                                │
│  └─ 定期检查视力的意识                              │
└─────────────────────────────────────────────────────┘

1.2 技术选型

技术方案 优势 适用场景
Canvas 2D 像素级控制,绘制精确 E字视力表绘制
CSS filter GPU加速,效果流畅 模糊效果实现
JavaScript ES6+ 现代化语法,计算能力强 度数-视力换算

1.3 功能模块划分

┌─────────────────────────────────────────────────────┐
│              近视度数模拟器功能模块                  │
├─────────────────────────────────────────────────────┤
│  👓 度数选择  │  🎯 模拟预览  │  📊 视力对照表    │
│  📚 护眼知识                                             │
└─────────────────────────────────────────────────────┘

二、核心代码实现详解

2.1 度数与视力对照数据设计

// 度数与视力对照数据
const visionData = [
    { degree: 0, vision: 2.0, level: '正常', blurLevel: 0, description: '视力完全正常' },
    { degree: -1.0, vision: 1.0, level: '轻度', blurLevel: 1, description: '轻度近视,远处稍有模糊' },
    { degree: -2.0, vision: 0.6, level: '轻度', blurLevel: 2, description: '轻度近视,建议配镜' },
    { degree: -3.0, vision: 0.4, level: '中度', blurLevel: 3, description: '中度近视,裸眼视力较差' },
    { degree: -5.0, vision: 0.15, level: '中度', blurLevel: 5, description: '中高度近视,建议长期配镜' },
    { degree: -6.0, vision: 0.1, level: '高度', blurLevel: 6, description: '高度近视,务必配镜矫正' },
    { degree: -8.0, vision: 0.04, level: '高度', blurLevel: 8, description: '高度近视,视力严重下降' },
    { degree: -10.0, vision: 0.01, level: '高度', blurLevel: 10, description: '重度近视,视力严重受损' }
];

度数-视力换算原理

近视度数与裸眼视力的关系并非线性,而是近似指数关系:
├─ 0.00D → 2.0(正常视力)
├─ -1.00D → 1.0(国际标准视力)
├─ -3.00D → 0.4(轻度近视)
├─ -6.00D → 0.1(高度近视)
└─ -10.00D → 0.01(接近法定盲)

度数每增加约-3.00D,视力约下降一行(国际标准视力表)

2.2 Canvas E字视力表绘制

E字视力表是国际通用的视力检测工具,通过识别不同大小和方向的E字符来测试视力:

function drawVisionChart(ctx, width, height, blur) {
    const centerX = width / 2;
    const centerY = height / 2;
    const size = Math.min(width, height) * 0.4;
    
    // 随机方向
    const directions = ['up', 'down', 'left', 'right'];
    const direction = directions[Math.floor(Math.random() * 4)];
    
    ctx.save();
    
    // 应用模糊效果
    if (blur > 0) {
        ctx.filter = `blur(${blur}px)`;
    }
    
    ctx.strokeStyle = '#60a5fa';
    ctx.lineWidth = size / 10;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    
    const halfSize = size / 2;
    const gap = size / 5;
    
    ctx.beginPath();
    
    switch (direction) {
        case 'up':
            // E 向上(缺口朝下)
            ctx.moveTo(centerX - halfSize, centerY - halfSize);
            ctx.lineTo(centerX + halfSize, centerY - halfSize);
            ctx.moveTo(centerX - halfSize, centerY);
            ctx.lineTo(centerX + halfSize - gap, centerY);
            ctx.moveTo(centerX - halfSize, centerY + halfSize);
            ctx.lineTo(centerX + halfSize, centerY + halfSize);
            break;
        case 'down':
            // E 向下(缺口朝上)
            ctx.moveTo(centerX - halfSize, centerY + halfSize);
            ctx.lineTo(centerX + halfSize, centerY + halfSize);
            ctx.moveTo(centerX - halfSize, centerY);
            ctx.lineTo(centerX + halfSize - gap, centerY);
            ctx.moveTo(centerX - halfSize, centerY - halfSize);
            ctx.lineTo(centerX + halfSize, centerY - halfSize);
            break;
        case 'left':
            // E 向左(缺口朝右)
            ctx.moveTo(centerX - halfSize, centerY - halfSize);
            ctx.lineTo(centerX - halfSize, centerY + halfSize);
            ctx.moveTo(centerX, centerY - halfSize);
            ctx.lineTo(centerX, centerY + halfSize - gap);
            ctx.moveTo(centerX + halfSize, centerY - halfSize);
            ctx.lineTo(centerX + halfSize, centerY + halfSize);
            break;
        case 'right':
            // E 向右(缺口朝左)
            ctx.moveTo(centerX + halfSize, centerY - halfSize);
            ctx.lineTo(centerX + halfSize, centerY + halfSize);
            ctx.moveTo(centerX, centerY - halfSize);
            ctx.lineTo(centerX, centerY + halfSize - gap);
            ctx.moveTo(centerX - halfSize, centerY - halfSize);
            ctx.lineTo(centerX - halfSize, centerY + halfSize);
            break;
    }
    
    ctx.stroke();
    ctx.restore();
}

E字视力表绘制原理

E字结构:
┌─────────────────────────────────────────────────────┐
│                                                     │
│     ┌─┐                                            │
│     │ │ ← 缺口朝右的E                              │
│     └─┘                                            │
│                                                     │
│  E字由3笔组成:                                     │
│  ├─ 第1笔:整个字符的顶部或左侧                     │
│  ├─ 第2笔:中间横杠或竖杠                          │
│  └─ 第3笔:底部或右侧                              │
│                                                     │
│  4个方向:上、下、左、右                            │
│                                                     │
└─────────────────────────────────────────────────────┘

2.3 CSS模糊效果模拟

使用Canvas的filter属性实现模糊效果:

function drawBlurredVisionChart(ctx, width, height, blurConfig) {
    ctx.save();
    
    // 应用模糊效果
    if (blurConfig.blur > 0) {
        ctx.filter = `blur(${blurConfig.blur}px)`;
    }
    
    ctx.globalAlpha = blurConfig.opacity;
    
    // 绘制E字...
    drawVisionChart(ctx, width, height, 0);
    
    ctx.restore();
}

模糊参数配置

// 模糊效果配置(0-10级)
const blurConfig = {
    levels: {
        0: { blur: 0, opacity: 1 },      // 清晰
        1: { blur: 1, opacity: 0.95 },  // 几乎清晰
        2: { blur: 2, opacity: 0.9 },   // 轻微模糊
        3: { blur: 3, opacity: 0.85 },   // 轻度模糊
        4: { blur: 5, opacity: 0.8 },   // 中度模糊
        5: { blur: 7, opacity: 0.75 },  // 明显模糊
        6: { blur: 9, opacity: 0.7 },   // 严重模糊
        7: { blur: 11, opacity: 0.65 }, // 非常模糊
        8: { blur: 14, opacity: 0.6 },  // 极度模糊
        9: { blur: 17, opacity: 0.55 }, // 几乎看不清
        10: { blur: 20, opacity: 0.5 }  // 完全模糊
    }
};

CSS filter blur效果

CSS filter: blur() 函数的模糊原理:
┌─────────────────────────────────────────────────────┐
│  原始图像          高斯模糊效果                      │
│  ┌─────┐          ┌─────┐                          │
│  │ E   │   ───▶   │     │                          │
│  │     │          │     │                          │
│  └─────┘          └─────┘                          │
│                                                     │
│  blur(0px) → 完全清晰                              │
│  blur(5px) → 轻度模糊                               │
│  blur(10px)→ 中度模糊                               │
│  blur(20px)→ 严重模糊                               │
│                                                     │
│  注意:blur值越大,性能消耗越高                      │
└─────────────────────────────────────────────────────┘

2.4 度数-视力换算算法

// 根据度数获取视力值
function getVisionByDegree(degree) {
    const absDegree = Math.abs(degree);
    
    // 查找最接近的度数数据
    let closest = visionData[0];
    for (const data of visionData) {
        if (Math.abs(data.degree - absDegree) < Math.abs(closest.degree - absDegree)) {
            closest = data;
        }
    }
    
    return closest.vision;
}

// 获取度数对应的近视程度
function getDegreeLevel(degree) {
    const absDegree = Math.abs(degree);
    if (absDegree <= 3) return 'mild';       // 轻度
    if (absDegree <= 6) return 'moderate';    // 中度
    return 'severe';                          // 高度
}

// 获取度数对应的模糊等级
function getBlurLevel(degree) {
    const absDegree = Math.abs(degree);
    
    let closest = visionData[0];
    for (const data of visionData) {
        if (Math.abs(data.degree - absDegree) < Math.abs(closest.degree - absDegree)) {
            closest = data;
        }
    }
    
    return closest.blurLevel;
}

换算算法说明

度数查找算法:
┌─────────────────────────────────────────────────────┐
│                                                     │
│  输入:度数 -3.5D                                   │
│                                                     │
│  查找过程:                                         │
│  ├─ visionData[0]: degree=0, |0-3.5|=3.5          │
│  ├─ visionData[2]: degree=-2, |2-3.5|=1.5  ✓最优  │
│  ├─ visionData[3]: degree=-3, |3-3.5|=0.5  ✓最优  │
│  └─ visionData[4]: degree=-4, |4-3.5|=0.5  ✓最优  │
│                                                     │
│  返回最接近的视力值:0.3                            │
│                                                     │
└─────────────────────────────────────────────────────┘

三、交互控制实现

3.1 滑块事件处理

// 滑块变化事件
function onSliderChange(e) {
    const sliderValue = parseInt(e.target.value);
    currentDegree = sliderValue / 100; // 转换为小数
    updateDegreeDisplay();      // 更新UI显示
    renderBlurCanvas();        // 重绘模糊视图
    renderComparisonCanvases(); // 重绘对比视图
}

// 更新度数显示
function updateDegreeDisplay() {
    // 更新度数值显示
    const degreeValue = document.getElementById('degreeValue');
    degreeValue.textContent = currentDegree.toFixed(2);
    
    // 确定近视程度
    const level = getDegreeLevel(currentDegree);
    const config = levelConfig[level];
    
    // 更新程度标签
    const levelBadge = document.getElementById('degreeLevel');
    levelBadge.textContent = config.name;
    levelBadge.className = `info-badge ${config.badgeClass}`;
    
    // 更新建议
    document.getElementById('degreeDesc').textContent = config.advice;
}

3.2 近视程度配置

// 近视程度分类配置
const levelConfig = {
    mild: {
        name: '轻度近视',
        range: '≤-3.00D',
        color: '#10b981',
        badgeClass: 'mild',
        advice: '注意用眼习惯,定期检查'
    },
    moderate: {
        name: '中度近视',
        range: '-3.00D ~ -6.00D',
        color: '#f59e0b',
        badgeClass: 'moderate',
        advice: '建议及时配镜矫正'
    },
    severe: {
        name: '高度近视',
        range: '>-6.00D',
        color: '#ef4444',
        badgeClass: 'severe',
        advice: '务必配镜,定期检查眼底'
    }
};

四、视力对照表实现

4.1 表格渲染

// 更新视力对照表
function updateVisionTable() {
    const tbody = document.getElementById('visionTableBody');
    tbody.innerHTML = '';
    
    // 只显示关键度数
    const keyDegrees = [-1, -2, -3, -4, -5, -6, -7, -8, -9, -10];
    
    keyDegrees.forEach(degree => {
        const data = visionData.find(d => d.degree === degree);
        if (!data) return;
        
        const level = getDegreeLevel(degree);
        const levelClass = level === 'mild' ? 'mild' : (level === 'moderate' ? 'moderate' : 'severe');
        
        const blurDescription = getBlurDescription(data.blurLevel);
        
        const row = document.createElement('tr');
        row.innerHTML = `
            <td class="${levelClass}">${degree.toFixed(2)} D</td>
            <td>${data.vision.toFixed(2)}</td>
            <td class="${levelClass}">${data.level}</td>
            <td>${blurDescription}</td>
        `;
        tbody.appendChild(row);
    });
}

// 获取模糊程度描述
function getBlurDescription(level) {
    const descriptions = [
        '清晰',
        '几乎清晰',
        '轻微模糊',
        '轻度模糊',
        '中度模糊',
        '明显模糊',
        '严重模糊',
        '非常模糊',
        '极度模糊',
        '几乎看不清',
        '完全模糊'
    ];
    return descriptions[Math.min(level, descriptions.length - 1)];
}

五、视觉效果设计

5.1 度数滑块样式

#degreeSlider {
    width: 100%;
    height: 8px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.1);
    outline: none;
    -webkit-appearance: none;
    cursor: pointer;
}

#degreeSlider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--primary);
    cursor: pointer;
    box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
    transition: var(--transition);
}

#degreeSlider::-webkit-slider-thumb:hover {
    transform: scale(1.1);
    box-shadow: 0 0 15px rgba(59, 130, 246, 0.7);
}

5.2 程度标签样式

.info-badge {
    padding: 8px 20px;
    border-radius: 20px;
    font-weight: 600;
    font-size: 0.95rem;
}

.info-badge.mild {
    background: rgba(16, 185, 129, 0.2);
    color: #10b981;
}

.info-badge.moderate {
    background: rgba(245, 158, 11, 0.2);
    color: #f59e0b;
}

.info-badge.severe {
    background: rgba(239, 68, 68, 0.2);
    color: #ef4444;
}

六、技术亮点与创新

6.1 Canvas绘制精度

技术亮点:
┌─────────────────────────────────────────────────────┐
│  1. 像素级绘制控制                                  │
│  2. E字方向随机生成                                 │
│  3. 线条圆角优化                                    │
│  4. 自适应尺寸                                      │
└─────────────────────────────────────────────────────┘

6.2 CSS模糊效果

技术亮点:
┌─────────────────────────────────────────────────────┐
│  1. GPU加速渲染                                     │
│  2. 渐进式模糊等级                                  │
│  3. 透明度同步调整                                  │
│  4. 流畅的过渡动画                                  │
└─────────────────────────────────────────────────────┘

6.3 实时交互

技术亮点:
┌─────────────────────────────────────────────────────┐
│  1. 滑块即时反馈                                    │
│  2. 视图同步更新                                    │
│  3. 程度自动分类                                    │
│  4. 建议智能推荐                                    │
└─────────────────────────────────────────────────────┘

七、性能优化策略

7.1 Canvas重绘优化

// 避免不必要的重绘
function renderBlurCanvas() {
    const canvas = document.getElementById('blurCanvas');
    const ctx = canvas.getContext('2d');
    
    // 只在度数变化时重绘
    // 使用requestAnimationFrame优化
    requestAnimationFrame(() => {
        // 清空画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // 绘制背景
        ctx.fillStyle = '#1e293b';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        // 绘制E字
        drawBlurredVisionChart(ctx, canvas.width, canvas.height, blurConfig);
    });
}

7.2 防抖优化

// 防抖处理滑块事件
let debounceTimer;
function onSliderChange(e) {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => {
        // 处理逻辑
        const sliderValue = parseInt(e.target.value);
        currentDegree = sliderValue / 100;
        updateDegreeDisplay();
        renderBlurCanvas();
    }, 16); // 约60fps
}

八、总结与展望

8.1 项目成果

功能模块 状态 核心特性
度数选择 滑块调节、实时显示、程度分类
模拟预览 Canvas绘制、模糊效果、对比展示
视力对照表 21个度数点、颜色分类、描述说明
护眼知识 6条科学建议、实用指导

8.2 未来规划

  1. 更多视力检测功能:添加散光、老花等模拟
  2. AR视觉效果:使用WebGL实现更真实的模拟
  3. 个性化推荐:根据用户度数推荐护眼方案
  4. 数据统计:记录用户使用习惯和视力变化
  5. 专业模式:添加专业验光参数模拟

8.3 技术价值

近视度数模拟器展示了如何利用Web技术实现健康科普类应用,为开发者提供了以下参考:

  • Canvas图形绘制:E字视力表的精确实现
  • CSS滤镜效果:模糊效果的性能优化
  • 交互设计:滑块交互和实时反馈
  • 数据可视化:视力对照表的清晰展示

通过本项目的实践,开发者可以快速掌握健康科普类应用开发的核心技术,为构建更多优秀应用奠定基础。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐