美文网首页
使用SVG画双向进度条

使用SVG画双向进度条

作者: 柠檬信息技术有限公司 | 来源:发表于2018-01-29 12:42 被阅读75次

    同学在公司遇到个需求,使用SVG画一个双向进度条(具体专业名词叫什么不清楚……),然后使用JS动态改变进度。之前一直都是用canvas画,没有过这方面经验,就尝试着画了一下,在此进行记录。下面是需求效果图:

    0x01. 效果

    • 下面这张图是需求的效果


      需求效果
    • 这张图是最后的代码实现的效果


      最后实现效果

    0x02. 在线工具起草

    上来就自己起草干肯定非常费劲(最起码对我这种SVG新手来说是这样),所以偷懒了一下,用了在线SVG绘制工具,地址:https://svg.haowen100.com

    用工具画的效果

    0x03. 分析与实现

    绘制完成之后点击View菜单,然后选择Souce菜单项,即可看见绘制出的图形对应的代码

    menu.jpg

    分析一下,整个进度条分为三部分,一部分是外面的黑色边框,第二部分是中间填充的进度条颜色,第三部分是周围零零碎碎的进度刻度等文字,其中第一部分黑色边框一旦设置位置大小之后就无需改变了,只需要改变进度条填充颜色部分的长度和X坐标即可,还有第三部分中的进度条上的刻度数字和刻度位置。
    其中进度颜色填充部分的还分两块,一部分是从0%(青岛)那里开始到左边月100%的部分,下文称之为负进度,第二部分是从0%(青岛)到右边日100%的部分,下文称之为正进度。整个进度条的X坐标根据负进度的多少而定,而进度条的长度根据负进度和正进度的计算而定,我们首先计算出正进度和负进度的每1%的单位长度、负进度条100%时候的进度条长度,然后拿到整个进度条黑色边框的最左侧X坐标后进行计算:

    进度条颜色填充的X坐标 = 黑色边框的X坐标 + 负进度的1%单位长度 * (100 - 负进度当前进度)
    进度条颜色填充的长度 = 负进度条的进度 * 负进度条的1%单位长度 + 正进度条的进度 * 正进度条的1%单位长度
    

    得到这两个数值之后,我们对界面中的控件属性进行赋值即可。接下来使用setInterval()进行动态更新进度得到文章开头中的动画效果。
    动画中还有一个效果就是当进度小于一定数值的时候 进度不动,这个很简单,就是用Math.min()Math.max()进行处理一下即可,具体的可以看一下下面代码。

    0x04. 代码

    最后整理代码如下,就一个HTML文件,就不放Github地址了。代码中有注释,有不懂的同学可以留言

    <!DOCTYPE html>
    <html>
    <head>
        <title>大吉大利,今晚吃鸡</title>
        <meta charset="utf-8">
    </head>
    <body>
    <!-- 画布 定义画布宽高,看你用多宽多高就写多少-->
    <svg width="700" height="400" xmlns="http://www.w3.org/2000/svg">
        <!-- 边框矩形 -->
        <rect id="borderView" height="40" width="600" y="80" x="50" stroke-width="1.5" stroke="#000" fill="#fff"/>
        <!-- 进度填充矩形 -->
        <rect id="progressView" height="40" width="387" y="80" x="100" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="#00bf5f"/>
    
        <!-- 刻度 负:50-150 正:150-50-->
        <!-- 负100% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="kedus100" y2="119.59974" x2="50" y1="131" x1="50" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 正0% -->
        <line stroke-linecap="null" stroke-linejoin="null" id="kedup0" y2="131.17834" x2="150" y1="61" x1="150" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
        <!-- 正20% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="kedup20" y2="120.59974" x2="250" y1="132" x1="250" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 正40% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_10" y2="120.59974" x2="350" y1="132" x1="350" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 正60% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_11" y2="120.59974" x2="450" y1="132" x1="450" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 正80% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_12" y2="121.59974" x2="550" y1="133" x1="550" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 正100% -->
        <line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="kedup100" y2="119.59974" x2="650" y1="131" x1="650" stroke-opacity="null" stroke-width="1.5" fill="none"/>
        <!-- 刻度数字 -->
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_7" y="145" x="40" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">100%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_18" y="145" x="140" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">0%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_19" y="145" x="240" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">20%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_20" y="145" x="340" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">40%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_21" y="145" x="440" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">60%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_22" y="145" x="540" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">80%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="12" id="svg_7" y="145" x="640" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">100%</text>
    
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="14" id="subNumView" y="105" x="0" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">90%</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="14" id="plusNumView" y="105" x="0" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">60%</text>
    
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="18" id="svg_13" y="55" x="45" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">月</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="18" id="svg_14" y="55" x="640" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">日</text>
        <text xml:space="preserve" text-anchor="start" font-family="Helvetica, Arial, sans-serif" font-size="22" id="svg_15" y="50" x="128" fill-opacity="null" stroke-opacity="null" stroke-width="0" stroke="#000" fill="#000000">青岛</text>
    </svg>
    
    <script type="text/javascript">
        function changeProgress(sub , plus){
            var progressView = document.getElementById('progressView');
            var subNumView = document.getElementById('subNumView');
            var plusNumView = document.getElementById('plusNumView');
    
            // 左边福进度条的最左边X坐标,即-100%进度时候的x坐标
            var sub_start = 50;
            // 整个负进度条占满100%的时候长度
            var sub_width = 100;
            // 左边的负数进度条每1%的像素长度
            var sub_unit = sub_width / 100.0
            // 整个正进度条占满100%的时候长度
            var plus_width = 500;
            // 右边的正数进度条每1%的像素长度
            var plus_unit = plus_width / 100.0;
            
            // 开始计算进度条控件属性
            var progress_x = sub_start + (sub_width - sub) * sub_unit;
            var progress_width = sub * sub_unit + plus * plus_unit;
            var sub_num_x = Math.min(progress_x + 10 , 110);
            var plus_num_x = Math.max(progress_x + progress_width - 40 , 190);
            // 计算完毕。开始赋值应用
            progressView.setAttribute('x' , progress_x);
            progressView.setAttribute('width' , progress_width);
            subNumView.setAttribute('x' , sub_num_x);
            plusNumView.setAttribute('x' , plus_num_x);
            subNumView.innerHTML = sub + '%';
            plusNumView.innerHTML = plus + '%';
        }
        var progress = 0;
        // 进度定时增加
        var interval = setInterval(function(){
            if (++ progress >= 100) {clearInterval(interval)}
            changeProgress(progress,progress);
        } , 100);
    </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:使用SVG画双向进度条

          本文链接:https://www.haomeiwen.com/subject/itdxzxtx.html