中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

canvas怎么實現2d環形統計圖

發布時間:2023-04-18 17:37:26 來源:億速云 閱讀:99 作者:iii 欄目:開發技術

這篇文章主要介紹了canvas怎么實現2d環形統計圖的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇canvas怎么實現2d環形統計圖文章都會有所收獲,下面我們一起來看看吧。

    先看看效果

    canvas怎么實現2d環形統計圖

    中間得環形圖以及里面的文字就是通過 canvas 2d 繪制出來的,下面看代碼。

    看看代碼

    • WXML

    <view class="row chart-container">
        <canvas type="2d" class="chart" id="myChart2d" />
        <view class="col center">
            <view class="row-center" wx:for="{{chartData}}" wx:key="chartData" >
                <view class="circle" ></view>
                <view class="project-item font-size-12 flex1 row">
                    <view>{{item.title}}</view>
                    <view class="flex1 margin-left-16"> {{item.numb}}</view>
                    <view class="margin-left-16"> {{item.percent}}%</view>
                </view>
            </view>
        </view>
    </view>

    這里并不需要多少代碼,但是 type 和 id 一定要,而且記得 class 指定寬高。

    • WXSS

    .chart {
        width: 112px;
        height: 112px;
    }
    .row{
      display:flex; 
      flex-direction:row;
    }
    .col{
      display:flex; 
      flex-direction:column;
    }
    .row-center{
      display:flex; 
      flex-direction:row;
      align-items: center;
    }
    .flex1{
      flex: 1;
    }
    .center{
      margin: auto;
      width: fit-content;
    }
    .circle {
        width: 18rpx;
        height: 18rpx;
        border-radius: 9rpx;
        box-sizing: border-box;
    }
    .project-item {
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #616161;
        line-height: 34rpx;
        margin-left: 8rpx;
    }
    .margin-left-16{
      margin-left: 16rpx;
    }
    .font-size-12{
      font-size: 24rpx;
    }

    這里就是上面說的指定寬高了,暫時先用 px 作為單位,其他不知道會不會有問題。

    • JS

    Component({
    	properties: {
            show: {
                type: Boolean,
                value: false,
                observer: function (newVal, oldVal) {
                    // 首次進來頁面圖標無法加載,監聽頁面切換來顯示
                    let isFirstComeIn = this.data.isFirstComeIn
                    if (isFirstComeIn) {
                        this.getCanvas()
                        this.data.isFirstComeIn = false
                    }
                }
            }
        },
        lifetimes: {
            attached: function () {
            	// 初始化加載數據
                this.getData()
            },
        },
        data: {
            // 畫布相關
            isFirstComeIn: true,
            context: null,
            height: 0,
            width: 0,
            // 圖表數據
            chartData: [{
                title: '待檢查項目',
                color: '#FF9000',
                numb: 0,
                percent: 0
            }, {
                title: '進行中項目',
                color: '#1FD55C',
                numb: 0,
                percent: 0
            }, {
                title: '已完成項目',
                color: '#0B7BFB',
                numb: 0,
                percent: 0
            }, {
                title: '已終止項目',
                color: '#616161',
                numb: 0,
                percent: 0
            }],
        }
        methods: {
        	getCanvas() {
                // 有的手機下拉刷新會造成畫兩個不同大小的餅圖
                let that = this;
                let query = wx.createSelectorQuery().in(this)
                query.select('#myChart2d')
                    .fields({
                        node: true,
                        size: true
                    })
                    .exec((res) => {
                        const canvas = res[0].node
                        const ctx = canvas.getContext('2d')
                        const dpr = wx.getSystemInfoSync().pixelRatio
                        canvas.width = res[0].width * dpr
                        canvas.height = res[0].height * dpr
                        ctx.scale(dpr, dpr)
                        that.setData({
                            width: res[0].width * dpr,
                            height: res[0].height * dpr,
                            context: ctx
                        })
                        // 首次進來畫圖
                        that.drawPieChart2d()
                })
            },
            // 下拉刷新
            onPullDownRefresh() {
                this.getData()
            },
            // 獲取數據
            getData() {
            	app.request({
                    url: 'you/url',
                    data: {},
                    finish: function () {
                        wx.stopPullDownRefresh();
                    },
                    success: function (res) {
                    	let count = res.undoCount + res.doingCount + res.finishCount + res.stopCount
                        let chartData = that.data.chartData
                        if (count != 0) {
                            chartData[0].numb = res.undoCount
                            chartData[0].percent = (res.undoCount * 100 / count).toFixed(2)
                            chartData[1].numb = res.doingCount
                            chartData[1].percent = (res.doingCount * 100 / count).toFixed(2)
                            chartData[2].numb = res.finishCount
                            chartData[2].percent = (res.finishCount * 100 / count).toFixed(2)
                            chartData[3].numb = res.stopCount
                            chartData[3].percent = (res.stopCount * 100 / count).toFixed(2)
                        } else {
                            chartData[0].numb = 0
                            chartData[0].percent = 0
                            chartData[1].numb = 0
                            chartData[1].percent = 0
                            chartData[2].numb = 0
                            chartData[2].percent = 0
                            chartData[3].numb = 0
                            chartData[3].percent = 0
                        }
                        that.setData({
                            chartData: chartData,
                        })
                        // 因為本頁作為組件隱藏了,首次進來無法獲取canvas高度,首次進來另外處理
                        if (!that.data.isFirstComeIn) {
                            that.drawPieChart2d()
                        }
                    }
                })    
            }
    		// 一次性使用,前面是舊 canvas,注釋的是一次性調用 canvas 2d 代碼
    		drawPieChart() {
                // 組件中使用需要增加 this
                const ctx = wx.createCanvasContext('myChart', this);
                //設置半徑 
                let radius = 56;
                let center = {
                    x: 56,
                    y: 56
                };
                // 設置數據、總數
                let data = this.data.chartData
                let count = 0;
                data.forEach(element => {
                    count += element.numb
                });
                for (let i = 0; i < data.length; i++) {
                    //計算占比,總長為 2PI
                    let start = 0;
                    for (let j = 0; j < i; j++) {
                        start += data[j].numb / count * 2 * Math.PI
                    }
                    var end = start + data[i].numb / count * 2 * Math.PI
                    ctx.beginPath()
                    ctx.arc(center.x, center.y, radius, start, end)
                    ctx.setLineWidth(1)
                    ctx.lineTo(center.x, center.y)
                    ctx.setStrokeStyle('#fff')
                    ctx.setFillStyle(data[i].color)
                    ctx.fill();
                    ctx.closePath();
                    ctx.stroke();
                }
                ctx.beginPath()
                radius = 40;
                ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI)
                ctx.setFillStyle('#fafafa')
                ctx.fill()
                ctx.closePath();
                ctx.stroke();
                ctx.fillStyle = "#2E2E2E";
                ctx.setFontSize(20)
                ctx.setTextAlign('center')
                ctx.fillText('' + count, 56, 50);
                ctx.setFontSize(14)
                ctx.setTextAlign('center')
                ctx.fillText('評估項目數', 56, 70);;
                ctx.draw()
                // let query = wx.createSelectorQuery().in(this)
                // query.select('#myChart2d')
                //     .fields({
                //         node: true,
                //         size: true
                //     })
                //     .exec((res) => {
                //         const canvas = res[0].node
                //         const ctx = canvas.getContext('2d')
                //         const dpr = wx.getSystemInfoSync().pixelRatio
                //         canvas.width = res[0].width * dpr
                //         canvas.height = res[0].height * dpr
                //         ctx.scale(dpr, dpr)
                //         //設置半徑 
                //         let radius = 56;
                //         let center = {
                //             x: 56,
                //             y: 56
                //         };
                //         // 設置數據、總數
                //         let data = this.data.chartData
                //         let count = 0;
                //         data.forEach(element => {
                //             count += element.numb
                //         });
                //         // 開始畫圖
                //         ctx.clearRect(0, 0, res[0].width * dpr, res[0].height * dpr)
                //         for (let i = 0; i < data.length; i++) {
                //             //計算占比,總長為 2PI
                //             let start = 0;
                //             for (let j = 0; j < i; j++) {
                //                 start += data[j].numb / count * 2 * Math.PI
                //             }
                //             var end = start + data[i].numb / count * 2 * Math.PI
                //             ctx.beginPath()
                //             ctx.arc(center.x, center.y, radius, start, end)
                //             ctx.lineWidth = 1
                //             ctx.lineTo(center.x, center.y)
                //             ctx.strokeStyle = '#fff'
                //             ctx.fillStyle = data[i].color
                //             ctx.closePath();
                //             ctx.fill();
                //         }
                //         radius = 40;
                //         ctx.beginPath()
                //         ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI)
                //         ctx.fillStyle = '#fafafa'
                //         ctx.closePath()
                //         ctx.fill()
                //         ctx.fillStyle = "#2E2E2E";
                //         ctx.font = "20px Arial";
                //         ctx.textAlign = 'center'
                //         ctx.fillText('' + count, 56, 50)
                //         ctx.font = "14px Arial";
                //         ctx.fillText('評估項目數', 56, 70)
                //     })
            },
            drawPieChart2d() {
                let ctx = this.data.context
                //設置半徑 
                let radius = 56;
                let center = {
                    x: 56,
                    y: 56
                };
                // 設置數據、總數
                let data = this.data.chartData
                let count = 0;
                data.forEach(element => {
                    count += element.numb
                });
                // 開始畫圖
                ctx.beginPath()
                ctx.clearRect(0, 0, this.data.width, this.data.height);
                for (let i = 0; i < data.length; i++) {
                    //計算占比,總長為 2PI
                    let start = 0;
                    for (let j = 0; j < i; j++) {
                        start += data[j].numb / count * 2 * Math.PI
                    }
                    var end = start + data[i].numb / count * 2 * Math.PI
                    ctx.beginPath()
                    ctx.lineWidth = 1
                    ctx.strokeStyle = '#fff'
                    ctx.fillStyle = data[i].color
                    ctx.arc(center.x, center.y, radius, start, end)
                    ctx.lineTo(center.x, center.y)
                    ctx.closePath();
                    ctx.fill();
                }
                radius = 40;
                ctx.beginPath()
                ctx.fillStyle = '#fafafa'
                ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI)
                ctx.closePath()
                ctx.fill()
                ctx.fillStyle = "#2E2E2E";
                ctx.font = "20px Arial";
                ctx.textAlign = 'center'
                ctx.fillText('' + count, 56, 50)
                ctx.font = "14px Arial";
                ctx.fillText('評估項目數', 56, 70)
            },
        } 
    })

    這里寫的有些復雜了,但是復雜的東西能學到的也多吧,在組件中使用都掌握了,在 Page 中使用那就得心應手了,下面詳細講講。

    繪制圖表

    實際上繪制圖表并不需要這么多的代碼,在Page也好,在組件頁面也好,其實只需要在需要繪制的時候調用上面 js 中 drawPieChart 代碼即可,前面是舊版本的canvas,后面注釋的是 canvas 2d的寫法,可以對比看看,還是有些去別的,特別是字體大小坑了我一把。

    但是為什么要寫這么多代碼呢?還是解決一些出現的問題,下面詳細介紹。

    解決問題

    • 下拉刷新會造成畫兩個不同大小的餅圖

    問題很奇怪,而且只在某些機型出現。仔細研究一下發現這個問題是因為繪制圖表的時候,多次調用一次性生成圖表函數造成的,即每次獲取到的 canvas 對象可能不太一樣了,具體什么不一樣了,我就沒有仔細研究了,可能是頁面發生了變化造成的。

    這里的解決辦法就是只獲取一次 canvas,后面就用它不停的繪制圖表,當繪需要制新的圖表時,清空原來內容并繪制。首先提取出一個函數獲取 canvas,這個函數要在 page 的 onReady中監聽,這里再組件中也可以在 lifetimes 的 ready 方法中監聽,都是一樣的。獲取到 canvas 對象后設置為全局變量,后面繪制的的時候取這個變量繪制就可以了。

    這里我們把 getCanvas 寫在了組件頁面第一次顯示時觸發,原因看下面問題。

    • 首次進來頁面圖表無法加載

    這個問題是我們自定義的底部導航欄引入的,因為組件頁面的出現后就被設置成了隱藏狀態,所以 canvas 并沒有獲得到寬高,導致圖表不顯示。

    解決辦法就是在組件頁面第一次顯示的時候觸發 getCanvas 函數,這里監聽 show 屬性的寫法可以參考我前面自定義底部導航欄的博客,就不詳述了。第一次顯示的問題,用到了一個全局變量,一旦觸發了,這個變量就永久設置為 false,使 getCanvas 函數不會再次執行。

    同時,在第一次獲取數據時因為 canvas 未獲取到,應該暫時不繪制圖表,當第一次進入頁面后,拿到 canvas 對象了,再進行繪制。后面在拉取數據,例如下拉刷新,因為 canvas 已經獲取到了,就不用特殊處理了。

    getCanvas() {
    	...
    	// 首次進來畫圖
    	that.drawPieChart2d()
    }
    getData() {
        ...
        // 因為本頁作為組件隱藏了,首次進來無法獲取canvas高度,首次進來另外處理
    	if (!that.data.isFirstComeIn) {
        	that.drawPieChart2d()
    	}
    }
    • 圖表數據處理

    這里還碰到一個很奇怪的問題,就是我一開始把數據的百分比算成四位小數,在頁面綁定的時候乘上100加上百分號再顯示,按理來說應該顯示小數點后兩位的百分比值,可實際卻是取小數點后兩位并不生效,小數點后面取了十幾位,可能時在頁面計算的時候出了問題。所以這里最好在 JS 中算好值,保留小數點后幾位,再進行數據綁定。計算的時候,分母不為零千萬別忘了。

    關于“canvas怎么實現2d環形統計圖”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“canvas怎么實現2d環形統計圖”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    花莲县| 兴义市| 黎川县| 玛曲县| 肃北| 文登市| 曲靖市| 中山市| 岳西县| 河曲县| 鹤庆县| 鹰潭市| 房山区| 米林县| 奉化市| 高台县| 五指山市| 应城市| 亚东县| 体育| 肥城市| 巴东县| 甘孜县| 阳江市| 江门市| 泸州市| 永嘉县| 玉环县| 岳西县| 丹东市| 阜平县| 视频| 荃湾区| 昌吉市| 华阴市| 通江县| 嘉祥县| 漳平市| 专栏| 万载县| 临夏市|