1. 微信小程序用的 是 canvas-id
<canvas class="canvas-process" id="canvas" canvas-id="canvas" :width="width" :height="height" ></canvas>
2. 需要在onLoad 里面指定canvas 的宽高, ==> 这里的宽高是画布的宽高, 不是容器的宽高
const systemInfo = uni.getSystemInfoSync(); this.pixelRatio = systemInfo.devicePixelRatio; // canvas 的宽度不等于 容器的宽度 this.width = uni.upx2px(750) * this.pixelRatio; this.height = uni.upx2px(448) * this.pixelRatio;
3. 一般是在页面绘制完成, 才会调用canvas的绘制功能, 所以 uniapp 中 需要加 this.$nextTick(() => { ... })
this.$nextTick(() => { this.drawProcess(process); });
4. 绘制前的一些操作
const context = uni.createCanvasContext("canvas"); context.scale(1 / this.pix, 1 / this.pix); // canvas 需要按照设备比 缩小 const size = (x) => uni.upx2px(x) * this.pixelRatio; // 所有的尺寸都要按照这个函数进行转换 const w = uni.upx2px(750) * this.pixelRatio; // canvas 的宽度, 下文直接使用 无需转换 const h = uni.upx2px(448) * this.pixelRatio; // canvas 的高度, 下文直接使用 无需转换
for example:
// 绘制进度条 drawProcess(process) { const context = uni.createCanvasContext("canvas"); context.scale(1 / this.pix, 1 / this.pix); const size = (x) => uni.upx2px(x) * this.pixelRatio; const w = uni.upx2px(750) * this.pixelRatio; const h = uni.upx2px(448) * this.pixelRatio; const pai = Math.PI; const percentage = process / 100; const endAngle = pai * percentage * 2; // 请除之前的样式 context.setFillStyle("#fff"); context.fillRect(0, 0, w, h); context.setShadow(0, 0, 0, "rgba(255,255,255,0)"); // 绘制最大的圆环 context.moveTo(w / 2, h / 2); context.beginPath(); context.arc(w / 2, h / 2, size(180), 0, 2 * pai, true); const grd = context.createCircularGradient(w / 2, h / 2, size(180)); grd.addColorStop(0, "#a9caff"); grd.addColorStop(1, "#e0ebff"); context.setFillStyle(grd); context.fill(); // 绘制内部的白色圆环 context.moveTo(w / 2, h / 2); context.beginPath(); context.arc(w / 2, h / 2, size(125), 0, 2 * pai, true); context.setFillStyle("#ffffff"); context.fill(); // 绘制进度 context.moveTo(w / 2, h / 2); context.beginPath(); context.arc(w / 2, h / 2, size(137), pai, endAngle + pai); context.setStrokeStyle("#0967ff"); context.setLineCap("round"); context.setLineWidth(size(24)); context.stroke(); // 求终点坐标 /** * cosA = x / r sinA = y / r * x = r * cosA y = r * sinA */ const endPointX = size(137) * Math.cos(endAngle + pai); const endPointY = size(137) * Math.sin(endAngle + pai); // 绘制终点 大白色圆 ----> 移动圆心到中心点位置 context.moveTo(endPointX, endPointY); context.beginPath(); context.arc(w / 2 + endPointX, h / 2 + endPointY, size(28), 0, 2 * pai); context.setShadow(0, size(12), size(16), "rgba(9,103,255, 0.3)"); context.setFillStyle("#fff"); context.fill(); // 绘制小蓝圆 context.beginPath(); context.arc(w / 2 + endPointX, h / 2 + endPointY, size(20), 0, 2 * pai); context.setFillStyle("#0967ff"); context.fill(); // 绘制进度文字 context.beginPath(); context.setTextAlign("center"); context.setTextBaseline("middle"); context.setFontSize(size(48)); context.setFillStyle("#0967ff"); context.fillText(`${process}%`, w / 2, h / 2); context.draw(); },