用canvas 写出滴滴进度条效果

最近学了点canvas,做了个滴滴的进度条效果,由于本人未使用过滴滴,所以不太清楚该具体效果以及该页面是怎样的。yy出了以下效果:

用canvas 写出滴滴进度条效果

先从简单的圆开始吧!

用canvas 写出滴滴进度条效果

代码:

let c = document.getElementById("myCanvas")
// getContext() 方法返回一个用于在画布上绘图的环境。
let ctx = c.getContext("2d")
// 起始一条路径,或重置当前路径
ctx.beginPath()
// 创建弧/曲线(用于创建圆形或部分圆)
ctx.arc(100, 75, 50, 0, 2*Math.PI)
// 绘制已定义的路径
ctx.stroke()

这里贴出arc()函数说明:

context.arc(x,y,r,sAngle,eAngle,counterclockwise);

用canvas 写出滴滴进度条效果

有兴趣的同学可以进入链接查看更多属性和方法: http://caibaojian.com/html5-c...

接下来我们绘制圆环以及动画:

用canvas 写出滴滴进度条效果

let canvas = document.getElementById('myCanvas'),
    context = canvas.getContext('2d'),
    cirX = canvas.width/2,
    cirY = canvas.height/2,
    rad = Math.PI*2/100,
    n = 0,
    r = 45;

绘制图形并生成动画:

function DreamLoading() {
  // clearRect() 方法清空给定矩形内的指定像素。
  context.clearRect(0,0,canvas.width,canvas.height);
  writeCircle();
  writeText(n);
  writeOrange(n);
  if(n < 100) {
    n = n + 0.1
  } else {
    n = 100;
  }
  window.requestAnimationFrame(DreamLoading);
}

当我们写window.requestAnimationFrame(回调函数)时,浏览器会在下次重绘前执行回调函数。这样就有进度条的效果了。

画圆:

function writeCircle() {
  // 画个圆
  // save() 方法把当前状态的一份拷贝压入到一个保存图像状态的栈中。这就允许您临时地改变图像状态,然后,通过调用 restore() 来恢复以前的值。
  context.save();
  context.beginPath();
  context.strokeStyle = "#FF8C00";
  context.arc(cirX,cirY,r,0,Math.PI*2,false);
  context.stroke();
  context.restore();
}

进度条:圆的厚边框,lineWidth自行设置

function writeOrange(n) {
  context.save();
  context.strokeStyle = "#FF8C00";
  context.lineWidth = 3;
  context.beginPath();
  context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
  context.stroke();
  // restore() 方法将绘图状态置为保存值。
  context.restore();
}

文本,百分比效果:

function writeText(n) {
  context.save();
  context.strokeStyle = '#FF8C00';
  context.font = '20px Arail';
  context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
  context.stroke();
  context.restore();
}

百分比进度条效果全部代码:

<!doctype html>
<html>
<head>
<style>
  * {
    margin: 0;
    padding: 0;
  }
  canvas {
    margin: 0 auto;
    display: block;
  }
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
window.onload = function () {
let canvas = document.getElementById('myCanvas'),
    context = canvas.getContext('2d'),
    cirX = canvas.width/2,
    cirY = canvas.height/2,
    rad = Math.PI*2/100,
    n = 0,
    r = 45;
function DreamLoading() {
  context.clearRect(0,0,canvas.width,canvas.height);
  writeCircle();
  writeText(n);
  writeOrange(n);
  if(n < 100) {
    n = n + 0.1
  } else {
    n = 100;
  }
  window.requestAnimationFrame(DreamLoading);
}

function writeText(n) {
  context.save();
  context.strokeStyle = '#FF8C00';
  context.font = '20px Arail';
  context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
  context.stroke();
  context.restore();
}

function writeOrange(n) {
  context.save();
  context.strokeStyle = '    #FF8C00';
  context.lineWidth = 3;
  context.beginPath();
  context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
  context.stroke();
  context.restore();
}

function writeCircle() {
  // 画个圆
  // stroke 边框
  // 保存当前的绘制缓冲区
  context.save();
  // 开始路径
  context.beginPath();
  context.strokeStyle = "    #FF8C00";
  context.arc(cirX,cirY,r,0,Math.PI*2,false);
  context.stroke();
  context.restore();
}
DreamLoading();
}
</script>
</body>
</html>

倒计时效果代码:

let minute = 1
      const Time = minute*60
      let second = 0
      render(minute, second)
      const interval = setInterval(() => {
        if (second < 60) {
          second--
          if (second < 0) {
            second = 59
            minute--
          }
        }
        if(minute == 0 && second == 0) {
            clearInterval(interval)
        }
        render(minute, second)
      },1000)

      function render(minute, second) {
        if (minute < 10) {
          document.querySelector('.minute').innerText = '0' + minute;
        } else {
          document.querySelector('.minute').innerText = minute;
        }
        if (second < 10) {
          document.querySelector('.second').innerText = '0' + second;
        } else {
          document.querySelector('.second').innerText = second;
        }
      }

