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(); },