• 小程序 Canvas 倒计时组件 (React 版)


    基于前面Web版修改而来    Canvas 倒计时

     源码:

    import { Canvas, View } from "@tarojs/components"
    import Taro from '@tarojs/taro'
    import { FC } from "@tarojs/taro"
    import rpxToPx from "../../utils/dom"
    import { useEffect, useState } from "react"
    import './countDown.less'
    import React from "react"
    
    interface ICountDownProps {
        onMissed: () => void
        duration: number // 总时长
        countTime: number // 已经错过的时间
    }
    
    let timer
    const CountDown: FC<ICountDownProps> = ({ onMissed, duration, countTime }) => {
    
        const basePx = 280
        const [time] = useState(duration) // 可以随意设置
        let [count, setCount] = useState(duration - countTime) // 倒计时剩余时间
        const percent = 2 / time // 每一秒需要的度数
    
        useEffect(() => {
            Taro.eventCenter.on('onSignClose', () => {
                clearInterval(timer)
            })
    
            return () => {
                clearInterval(timer)
                Taro.eventCenter.off('onSignClose')
            }
        }, [])
    
        const XYPoint = rpxToPx(basePx) / 2
        const R = (rpxToPx(basePx) - 7) / 2
    
        const getPercent = (count) => {
            const deg = (time - count) * percent
            console.log('count , deg:', count, deg)
            return deg <= 0 ? -0.5 * Math.PI : (1.5 - deg) * Math.PI
        }
    
        const drawBottom = () => {
            wx.createSelectorQuery()
                .select('#cvs1')
                .fields({
                    node: true,
                    size: true,
                })
                .exec((res) => {
                    console.log(res)
                    if (!res[0]) return
                    const canvas = res[0].node
                    const ctx1 = canvas.getContext('2d')
    
                    // 设置canvas 高宽
                    const dpr = wx.getSystemInfoSync().pixelRatio
                    canvas.width = rpxToPx(basePx) * dpr
                    canvas.height = rpxToPx(basePx) * dpr
                    ctx1.scale(dpr, dpr)
    
                    ctx1.beginPath()
                    ctx1.lineWidth = 3
                    ctx1.strokeStyle = '#d9d9d9'
                    ctx1.arc(XYPoint, XYPoint, R, 0, 2 * Math.PI, false)
                    ctx1.stroke()
                })
        }
    
        const drawCenter = () => {
            wx.createSelectorQuery()
                .select('#cvs2')
                .fields({
                    node: true,
                    size: true,
                })
                .exec((res) => {
                    console.log(res)
                    if (!res[0]) return
                    const canvas = res[0].node
                    const ctx2 = canvas.getContext('2d')
    
                    // 设置canvas 高宽
                    const dpr = wx.getSystemInfoSync().pixelRatio
                    canvas.width = rpxToPx(basePx) * dpr
                    canvas.height = rpxToPx(basePx) * dpr
                    ctx2.scale(dpr, dpr)
    
                    ctx2.beginPath()
                    ctx2.lineWidth = 5
                    ctx2.strokeStyle = '#4F8BFF'
                    ctx2.lineCap = 'round'
                    ctx2.arc(XYPoint, XYPoint, R, 1.5 * Math.PI, getPercent(count), false)
                    ctx2.stroke()
                })
        }
    
        const drawTop = () => {
            wx.createSelectorQuery()
                .select('#cvs3')
                .fields({
                    node: true,
                    size: true,
                })
                .exec((res) => {
                    console.log(res)
                    if (!res[0]) return
                    const canvas = res[0].node
                    const ctx3 = canvas.getContext('2d')
    
                    // 设置canvas 高宽
                    const dpr = wx.getSystemInfoSync().pixelRatio
                    canvas.width = rpxToPx(basePx) * dpr
                    canvas.height = rpxToPx(basePx) * dpr
                    ctx3.scale(dpr, dpr)
    
                    ctx3.beginPath()
                    ctx3.lineWidth = 5
                    ctx3.strokeStyle = '#4F8BFF'
                    ctx3.lineCap = 'round'
                    ctx3.arc(XYPoint, XYPoint, R, 1.5 * Math.PI, getPercent(count), false)
                    ctx3.stroke()
                })
        }
    
        const startCountDown = () => {
            if (count <= 1) {
                onMissed()
                clearInterval(timer)
                return
            }
            setCount(--count)
            wx.createSelectorQuery()
                .select('#cvs2')
                .fields({
                    node: true,
                    size: true,
                })
                .exec((res) => {
                    console.log(res)
                    if (!res[0]) return
                    const canvas = res[0].node
                    const ctx2 = canvas.getContext('2d')
    
                    // 设置canvas 高宽
                    const dpr = wx.getSystemInfoSync().pixelRatio
                    canvas.width = 0
                    canvas.width = rpxToPx(basePx) * dpr
                    canvas.height = rpxToPx(basePx) * dpr
                    ctx2.scale(dpr, dpr)
                })
    
    
            setTimeout(() => {
                drawCenter()
    
                wx.createSelectorQuery()
                    .select('#cvs3')
                    .fields({
                        node: true,
                        size: true,
                    })
                    .exec((res) => {
                        console.log(res)
                        if (!res[0]) return
                        const canvas = res[0].node
                        const ctx3 = canvas.getContext('2d')
    
                        // 设置canvas 高宽
                        const dpr = wx.getSystemInfoSync().pixelRatio
                        canvas.width = 0
                        canvas.width = rpxToPx(basePx) * dpr
                        canvas.height = rpxToPx(basePx) * dpr
                        ctx3.scale(dpr, dpr)
                    })
    
                setTimeout(() => {
                    drawTop()
                }, 20)
            }, 20)
        }
    
        useEffect(() => {
            setTimeout(() => {
                drawBottom()
                drawCenter()
                drawTop()
            }, 100)
    
            timer = setInterval(startCountDown, 1000)
        }, [])
    
        const _pixel = rpxToPx(basePx)
    
        return <View
            style={` ${_pixel}px; height: ${_pixel}px;`}
            className="countdown-container flex flex-item-center flex-justify-center">
            <Canvas style={` ${_pixel}px; height: ${_pixel}px;z-index: 0;`} id="cvs1" type="2d"></Canvas>
            <Canvas style={` ${_pixel}px; height: ${_pixel}px;z-index: 1;`} id="cvs2" type="2d"></Canvas>
            <Canvas style={` ${_pixel}px; height: ${_pixel}px;z-index: 2;`} id="cvs3" type="2d"></Canvas>
            <View className="flex flex-col flex-justify-center flex-item-center">
                <View className="timer-count flex flex-item-center flex-justify-center"> {count} </View>
                <View className="timer-tips flex flex-item-center" > 倒计时 (S) </View>
            </View>
        </View >
    }
    
    export default CountDown
    

      

    rpx to px(横屏、分辨率适配需要用到):

    export default function rpxToPx(rpx) {
        const orientation = wx.getSystemInfoSync().deviceOrientation
        if (orientation == 'landscape') {
            return Math.round(rpx * wx.getSystemInfoSync().windowHeight / 750)
        }
    
        return Math.round(rpx * wx.getSystemInfoSync().windowWidth / 750)
    }
    

      

    效果:

      

  • 相关阅读:
    Python-Collections模块之defaultdict
    Python-Collections模块之deque
    Python-Collections模块之NameTuple
    Python-Collections模块之OrderedDict
    @常见的远程服务器连接工具:Xshell与secureCRT的比较!!!(对于刚接触的测试小白很有帮助哦)
    告诉你:传统测试和敏捷测试的区别!!!(比较全的解答,一看便明白)
    @软件测试环境搭建的详细流程(初学者不要错过哦,很实用)!!!!
    Netlib文件转化为mps文件
    新设备关联Gitlab
    CMake与OpenMP
  • 原文地址:https://www.cnblogs.com/307914070/p/15014551.html
Copyright © 2020-2023  润新知