完整代码:

   <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .header {
      height: 44px;
      border-bottom: 1px solid #eee;
      background-color: #ddd;
      display: -webkit-flex;
      display: flex;
      align-items: center;
    }
    .header-left {
      width: 3rem;
      margin-left: 1rem;
    }
    .header-left .back {
      display: block;
      width: .8rem;
      height: .8rem;
      border-left: 1px solid red;
      border-bottom: 1px solid red;
      transform: rotateZ(45deg);
    }
    .header-middle {
      flex: 1;
      text-align: center;
    }
    .header-right {
      width: 4rem;
      margin-right: .5rem;
    }
    .content {
      width: 100%;
      height: 11rem;
      background: url(http://st2.depositphotos.com/6064568/10599/v/950/depositphotos_105993268-stock-illustration-man-holding-smartphone-in-hand.jpg);
      background-size: cover;
      position: relative;
    }
    canvas {
      margin: 0 auto;
      display: block;
    }
    .tip {
      text-align: center;
      font-size: 1.2rem;
      margin-top: -.5rem;
    }
    .time {
      /*width: 5rem;
      height: 1rem;*/
      /*position: absolute;
      top: 30%;*/
      /*left: 42%;*/
      margin: 0 auto;
      margin-top: -7rem;
    }
    .time p:first-child {
      font-size: 1.5rem;
      text-align: center;
    }
    .time p:last-child {
      font-size: .8rem;
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="header">
    <div class="header-left">
      <i class="back"></i>
    </div>
    <div class="header-middle">
      派单中
    </div>
    <div class="header-right">
      取消订单
    </div>
  </div>
  <div class="content">
    <canvas id="canvas"></canvas>
    <div class="tip">系统选择司机</div>
    <div class="time">
      <p><span class="minute"></span>:<span class="second"></span></p>
      <p>秒倒计时</p>
    </div>
  </div>
  <script>
    window.onload = function() {
      let minute = 1
      const Time = minute*60
      let second = 0
      render(minute, second)
      const interval = setInterval(() => {
        if (second < 60) {
          second--
          if (second < 0) {
            second = 59
            minute--
          }
        }
        if(minute == 0 && second == 0) {
            clearInterval(interval)
        }
        render(minute, second)
      },1000)

      function render(minute, second) {
        if (minute < 10) {
          document.querySelector('.minute').innerText = '0' + minute;
        } else {
          document.querySelector('.minute').innerText = minute;
        }
        if (second < 10) {
          document.querySelector('.second').innerText = '0' + second;
        } else {
          document.querySelector('.second').innerText = second;
        }
      }
      var canvas = document.getElementById('canvas'),
          context = canvas.getContext('2d'),
          cirX = canvas.width/2,
          cirY = canvas.height/2,
          rad = Math.PI*2/(Time*Math.PI*2),
          n = 0,
          r = 45;
      function DreamLoading() {
        context.clearRect(0,0,canvas.width,canvas.height);
        writeCircle();
        // writeText(n);
        writeOrange(n);
        if(n < Time*Math.PI*2) {
          n = n + 0.105
        } else {
          n = Time*Math.PI*2;
        }
        window.requestAnimationFrame(DreamLoading);
      }

      // function writeText(n) {
      //   context.save();
      //   context.strokeStyle = '#FF8C00';
      //   context.font = '20px Arail';
      //   context.strokeText(n.toFixed() + '%', cirX-30,cirY+10);
      //   context.stroke();
      //   context.restore();
      // }

      function writeOrange(n) {
        context.save();
        context.strokeStyle = '    #FF8C00';
        context.lineWidth = 3;
        context.beginPath();
        context.arc(cirX,cirY,r,-Math.PI/2,-Math.PI/2+rad*n,false);
        context.stroke();
        context.restore();
      }

      function writeCircle() {
        // 画个圆
        // stroke 边框
        // 保存当前的绘制缓冲区
        context.save();
        // 开始路径
        context.beginPath();
        context.strokeStyle = "    #FF8C00";
        context.arc(cirX,cirY,r,0,Math.PI*2,false);
        context.stroke();
        context.restore();
      }
      DreamLoading();
    }
  </script>
</body>
</html>

不够精确,在计算的时候有些错误。希望同学们能一起解决。谢谢!

上一篇:MySQL字段名与保留字冲突导致的异常解决


下一篇:微信小程序日期转换、比较、加减