| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- 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<any>(null)
- const [canvas, setCanvas] = useState<any>(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 <Canvas canvasId={canvasId} id={canvasId} className="canvas" type="2d"
- style={{ width: canvasWidth, height: canvasHeight, zIndex: 0 }}
- ref={canvasRef}
- />
- }
|