美文网首页
uni-app使用canvas绘制时间刻度以及不显示问题处理

uni-app使用canvas绘制时间刻度以及不显示问题处理

作者: hao_developer | 来源:发表于2023-03-28 19:33 被阅读0次
    image.png

    为了减少性能消耗,把底部半透明圆环、刻度、数字、图标、字符串作为一个canvas

    有色进度圆环作为一个canvas,避免重复的进行画,需要用定位进行叠加

    有更好的方法欢迎在下方留下宝贵的ideal

    修改前

     ctx.draw()
    

    修改后

    setTimeout(()=>{// uni-app必须加上延迟,不然显示不出来, 亲测 
      ctx.draw() 
    }, 100)
    

    项目的构思

    canvas中圆的起点都是从三点钟顺时针方向开始的,后面需要用到旋转来调整到快要到九点钟开始画圆ctx.rotate(旋转角度 * Math.PI / 180)

    image.png
    405da8af391e8ab3d1d8c356a2e4325.jpg
    image.png

    全部代码

    <template>
        <view>
            <view class="content" style="position: relative;width:70vw;height:70vw">
                <canvas id="circle" canvas-id="circle" style="width:70vw;height:70vw;"></canvas>
                <canvas canvas-id="circlePro"
                    style="width:70vw;height:70vw;border: 1rpx solid green;position: absolute;left: 0;top: 0;right: 0;bottom: 0;"></canvas>
            </view>
            <view style="color: white;text-align: center;margin-top: 50rpx;">
                {{time}} min
            </view>
            <view style="display: flex;flex-direction: row;justify-content: space-evenly;margin-top: 50rpx;">
                <button @click="clickHandler(1)" @longpress="longHandler(1)" @touchend="endHandler" type="default" style="width: 300rpx;">+1</button>
                <button @click="clickHandler(2)" @longpress="longHandler(2)" @touchend="endHandler" type="default" style="width: 300rpx;">-1</button>
            </view>
        </view>
    </template>
    
    <script>
        export default {
            data() {
                return {
                    value: 0, //当前角度对应值
                    time: 0, //当前角度对应时间
                    addId: null, //循环增加标识
                    reduceId: null, //循环减少标识
                }
            },
            onLoad() {
                this.drawCircle();
            },
            methods: {
                clickHandler(operation) {//+,-点击事件处理
                    let value = this.value;
                    if (operation == 1) {
                        value++;
                        if (value > 8) return;
                    } else {
                        value--;
                        if (value < 0) return;
                    }
                    this.value = value;
                    this.drawPro();
                    this.valueToMin();
                },
                valueToMin() { //value转化为时间min
                    const value = this.value;
                    let time = 0;
                    switch (value) {
                        case 0:
                            time = 0;
                            break;
                        case 1:
                            time = 5;
                            break;
                        case 2:
                            time = 10;
                            break;
                        case 3:
                            time = 15;
                            break;
                        case 4:
                            time = 20;
                            break;
                        case 5:
                            time = 25;
                            break;
                        case 6:
                            time = 30;
                            break;
                        case 7:
                            time = 35;
                            break;
                        case 8:
                            time = 40;
                            break;
                    }
                    this.time = time;
                },
                longHandler(operation) { //+,-长按事件处理
                    let value = this.value;
                    if (operation == 1) {
                        this.addId = setInterval(() => {
                            value++;
                            if (value > 8) return;
                            this.value = value;
                            this.drawPro();
                            this.valueToMin();
                        }, 200);
                    } else {
                        this.reduceId = setInterval(() => {
                            value--;
                            if (value < 0) return;
                            this.value = value;
                            this.drawPro();
                            this.valueToMin();
                        }, 200);
                    }
    
                },
                endHandler() { //+,-短或长按事件处理
                    clearInterval(this.addId);
                    clearInterval(this.reduceId);
                },
                drawPro() { //画白色进度
                    //定义画图大小    
                    const windowWidth = uni.getSystemInfoSync().windowWidth; //获取屏幕的宽度
                    let width = windowWidth * 0.7; //canvas宽
                    let height = windowWidth * 0.7; //canvas高
    
                    //获取中心坐标
                    let centerPoint = {
                        x: width / 2,
                        y: height / 2
                    }
                    const radius = width / 2;
                    const ringHD = radius * 0.06;
                    const ringRadius = radius * 0.8;
                    let ctx = uni.createCanvasContext('circlePro', this);
                    ctx.save();
                    ctx.translate(centerPoint.x, centerPoint.y); //移动中心点到centerPoint点上
                    ctx.rotate(157.5 * Math.PI / 180); //顺时针旋转角度 90 + 45 + 45 / 2
    
                    const value = this.value;
                    const eachMark = 1 / 8; //0.125  一半 0.0625
                        
                    ctx.beginPath();
                    ctx.setStrokeStyle('white');
                    ctx.setLineCap('round');
                    ctx.setLineWidth(ringHD);
                    //0~5和40~45 每一各占有 eachMark / 2
                    //5~40 每一各占有 eachMark / 5 
                    if (value == 1) {
                        ctx.arc(0, 0, ringRadius, 0, value * (eachMark / 2) * (1.25 * Math.PI));
                    } else if (value > 1 && value <= 7) {
                        ctx.arc(0, 0, ringRadius, 0, (eachMark / 2 + (value - 1) * eachMark) * (1.25 * Math.PI));
                    } else if (value == 8) {
                        ctx.arc(0, 0, ringRadius, 0, (eachMark * 8 + (value - 8) * eachMark / 2) * (1.25 * Math.PI));
                    }
                    ctx.stroke();
    
                    setTimeout(() => {//需要做延迟处理才能够渲染出来
                        ctx.draw();
                    }, 50)
                },
                drawCircle() {//画底部半透明进度背景
                    //定义画图大小    
                    const windowWidth = uni.getSystemInfoSync().windowWidth; //获取屏幕宽度
                    let width = windowWidth * 0.7; //canvas宽
                    let height = windowWidth * 0.7; //canvas高
    
                    //获取中心坐标
                    let centerPoint = {
                        x: width / 2,
                        y: height / 2
                    }
                    const radius = width / 2;
                    const ringHD = radius * 0.06;
                    const ringRadius = radius * 0.8;
                    const ctx = uni.createCanvasContext('circle', this);
                    ctx.save();
                    ctx.translate(centerPoint.x, centerPoint.y); //把中心点移动到centerPoint点上
                    ctx.rotate(157.5 * Math.PI / 180); //顺时针旋转 90 + 45 + 45 / 2
    
                                    //画中心圆点
                    // ctx.beginPath();
                    // ctx.setStrokeStyle('red');
                    // ctx.arc(0, 0, 5, 0, 2 * Math.PI);
                    // ctx.stroke();
    
                    ctx.beginPath();
                    ctx.setStrokeStyle('#66bffa');
                    ctx.setLineWidth(ringHD);
                    ctx.setLineCap('round');
                    ctx.arc(0, 0, ringRadius, 0, 1.25 * Math.PI);
                    ctx.stroke();
    
                    ctx.rotate(-157.5 * Math.PI / 180); //顺时针旋转角度 90 + 45 + 45 / 2
                                    
                                    //画小短线
                    const each = 225 / 8; //225 整个圆弧的角度是225°
                    for (let index = 0; index < 8; index++) {
                        ctx.rotate(((index == 0) ? (90 - 45 / 2 + each / 2) : each) * Math.PI / 180); //每个小短线的顺时针旋转角度
                        ctx.beginPath();
                        ctx.setLineWidth(1);
                        ctx.setStrokeStyle('white');
                        ctx.moveTo(0, radius * 0.765);
                        ctx.lineTo(0, radius * 0.68);
                        ctx.stroke();
                    }
                    ctx.rotate(-(each * 7 + ((90 - 45 / 2 + each / 2))) * Math.PI / 180); //恢复到画小短线之前的角度
    
                    const textRadius = radius * 0.6
                    //5
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('5', -Math.cos(45 / 4 * Math.PI / 180) * textRadius * 1.08, Math.sin(45 / 4 * Math.PI / 180) *
                        textRadius);
                    ctx.fill();
                    //10
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('10', -Math.cos(45 / 2 * Math.PI / 180) * textRadius * 1.1, -Math.sin(45 / 2 * Math.PI /
                        180) * textRadius * 0.8);
                    ctx.fill();
                    //15
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('15', -Math.cos(45 * Math.PI / 180) * textRadius, -Math.sin(45 * Math.PI / 180) * textRadius);
                    ctx.fill();
                    //20
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('20', -Math.cos((90 - each / 2) * Math.PI / 180) * textRadius * 1.4, -Math.sin((90 - each /
                        2) * Math.PI / 180) * textRadius * 0.9);
                    ctx.fill();
                    //25
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('25', Math.cos((90 - each / 2) * Math.PI / 180) * textRadius * 0.8, -Math.sin((90 - each /
                        2) * Math.PI / 180) * textRadius * 0.9);
                    ctx.fill();
                    //30
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('30', Math.cos(45 * Math.PI / 180) * textRadius * 0.8, -Math.sin(45 * Math.PI / 180) *
                        textRadius * 0.9);
                    ctx.fill();
                    //35
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('35', Math.cos(45 / 4 * Math.PI / 180) * textRadius * 0.8, -Math.sin(45 / 4 * Math.PI / 180) *
                        textRadius * 1.4);
                    ctx.fill();
                    //40
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(12);
                    ctx.fillText('40', Math.cos(45 / 4 * Math.PI / 180) * textRadius * 0.85, Math.sin(45 / 4 * Math.PI / 180) *
                        textRadius);
                    ctx.fill();
                    
                                    //画中心的图标
                    const imgWidth = radius * 0.6; //图标的宽
                    ctx.beginPath();
                    ctx.drawImage('../../static/su.png', -imgWidth / 2, -imgWidth / 2, imgWidth, imgWidth);
                    ctx.stroke();
    
                                    //画图标下的提示字符串
                    const txtStr = '定时运动';
                    ctx.beginPath();
                    ctx.setFillStyle('white');
                    ctx.setFontSize(15);
                    const txtWidth = ctx.measureText(txtStr).width;
                    ctx.fillText(txtStr, -txtWidth / 2, radius * 0.45);
                    ctx.fill();
    
                    setTimeout(() => {//需要做延迟处理才能够渲染出来
                        ctx.draw();
                    }, 50)
                }
            }
        }
    </script>
    
    <style>
        page {
            background: #00a8ff;
            padding-top: 100rpx;
        }
    
        .content {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: #00a8ff;
            margin: auto;
        }
    </style>
    

    相关文章

      网友评论

          本文标题:uni-app使用canvas绘制时间刻度以及不显示问题处理

          本文链接:https://www.haomeiwen.com/subject/cbrxddtx.html