天天看點

canvas畫弧形漸變進度條

需求:在swiper輪播圖中做出如圖的弧形進度條,輪播的會員等級分别為白銀、黃金、鉑金、鑽石;

以下代碼會先展示一個弧形圖的代碼,之後會展示輪播圖中的弧形進度條代碼

單個弧形圖:

canvas畫弧形漸變進度條

代碼

<view>
    <block>
        <view class='canvasBox' id = "canvasBox">
            <canvas canvas-id="bgcanvas1"  id="bgcanvas1" class='canvas'></canvas>
            <canvas canvas-id="runCanvas1"  id="runCanvas1" class='canvas'></canvas>
        </view>
    </block>
</view>
           

js

const app = getApp();
Component({
    /**
     * 元件的屬性清單
     */
    properties: {
        nowLevel:{
            type: Number,
            value: 0,
            observer(nv, ov, path) {
                if(nv){

                }
            }
        },
        levelList:{
            type: Array,
            observer(levelList, ov, path) {
                // this.drawerbg("bgcanvas1",this.data.swiCurrent);// 擷取節點資訊
            }
        },
        swiCurrent:{
            type: Number,
            value: 0,
            observer(nv, ov, path) {
            }
        },
        cardIndex: {
            type: Number,
            value: 0,
            observer(nv, ov, path) {
            }
        }
    },

    /**
     * 元件的初始資料
     */
    data: {
        // levelMembershipVo: {},
        // loginState: app.globalData.loginState,
        // levelList: app.globalData.levelList,
        // gradeMember: app.globalData.gradeMember,
        nowNum: 0,
        canvasWidth: 0,
        canvasHeight: 0
    },
    pageLifetimes: {
        show: function() {
            // 頁面被展示
            
        },
    },
    lifetimes: {
        ready: function(){
            this.drawerbg("bgcanvas1",700,1000,0);// /參數(id,目前值,階段最高值,階段最低值)
            this.runCanvas1("runCanvas1",700,1000,0) //參數(id,目前值,階段最高值,階段最低值)
        }
    },
    observers: {
    },
    /**
     * 元件的方法清單
     */
    methods: {
       
        drawerbg(id,now,end,start){
            let that = this;
            let ctx = wx.createCanvasContext(id,this);
            const grd = ctx.createLinearGradient(20, 20, 300,300)
            let topBorder;
            let bottomBorder;
            let textColor;
            let botText;
                grd.addColorStop(0.3, '#FF863D')//深
                grd.addColorStop(0.42, '#FFF14B')
                topBorder="#D29C54"
                bottomBorder="#6D490B"
                textColor="#A4825D"
                botText="黃金會員"
            wx.createSelectorQuery().in(this).select('#'+id).boundingClientRect(function (rect) { //監聽canvas的寬高
                var w = parseInt(rect.width / 2); //擷取canvas寬的的一半
                var h = parseInt(rect.height  / 2); //擷取canvas高的一半,
                that.setData({
                    canvasWidth: rect.width,
                    canvasHeight: rect.height
                });
                //   arc(圓心x軸,圓心y軸,半徑機關像素,起始角度弧度制從x軸正方向開始,結束角度弧度制,true表示逆時針繪制)
                ctx.arc(2*w/3*2, 2*h/3*1.8, 2*h/3*2.3, 0.833 * Math.PI, 1.35 * Math.PI,false );  //繪制圓形弧線 1.24
                ctx.setStrokeStyle("#ffffff");
                ctx.setLineWidth("2");     //設定線條寬度
                ctx.setLineCap("round");        //設定線條端點樣式
                ctx.stroke();     //對路徑進行描邊,也就是繪制線條。

                ctx.closePath();
                    if(now < start){
                        //繪制下面黃色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.62, 2*h/3*2.54,0.025*w,0,Math.PI*2,true); 
                        ctx.fillStyle=bottomBorder; 
                        ctx.closePath(); 
                        ctx.fill(); 
                        //繪制下面白色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.62, 2*h/3*2.54,0.012*w,0,Math.PI*2,true); 
                        ctx.fillStyle="#FFFFFF"; 
                        ctx.closePath(); 
                        ctx.fill();
                    }
                    if(now === start || now < start){
                        //繪制上面黃色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.025*w,0,Math.PI*2,true); 
                        ctx.fillStyle=topBorder; 
                        ctx.closePath(); 
                        ctx.fill(); 
                        //繪制上面白色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.012*w,0,Math.PI*2,true); 
                        ctx.fillStyle="#FFFFFF"; 
                        ctx.closePath(); 
                        ctx.fill();
                    }
                    ctx.fillStyle=textColor; 
                    // ctx.textAlign="right";
                    ctx.font="10px 微軟雅黑";
                    ctx.textAlign="center";
                    ctx.fillText("鉑金會員",w*0.84,2*h/3*0.7);
                    ctx.font="9px 微軟雅黑";
                    ctx.fillText(end,w*0.84,2*h/3*0.95);
                    ctx.font="10px 微軟雅黑";
                    ctx.fillText(botText,w*0.78,h*1.53);
                    ctx.font="9px 微軟雅黑";
                    ctx.fillText(start,w*0.78,h*1.7);
                    ctx.font="10px 微軟雅黑";
                    ctx.fillText("目前成長值",w*0.77,h*1);
                    ctx.font="9px 微軟雅黑";
                    ctx.fillText(now,w*0.77,h*1.15);
                ctx.draw();       //開始繪制
            }).exec();
        },
        runCanvas1(id,now,end,start){
            let that = this;
            let ctx = wx.createCanvasContext(id,this);
            const grd = ctx.createLinearGradient(20, 20, 300,300)
            let topBorder;
            let bottomBorder;
            grd.addColorStop(0.3, '#FF863D')//深
            grd.addColorStop(0.42, '#FFF14B')
            topBorder="#D29C54"
            bottomBorder="#6D490B"
           
            wx.createSelectorQuery().in(this).select('#'+id).boundingClientRect(function (rect) { //監聽canvas的寬高
                let percent = (( now - start ) / ( end - start ));
                if( percent < 0 || Object.is(percent,NaN) ){
                    percent = 0
                }
                var num =( 0.239 * percent + 0.9 ) //0.239由最高成長的弧度值1.139-最低成長的弧度值0.9
                if((now > 0 || now > start) && (now < end )){
                    num = num;
                }else if((now > 0 && (now > end)) || (now > 0 && (now === end))){
                    num = 1.139;
                }else if(now < 0 || now < start){
                    num = 0.9;
                }
                var w = parseInt(rect.width / 2); //擷取canvas寬的的一半
                var h = parseInt(rect.height  / 2); //擷取canvas高的一半,
                //   arc(圓心x軸,圓心y軸,半徑機關像素,起始角度弧度制從x軸正方向開始,結束角度弧度制,true表示逆時針繪制)
                ctx.arc(2*w/3*2, 2*h/3*1.8, 2*h/3*2.3, 0.833 * Math.PI, num * Math.PI,false );  //繪制圓形弧線
                ctx.setLineWidth("4");     //設定線條寬度
                ctx.setLineCap("round");        //設定線條端點樣式
                ctx.strokeStyle = grd;
                ctx.stroke();     //對路徑進行描邊,也就是繪制線條。
                if(now === start || now > start){
                    //繪制下面黃色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.025*w,0,Math.PI*2,true); 
                    ctx.fillStyle=bottomBorder; 
                    ctx.closePath(); 
                    ctx.fill(); 
                    //繪制下面白色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.012*w,0,Math.PI*2,true); 
                    ctx.fillStyle="#FFFFFF"; 
                    ctx.closePath(); 
                    ctx.fill();
                }
                if(now > start){
                    //繪制上面黃色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.67, 2*h/3*0.73,0.025*w,0,Math.PI*2,true); 
                    ctx.fillStyle=topBorder; 
                    ctx.closePath(); 
                    ctx.fill(); 
                    //繪制上面白色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.67, 2*h/3*0.73,0.012*w,0,Math.PI*2,true); 
                    ctx.fillStyle="#FFFFFF"; 
                    ctx.closePath(); 
                    ctx.fill();
                }
                ctx.draw();       //開始繪制
            }).exec();
        },
    }
})

           

