使用 canvas 制作一个动态的音乐播放按钮
效果动图
背景
按钮需要显示进度、封面、跳动的线条。
如果用 canvas 画图片的话,可能存在图片跨域的情况,图片就用 img
标签加载。
canvas 需要做的事就只有绘制进度圈、图标。
HTML 结构
<div class="play-box">
<div class="cover-box">
<img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" alt="封面">
</div>
<canvas class="canvas-progress" id="j-progress" width="60" height="60"></canvas>
</div>
固定一个区域,图片用一个 div 包裹,超过就隐藏(部分浏览器 img 标签不支持圆角属性)。
基础变量
const ELE_PROGRESS = document.querySelector('#j-progress');
const CTX_PROGRESS = ELE_PROGRESS.getContext('2d');
const ARC_WIDTH = 4; // 圆弧宽
const WhiteValue = '#fff';
const FillingValue = '#c64e40';
画一个最简单的进度
先画最外层的白色圈,再在白色圈上覆盖一层其他颜色的进度
let progress = 30;
const SIZE_HALF = SIZE / 2;
const lineWidth = ARC_WIDTH;
const startAngle = (3 / 2) * Math.PI; // 开始位置弧度
const diffAngle = (progress / 100) * Math.PI * 2; // 完成进度弧度值
ctx.beginPath();
ctx.lineWidth = lineWidth;
ctx.lineCap = 'butt';
ctx.arc(SIZE_HALF, SIZE_HALF, SIZE_HALF - lineWidth / 2, 0, 2 * Math.PI, false);
ctx.strokeStyle = WhiteValue;
ctx.stroke();
ctx.beginPath();
ctx.arc(SIZE_HALF, SIZE_HALF, SIZE_HALF - lineWidth / 2, startAngle, diffAngle + startAngle, false);
ctx.strokeStyle = FillingValue;
ctx.stroke();
中心点是二分之一的容器大小,圆弧的起点是 三点钟方向
,这需要注意一下,一般情况视觉上起点是 十二点中方向
。
画一个三角形
先给内圈添加一个背景色,再加一个白色的三角形
ctx.beginPath();
ctx.arc(SIZE / 2, SIZE / 2, SIZE / 2 - ARC_WIDTH, 0, 2 * Math.PI);
ctx.fillStyle = FillingValue;
ctx.fill();
ctx.beginPath();
ctx.moveTo(SIZE / 3, SIZE / 4);
ctx.lineTo((SIZE / 4) * 3, SIZE / 2);
ctx.lineTo(SIZE / 3, (SIZE / 4) * 3);
ctx.closePath();
ctx.fillStyle = WhiteValue;
ctx.fill();
边缘模糊
画进度的时候就会发现,圈的边缘会模糊,还是应为高清屏的原因。
纯浏览器端可以试试 hidpi-canvas-polyfill 这个库。
其他
剩下的过程查看源码了解。canvas-play-bar
还有一个问题,边沿锯齿,暂时没有解决。