?前言
- 这个小项目源于github项目:✨50 projects 50 days, 这个项目包含了50个小型前端项目,适合学习了Html+Css+JavaScript但是还没有学习框架的前端新手作为练习。
 - 这里是原项目对模糊加载的代码实现?Blurry Loading.
 
?分析
![[前端小项目] 模糊加载 blurry loading (50projects50days) [前端小项目] 模糊加载 blurry loading (50projects50days)](https://www.yuucn.com/wp-content/uploads/2022/08/1660193175-547ea2f0bbc6c68.png)
- 变化过程:
 
- 数字从0不断增长到100;
 - 中间的百分比数字逐渐消失,即透明度
opacity到1到0; - 背景图片从模糊变为清晰,滤镜
filter:blur()的参数设置为从30px到0px. 
?布局
- 
body使用flex布局,将文字置于屏幕中央即可。 
?图片大小
- 图片的宽高如果只是设置成
100vw和100vh的话,在边界处会出现白色模糊区域(滤镜导致)。 - 可以将背景图片的宽高设置大一些,然后再调整
top和left属性,然后body设置overflow:hidden;,将白色模糊区域置于“屏幕”之外。 
⏱进度模拟
- JavaScript中使用setInterval()即可模拟进度不断增加。
 - 在进度值达到100时,使用clearInterval()取消进度增加。
 
?不同数值范围之间的映射
- 由于进度值是从0到100,而数字文本的
opacity参数是从1到0,模糊滤镜的参数值是从30到0,不同的数值范围之间需要有一个映射关系。
 
| 变量名 | 意义 | 
|---|---|
| $in\_min$ | 输入范围的起始值 | 
| $in\_max$ | 输入范围的终止值 | 
| $input$ | 输入的值 | 
| $out\_min$ | 输出范围的起始值 | 
| $out\_max$ | 输出范围的终止值 | 
| $output$ | 输出的值,即映射得到的值 | 
输入值在输入范围内占比:
\[scale_0 = \frac{input-in\_min}{in\_max - in\_min}
\]
\]
输出值在输出范围内的占比:
\[scale_1 = \frac{output-out\_min}{out\_max - out\_min}
\]
\]
又因为输入值在输入范围内的占比与输出值在输出范围中的占比应保持一致:
\[\frac{input-in\_min}{in\_max - in\_min} = \frac{output-out\_min}{out\_max - out\_min}
\]
\]
化简后,可得输出值output:
\[output = \frac{input-in\_min}{in\_max - in\_min} \times (out\_max - out\_min) + out\_min
\]
\]
function scale(num, inMin, inMax, outMin, outMax) {
        return ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
    }
该函数代码参考自StackOverflow?map a range of numbers to another range of numbers
?代码实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>blurry-loading</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            min-height: 100vh;
            /* 使用flex布局,将文字设置在屏幕中间 */
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: hidden;
        }
        .bg {
            position: absolute;
            background: url(https://images.unsplash.com/photo-1576161787924-01bb08dad4a4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2104&q=80) no-repeat center center/cover;
            filter: blur(0px);
            z-index: -1;
            /* blur滤镜会导致图片边界出现白色区域,将图片扩大可以改善 */
            top:-30px;
            left:-30px;
            width: calc(100vw + 60px);
            height: calc(100vh + 60px);
        }
        .load {
            /* 文字样式 */
            font-size: 2rem;
            color: #fff;
            font-weight: bold;
            /* 设置为不可选中 */
            user-select: none;
        }
    </style>
</head>
<body>
    <section class="bg"></section>
    <p class="load">0%</p>
</body>
<script>
    // 获取文字和背景图片
    const loadText = document.querySelector('.load');
    const bg = document.querySelector('.bg');
    //load表示当前进度的百分比数字
    let load = 0;
    // setInterval:进度不断增加,并渲染进度数字和背景模糊程度
    const int = setInterval(loading, 20);
    function loading() {
        //进度增加
        load++;
        //如果进度到达100,表示进度完成,不用增加了。
        if (load > 99) {
            clearInterval(int);
        }
        //修改进度百分数
        loadText.innerText = `${load}%`;
        //修改数字的透明度:具体表现为文字逐渐隐形
        loadText.style.opacity = scale(load, 0, 100, 1, 0);
        //修改背景图片的模糊程度
        bg.style.filter = `blur(${scale(load,0,100,30,0)}px)`;
    }
    //https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers
    //这个函数的作用是:获取 一个在某范围内的值 映射到 另一个范围时 对应的值。
    function scale(num, inMin, inMax, outMin, outMax) {
        return ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
    }
</script>
</html>