輪播圖中的弧形圖:

html

<view>
    <block>
        <view class='canvasBox' id = "canvasBox">
            <canvas canvas-id="bgcanvas1"  id="bgcanvas1" class='canvas'></canvas>
            <block wx:if="{{ swiCurrent === nowNum }}">
                <canvas canvas-id="runCanvas1"  id="runCanvas1" class='canvas'></canvas>
            </block>
        </view>
    </block>
</view>
           

js

const app = getApp();
Component({
    /**
     * 元件的屬性清單
     */
    properties: {
        swiCurrent:{ //目前swiper所在的索引
            type: Number,
            value: 1,
            observer(nv, ov, path) {
            }
        },
    },

    /**
     * 元件的初始資料
     */
    data: {
        // levelMembershipVo: {},
        // loginState: app.globalData.loginState,
        levelList: [
            {
                id:5,
                name:"白銀會員",
                levelMinGrowthValue:0,
                levelMaxGrowthValue:1000
            },
            {
                id:6,
                name:"黃金會員",
                levelMinGrowthValue:1001,
                levelMaxGrowthValue:6000
            },
            {
                id:7,
                name:"鉑金會員",
                levelMinGrowthValue:6001,
                levelMaxGrowthValue:15000
            },
            {
                id:8,
                name:"鑽石會員",
                levelMinGrowthValue:15001,
                levelMaxGrowthValue:null
            }
        ],
        // gradeMember: app.globalData.gradeMember,
        nowNum: 1, //目前的等級
        canvasWidth: 0,
        canvasHeight: 0
    },
    pageLifetimes: {
        show: function() {
            // 頁面被展示
            
        },
    },
    lifetimes: {
        // attached: async function () {
        //     this.setData({
        //         levelMembershipVo: app.globalData.levelMembershipVo,
        //         gradeMember: app.globalData.gradeMember,
        //         nowNum: this.checkNumber(app.globalData.gradeMember)
        //     });
        // },
        ready: function(){
            console.log("swiCurrent",this.data.swiCurrent)
            this.drawerbg("bgcanvas1",this.data.swiCurrent,500);// 參數(id,目前的swiCurrent,目前值)
            this.runCanvas1("runCanvas1",500,1000,0,this.data.swiCurrent) //(id,目前值,階段最高值,階段最低值,目前的swiCurrent)
        }
    },
    observers: {
    },
    /**
     * 元件的方法清單
     */
    methods: {
       
        drawerbg(id,currenLevel,now){
            let that = this;
            let ctx = wx.createCanvasContext(id,this);
            const grd = ctx.createLinearGradient(20, 20, 300,300)
            let topBorder;
            let bottomBorder;
            let textColor;
            let botText;
            if(currenLevel===0){//白銀會員
                grd.addColorStop(0.3, '#DDDEDE')
                grd.addColorStop(0.52, '#DDDEDE')
                topBorder="#B2B2B2"
                bottomBorder="#000000"
                textColor="#888888"
                botText="白銀會員"
            }else if(currenLevel===1){//黃金會員
                grd.addColorStop(0.3, '#FF863D')//深
                grd.addColorStop(0.42, '#FFF14B')
                topBorder="#D29C54"
                bottomBorder="#6D490B"
                textColor="#A4825D"
                botText="黃金會員"
            }else if(currenLevel===2){//鉑金會員
                grd.addColorStop(0.3, '#3660A7')
                grd.addColorStop(0.42, '#84BAE5')
                topBorder="#7295E5"
                bottomBorder="#295283"
                textColor="#5F6B91"
                botText="鉑金會員"
            }else if(currenLevel===3){//鑽石會員
                grd.addColorStop(0.3, '#8A53C8')
                grd.addColorStop(0.42, '#A08FE7')
                topBorder="#A97CE5"
                bottomBorder="#381B6B"
                textColor="#75639B"
                botText="鑽石會員"
            }
            wx.createSelectorQuery().in(this).select('#'+id).boundingClientRect(function (rect) { //監聽canvas的寬高
                var w = parseInt(rect.width / 2); //擷取canvas寬的的一半
                var h = parseInt(rect.height  / 2); //擷取canvas高的一半,
                that.setData({
                    canvasWidth: rect.width,
                    canvasHeight: rect.height
                });
                //   arc(圓心x軸,圓心y軸,半徑機關像素,起始角度弧度制從x軸正方向開始,結束角度弧度制,true表示逆時針繪制)
                ctx.arc(2*w/3*2, 2*h/3*1.8, 2*h/3*2.3, 0.833 * Math.PI, 1.35 * Math.PI,false );  //繪制圓形弧線 1.24
                ctx.setStrokeStyle("#ffffff");
                ctx.setLineWidth("2");     //設定線條寬度
                ctx.setLineCap("round");        //設定線條端點樣式
                ctx.stroke();     //對路徑進行描邊,也就是繪制線條。

                
                ctx.closePath();
                    let levelMaxGrowthValue = ( that.data.levelList[that.data.swiCurrent].levelMaxGrowthValue  || 0) + 1
                    let levelMinGrowthValue= that.data.levelList[that.data.swiCurrent].levelMinGrowthValue || 0
                if(now === levelMinGrowthValue || now > levelMinGrowthValue){
                
                    //繪制下面黃色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.025*w,0,Math.PI*2,true); 
                    ctx.fillStyle=bottomBorder; 
                    ctx.closePath(); 
                    ctx.fill(); 
                    //繪制下面白色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.012*w,0,Math.PI*2,true); 
                    ctx.fillStyle="#FFFFFF"; 
                    ctx.closePath(); 
                    ctx.fill();
                }

                    if( that.data.swiCurrent !== 3 && (now === levelMinGrowthValue || now < levelMinGrowthValue)){
                        //繪制上面黃色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.025*w,0,Math.PI*2,true); 
                        ctx.fillStyle=topBorder; 
                        ctx.closePath(); 
                        ctx.fill(); 
                        //繪制上面白色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.012*w,0,Math.PI*2,true); 
                        ctx.fillStyle="#FFFFFF"; 
                        ctx.closePath(); 
                        ctx.fill();
                    }
                    ctx.fillStyle=textColor; 
                    // ctx.textAlign="right";
                    ctx.font="10px 微軟雅黑";

                    // ctx.fillText("目前",w*0.5,h*1.25);
                    // ctx.fillText(now,w*0.5,h*1.45);

                    ctx.textAlign="center";
                    if( that.data.swiCurrent ===3 ){
                        levelMaxGrowthValue = 25000
                    }
                    if( that.data.swiCurrent !==3 ){
                        if(currenLevel===0){//白銀會員
                            ctx.fillText("黃金會員",w*0.84,2*h/3*0.7);
                        }else if(currenLevel===1){//黃金會員
                            ctx.fillText("鉑金會員",w*0.84,2*h/3*0.7);
                        }else if(currenLevel===2){//鉑金會員
                            ctx.fillText("鑽石會員",w*0.84,2*h/3*0.7);
                        }
                        ctx.font="9px 微軟雅黑";
                        ctx.fillText(levelMaxGrowthValue,w*0.84,2*h/3*0.95);
                    }
                    ctx.font="10px 微軟雅黑";
                    ctx.fillText(botText,w*0.78,h*1.53);
                    ctx.font="9px 微軟雅黑";
                    ctx.fillText(levelMinGrowthValue,w*0.78,h*1.7);
                    if(that.data.swiCurrent === that.data.nowNum && now){
                        ctx.font="10px 微軟雅黑";
                        ctx.fillText("目前成長值",w*0.77,h*1);
                        ctx.font="9px 微軟雅黑";
                        ctx.fillText(now,w*0.77,h*1.15);
                    }
                ctx.draw();       //開始繪制
            }).exec();
        },
        runCanvas1(id,now,end,start,currenLevel){
            let that = this;
            let ctx = wx.createCanvasContext(id,this);
            const grd = ctx.createLinearGradient(20, 20, 300,300)
            let topBorder;
            let bottomBorder;
            if(currenLevel===0){//白銀會員
                grd.addColorStop(0.3, '#DDDEDE')
                grd.addColorStop(0.52, '#DDDEDE')
                topBorder="#B2B2B2"
                bottomBorder="#000000"
            }else if(currenLevel===1){//黃金會員
                grd.addColorStop(0.3, '#FF863D')//深
                grd.addColorStop(0.42, '#FFF14B')
                topBorder="#D29C54"
                bottomBorder="#6D490B"
            }else if(currenLevel===2){//鉑金會員
                grd.addColorStop(0.3, '#3660A7')
                grd.addColorStop(0.42, '#84BAE5')
                topBorder="#7295E5"
                bottomBorder="#295283"
            }else if(currenLevel===3){//鑽石會員
                grd.addColorStop(0.3, '#8A53C8')
                grd.addColorStop(0.42, '#A08FE7')
                topBorder="#A97CE5"
                bottomBorder="#381B6B"
            }
            wx.createSelectorQuery().in(this).select('#'+id).boundingClientRect(function (rect) { //監聽canvas的寬高
              
                let percent = (( now - start ) / ( end - start ));
                if( percent < 0 || Object.is(percent,NaN) ){
                    percent = 0
                }
                console.log("percent===",percent)
                var num =( 0.239 * percent + 0.9 ) //0.23由最高成長的弧度值1.12-最低成長的弧度值0.9
                // var num =1.15
             
                if( currenLevel === 3 ){
                    end = 25000;
                }
                console.log("end",end)
                if((now > 0 || now > start) && (now < end )){
                    num = num;
                }else if((now > 0 && (now > end)) || (now > 0 && (now === end))){
                    num = 1.139;
                }else if(now < 0 || now < start){
                    num = 0.9;
                }
                console.log("num",num)
                var w = parseInt(rect.width / 2); //擷取canvas寬的的一半
                var h = parseInt(rect.height  / 2); //擷取canvas高的一半,
                //   arc(圓心x軸,圓心y軸,半徑機關像素,起始角度弧度制從x軸正方向開始,結束角度弧度制,true表示逆時針繪制)
                ctx.arc(2*w/3*2, 2*h/3*1.8, 2*h/3*2.3, 0.833 * Math.PI, num * Math.PI,false );  //繪制圓形弧線
                ctx.setLineWidth("4");     //設定線條寬度
                ctx.setLineCap("round");        //設定線條端點樣式
                ctx.strokeStyle = grd;
                ctx.stroke();     //對路徑進行描邊,也就是繪制線條。
                if( that.data.swiCurrent === that.data.nowNum || that.data.cardIndex !== 1){
                    //繪制下面黃色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.025*w,0,Math.PI*2,true); 
                    ctx.fillStyle=bottomBorder; 
                    ctx.closePath(); 
                    ctx.fill(); 
                    //繪制下面白色小圓 
                    ctx.beginPath(); 
                    ctx.arc(w*0.62, 2*h/3*2.54,0.012*w,0,Math.PI*2,true); 
                    ctx.fillStyle="#FFFFFF"; 
                    ctx.closePath(); 
                    ctx.fill();
                    if( that.data.swiCurrent !== 3 ){
                        //繪制上面黃色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.025*w,0,Math.PI*2,true); 
                        ctx.fillStyle=topBorder; 
                        ctx.closePath(); 
                        ctx.fill(); 
                        //繪制上面白色小圓 
                        ctx.beginPath(); 
                        ctx.arc(w*0.67, 2*h/3*0.73,0.012*w,0,Math.PI*2,true); 
                        ctx.fillStyle="#FFFFFF"; 
                        ctx.closePath(); 
                        ctx.fill();
                    }
                }
                ctx.draw();       //開始繪制
            }).exec();
        },
    }
})

           

繼續閱讀