import { Canvas } from "@tarojs/components"; import Taro, { useReady } from "@tarojs/taro"; import { useEffect, useRef, useState } from "react"; export default function RingProgress(props: { canvasId?: string; bgRing: any; target?: any; real?: any; scale?: number; radius: number; width?: number; height?: number; extra?: any; count?: number; shareBg?: any; shareCover?: any; isCompleted?: boolean; }) { const canvasId = props.canvasId ?? new Date().getTime() + '' const info = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync() const dpr = info.pixelRatio; // 获取设备的像素比 const [ctx, setCtx] = useState(null) const [canvas, setCanvas] = useState(null) const canvasRef = useRef(null); const canvasWidth = props.width ?? 450 const canvasHeight = props.height ?? 360 const scale = props.scale ?? 1 useEffect(() => { if (ctx) { drawContent(ctx) } else { initCanvas() } }, [props.canvasId, props.count]) useReady(() => { initCanvas() }) var retryCount = 0; function initCanvas() { const query = Taro.createSelectorQuery(); query.select(`#${canvasId}`).fields({ node: true, size: true }); query.exec((res) => { if (res[0] == null) { retryCount++; if (retryCount > 5) { return; } initCanvas() return } const _canvas = res[0].node; _canvas.width = res[0].width * dpr; _canvas.height = res[0].height * dpr; const ctx = _canvas.getContext('2d'); ctx.scale(dpr, dpr) ctx.translate(0, 0) ctx.scale(scale, scale); ctx.translate(0, 0); drawContent(ctx) setCtx(ctx) setCanvas(_canvas) }) } function drawContent(ctx) { ctx.clearRect(0, 0, canvasWidth, canvasHeight); // 清除画布 // 设置画布尺寸 if (props.shareBg) { const grd = ctx.createLinearGradient(0, 0, 0, canvasHeight); grd.addColorStop(0, props.shareBg[0]) grd.addColorStop(1, props.shareBg[1]) ctx.fillStyle = grd; ctx.fillRect(0, 0, canvasWidth, canvasHeight) } ctx.beginPath(); ctx.arc(canvasWidth / 2.0, canvasHeight / 2.0, props.radius, 0, 2 * Math.PI); ctx.lineWidth = props.bgRing.width; ctx.strokeStyle = props.bgRing.color; ctx.lineCap = 'round'; // 设置为圆角 ctx.stroke(); if (props.target) { ctx.beginPath(); ctx.arc(canvasWidth / 2.0, canvasHeight / 2.0, props.radius, props.target.start, props.target.start + Math.max(props.target.duration, 0.01)); ctx.lineWidth = props.target.width; ctx.strokeStyle = props.target.color; ctx.lineCap = 'round'; // 设置为圆角 ctx.stroke(); } if (props.real) { ctx.beginPath(); ctx.arc(canvasWidth / 2.0, canvasHeight / 2.0, props.radius, props.real.start, props.real.start + Math.max(props.real.duration, 0.01)); ctx.lineWidth = props.real.width; ctx.strokeStyle = props.real.color; ctx.lineCap = 'round'; // 设置为圆角 ctx.stroke(); } // ctx.beginPath() // ctx.arc(100, 100, 30, 0, 2 * Math.PI, false); // ctx.clip(); // ctx.beginPath(); // ctx.arc(100, 100, 30, 0, 2 * Math.PI, true); // ctx.fill(); // 设置混合模式为擦除 // ctx.globalCompositeOperation = 'destination-out' // // 绘制透明环 // ctx.beginPath() // ctx.arc(100, 100, 50, 0, 2 * Math.PI) // ctx.lineWidth = 10 // ctx.stroke() // // 重置混合模式 // ctx.globalCompositeOperation = 'source-over' if (!props.isCompleted) { var time = new Date(); var seconds = time.getHours() * 3600 + time.getMinutes() * 60 + time.getSeconds(); // seconds += props.currentDot.offset! * 60 if (seconds > 24 * 3600) { seconds -= 24 * 3600 } else if (seconds < 0) { seconds += 24 * 3600 } var arc = seconds / 86400 * 2 * Math.PI - Math.PI / 2.0; const radians = arc;//angle * Math.PI / 180; // 将角度转换为弧度 const xPrime = canvasWidth / 2.0 + props.radius * Math.cos(radians); const yPrime = canvasHeight / 2.0 + props.radius * Math.sin(radians); ctx.globalCompositeOperation = 'destination-out' ctx.beginPath(); var dotLineWidth = 4 // if (lineWidth == 28) { // dotLineWidth = 4 // } ctx.arc(xPrime, yPrime, props.target.width / 2.0, 0, 2 * Math.PI); ctx.lineWidth = dotLineWidth; ctx.fillStyle = 'transparent' ctx.fill() ctx.strokeStyle = '#1C1C1C'; ctx.lineCap = 'round'; // 设置为圆角 ctx.stroke(); ctx.globalCompositeOperation = 'source-over' } if (props.extra) { const { header, value, footer, color } = props.extra if (header) { ctx.font = `bold ${12}px sans-serif` ctx.fillStyle = '#000' ctx.textAlign = 'center' ctx.fillText(header, 225, 110); } if (value) { ctx.font = `bold ${36}px sans-serif` ctx.fillStyle = '#000' ctx.textAlign = 'center' ctx.fillText(value, 225, 164); } if (footer) { ctx.font = `bold ${15}px sans-serif` ctx.fillStyle = color ctx.textAlign = 'center' ctx.fillText(footer, 225, 195); } } if (props.isCompleted) { if (canvas) { const img1 = canvas.createImage(); // 创建图像对象 img1.src = global.checkImg img1.onload = () => { ctx.drawImage(img1, 162, 30, 200, 170); ctx.stroke(); if (props.shareCover && canvas) { save() } } } } else { if (props.shareCover && canvas) { save() } } } function save() { Taro.canvasToTempFilePath({ canvas: canvas, success: (res) => { console.log('图片保存成功:', res.tempFilePath); props.shareCover(res.tempFilePath) }, fail: (err) => { console.error('转为图片失败:', err); } }); } return }