校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > Canvas環形餅圖與手勢控制的實現代碼

Canvas環形餅圖與手勢控制的實現代碼

熱門標簽:如何查看地圖標注 黃石ai電銷機器人呼叫中心 惡搞電話機器人 電話機器人技術 智能電銷機器人被禁用了么 地圖標注軟件打印出來 ok電銷機器人 欣鼎電銷機器人 效果 高德地圖標注商戶怎么標

首先上一下效果圖:

左右的箭頭和下方的標注以及環形圖本身都可以控制環形圖的選中狀態。

首先講一下思路:

布局很簡單,我就不寫了,主要講下作圖過程。

首先跟圖需求可以知道,作出這樣的效果需要一組對象,每個對象有顏色,所占比例,名字等,也就是這樣:

let chartData=[
{color:"#FD7A4F",title:"其他",percent:0.2},
{color:"#FDD764",title:"建筑/土木工程",percent:0.25},
***
]

注意百分比加在一起必須是100%,也就是1,否則圓環可能不會畫滿,或者多處一部分。

根據每部分所占比例計算出每個部分所占的弧度,使用ctx.arc(x0, y0,r, startAngle, endAngle);畫出圓弧,當前項需要向外偏移一些,過程中具體上代碼講這部分:

首先定義一個multiCircleChart類,

//ES6寫法
class multiCircleChart {
   constructor(id, chartDatas, defalutIndex,callback) {
    /*構造函數:
    傳入的參數ID,canvas的id,用于放置繪畫內容;
    chartDatas:畫圖所需參數數據;
    defalutIndex:defalutIndex:當前選中項
    callback:點擊環形圖的回調函數
    */
        this.canvas = document.getElementById(id);
        this.size = this.canvas.parentNode.clientWidth * 4;
        this.canvas.style.width = this.size / 4 + "px";
        this.canvas.style.height = this.size / 4 + "px";
        this.canvas.width = this.size;
        this.canvas.height = this.size;
        /*
        因為在移動端畫圖需要多倍圖,這樣圖像會很清晰,所以這里size,也就是canvas的context設置為canvas大小的4倍;
        注意:!??!canvas.width指的是畫布內容(context)的大小,cavas.style.width是canvas在頁面上顯示的大小,也就是說,真是的圖片是顯示圖片大小的4倍
        */
       
        this.ctx = this.canvas.getContext("2d");
        this.defalutIndex = defalutIndex;//當前選中項
        this.chartDatas = chartDatas;//繪制所需數據
        this.lineWidth = this.size/5;//環形圖的圓環寬度,設置為canvas寬度的1/5;
        this.startAngle = -0.5;//環形圖起始角度,這里為-0.5,計算時也就是-0.5*Math.PI,放在坐標系中也就是環形圖最高點那個位置的角度;順便說一下,右側為0,下方為0.5,左側為1
        this.callback=callback;
        this.canvas.addEventListener('click',this.mouseDownEvent.bind(this));
        /*給canvas添加監聽函數,并將事件傳遞過去,用于計算點擊位置在哪個數據項里*/
        this.AngleList=[];//記錄每一項的結束角度,結合監聽事件,計算點擊事件的位置在哪個數據項里
    }
}

構造函數寫好了,接下來需要畫環形圖了:

class multiCircleChart {
    ***
    draw() {
        this.ctx.clearRect(0,0,this.size,this.size);//每次繪畫前,先清空一下畫布,避免畫布被污染
        if (this.chartDatas.length == 0) return;//如果傳入的參數長度為0的話,也就不需要繼續畫了
        this.ctx.lineWidth = this.lineWidth;//為圓環寬度賦值
        let startAngle = Math.PI * -0.5;//設置起始角度
        let endAngle = startAngle;設置結束角度
        this.AngleList=[];
        /*下面就開始動筆畫圖了*/
        this.chartDatas.map((item, i) => {
            this.ctx.beginPath();//開始畫圖命令,避免粘連
            this.ctx.strokeStyle = item.color;//設置邊框顏色,因為我們畫的是圓環,所以填充色不需要,只要有邊框色就行了
            if (i > 0) {
                //從第二項開始(i==1)時,起始角度就是上一次的結束角度
                startAngle = endAngle;
            }
            endAngle = startAngle + item.percent * Math.PI * 2;//計算當前項的結束角度,根據所占的百分比計算所占角度(item.percent * Math.PI * 2),再結合起始角度就可以計算出真正的偏移角度了(startAngle + item.percent * Math.PI * 2)
            this.AngleList.push(endAngle);
            //選中當前項,需要向外偏移
            if (i == this.defalutIndex) {
                /*
                選中當前項,需要向外偏移
                使用起始角度和結束角度的中間值來就算偏移位置
                */
                let centerAngle=(startAngle+endAngle)/2;
                let x=this.lineWidth*0.2*Math.cos(centerAngle);//x軸偏移量
                let y=this.lineWidth*0.2*Math.sin(centerAngle);//y軸偏移量
                //未選中項的圓心位置是(this.size / 2, this.size / 2),選中的需要偏移,圓心是(this.size / 2+x, this.size / 2+y);這樣畫出的環形就會向外偏移環形寬度的1/5了;
                this.ctx.arc(this.size / 2+x, this.size / 2+y, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle);
            } else {
                this.ctx.arc(this.size / 2, this.size / 2, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle);
            }
            this.ctx.stroke();
        });
    }
}

現在所畫的圖是一個靜態的,點擊環形圖是不會有任何變化的,當然現在這樣也是可以用的

 let circlePeiChart = new multiCircleChart("circle-pei-chart",chartDatas,defalutIndex,);//new 一個
 circlePeiChart.draw();//畫圖

外部切換選中項

circlePeiChart.defalutIndex=2;//修改選中項Index值
 circlePeiChart.draw();//重繪

那么怎樣點擊canvas切換當前選項呢,思路很簡單:以canvas中心為圓心,監測點擊位置,點擊位置與圓心連成一線,以直角坐標系為參照,計算出點擊位置的弧度,跟angleList做比較,計算出點擊的是第幾項,然后修改defalutIndex,重繪canvas.

class multiCircleChart {
    ***
    ***
     mouseDownEvent(e){
        const [x1,y1]=[e.offsetX,e.offsetY];//點擊事件位置
        const [x0,y0]=[this.size/2/4,this.size/2/4];//原點位置;注意:原點位置為canvas中心,不是context中心
        let angle=0;
        if(x1>x0){
            //點擊位置在第一象限(y1>y0)或者第二象限(y1<y0)
            y1<y0?angle=-0.5*Math.PI+Math.atan((x1-x0)/(y0-y1)):angle=Math.atan((y1-y0)/(x1-x0));
        }else{
            //點擊位置在第三象限(y1<y0)或者第四象限(y1>y0)
            y1<y0?angle=Math.PI+Math.atan((y0-y1)/(x0-x1)):angle=Math.atan((x0-x1)/(y1-y0))+Math.PI*0.5;
        }
        for(let i=0;i<this.AngleList.length;i++){//計算角度落在第幾項
            if(angle<this.AngleList[i]){
            //當點擊位置角度值第一次大于某一項時,也就是說點擊位置就在這一項上
                this.defalutIndex=i;//重新賦值defaultIndex
                this.draw();//重繪canvas
                this.callback?this.callback(i):'';//如果有回調函數,則調用毀掉函數
                break;//跳出循環,結束操作;
            }
        }
    }
}

最后把整體代碼貼上吧

//html
<canvas id="circle-pei-chart"></canvas>
//調用
let chartDatas=[ {color: "rgb(253, 122, 79)",title: "后端開發",percent: 0.2}, **];
let defalutIndex=0
let circlePeiChart = new multiCircleChart("circle-pei-chart",chartDatas, defalutIndex,(i)=>{defalutIndex=i});
circlePeiChart.draw();
//重繪
circlePeiChart.defaultIndex=2;
circlePeiChart.draw();
/*
chartDatas [ {color: "rgb(253, 122, 79)",title: "后端開發",percent: 0.2}, **];
*/
class multiCircleChart {
    constructor(id, chartDatas, defalutIndex,callback) {
        this.canvas = document.getElementById(id);
        this.size = this.canvas.parentNode.clientWidth * 4;
        this.canvas.style.width = this.size / 4 + "px";
        this.canvas.style.height = this.size / 4 + "px";
        this.canvas.width = this.size;
        this.canvas.height = this.size;
        this.ctx = this.canvas.getContext("2d");
        this.defalutIndex = defalutIndex;
        this.chartDatas = chartDatas;
        this.lineWidth = this.size/5;
        this.startAngle = -0.5;
        this.callback=callback;
        this.canvas.addEventListener('click',this.mouseDownEvent.bind(this));
        this.AngleList=[];
    }
    draw() {
        this.ctx.clearRect(0,0,this.size,this.size);
        if (this.chartDatas.length == 0) return;
        this.ctx.lineWidth = this.lineWidth;
        this.ctx.lineCap="butt";
        let startAngle = Math.PI * -0.5;
        let endAngle = startAngle;
        this.AngleList=[];
        this.chartDatas.map((item, i) => {
            this.ctx.beginPath();
            this.ctx.strokeStyle = item.color;
            if (i > 0) {
                startAngle = endAngle;
            }
            endAngle = startAngle + item.percent * Math.PI * 2;
            this.AngleList.push(endAngle);
            //選中當前項,需要向外偏移
            if (i == this.defalutIndex) {
                //選中當前項,需要向外偏移
                let centerAngle=(startAngle+endAngle)/2;
                let x=this.lineWidth*0.2*Math.cos(centerAngle);
                let y=this.lineWidth*0.2*Math.sin(centerAngle);
                this.ctx.arc(this.size / 2+x, this.size / 2+y, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle);
            } else {
                this.ctx.arc(this.size / 2, this.size / 2, this.size / 2 - this.lineWidth / 2 - this.lineWidth * 0.2, startAngle, endAngle);
            }
            this.ctx.stroke();
        });
    }
    mouseDownEvent(e){
        const [x1,y1]=[e.offsetX,e.offsetY];
        const [x0,y0]=[this.size/2/4,this.size/2/4];
        let angle=0;
        if(x1>x0){
            y1<y0?angle=-0.5*Math.PI+Math.atan((x1-x0)/(y0-y1)):angle=Math.atan((y1-y0)/(x1-x0));
        }else{
            y1<y0?angle=Math.PI+Math.atan((y0-y1)/(x0-x1)):angle=Math.atan((x0-x1)/(y1-y0))+Math.PI*0.5;
        }
        for(let i=0;i<this.AngleList.length;i++){
            if(angle<this.AngleList[i]){
                this.defalutIndex=i;
                this.draw();
                this.callback?this.callback(i):'';
                break;
            }
        }
    }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

標簽:萍鄉 中山 金昌 阿壩 赤峰 盤錦 聊城 綏化

巨人網絡通訊聲明:本文標題《Canvas環形餅圖與手勢控制的實現代碼》,本文關鍵詞  Canvas,環形,餅圖,與,手勢,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Canvas環形餅圖與手勢控制的實現代碼》相關的同類信息!
  • 本頁收集關于Canvas環形餅圖與手勢控制的實現代碼的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    日本伦理一区二区| 久久伊99综合婷婷久久伊| 99精品久久免费看蜜臀剧情介绍| 国产在线国偷精品免费看| 激情综合亚洲精品| 久久99精品久久久久久动态图 | 亚洲激情综合网| 日韩一区中文字幕| 亚洲男同1069视频| 亚洲福利电影网| 日本美女一区二区| 久久99精品久久久久久动态图| 国产综合久久久久影院| 国产福利一区在线观看| 不卡的电影网站| 日本精品裸体写真集在线观看| 欧美日韩精品免费观看视频| 67194成人在线观看| 精品久久人人做人人爱| 国产日韩一级二级三级| 亚洲视频香蕉人妖| 亚洲福利一二三区| 久久av资源站| 国产99久久久国产精品潘金| 99久久久国产精品| 制服视频三区第一页精品| 555www色欧美视频| 久久综合成人精品亚洲另类欧美| 中文字幕乱码日本亚洲一区二区 | 国产精品自在在线| 懂色一区二区三区免费观看| 91日韩精品一区| 在线综合视频播放| 国产三区在线成人av| 亚洲美女淫视频| 蜜桃久久精品一区二区| 成人小视频在线| 欧美日韩国产高清一区| 2014亚洲片线观看视频免费| 国产精品污www在线观看| 亚洲第一激情av| 国产一区二区不卡在线| 一本一道综合狠狠老| 日韩一二三区不卡| 国产精品国产三级国产普通话蜜臀| 亚洲一区二区五区| 黄色成人免费在线| 一本色道久久加勒比精品| 欧美一卡2卡三卡4卡5免费| 国产精品久久久久影院老司| 亚洲成精国产精品女| 成人午夜视频福利| 777xxx欧美| 成人欧美一区二区三区白人| 青青草国产精品97视觉盛宴| www.在线成人| 欧美zozozo| 亚洲一区二区三区四区不卡| 国产精品亚洲午夜一区二区三区 | 欧美偷拍一区二区| 国产色91在线| 蜜臀91精品一区二区三区 | 欧美久久免费观看| 国产精品二三区| 国模大尺度一区二区三区| 一本色道久久综合亚洲91| 久久亚区不卡日本| 天天av天天翘天天综合网色鬼国产 | 17c精品麻豆一区二区免费| 久久精品国产第一区二区三区| 日本精品一区二区三区高清 | 秋霞影院一区二区| 91麻豆免费看片| 精品国产伦一区二区三区观看方式| 亚洲小说春色综合另类电影| 成人教育av在线| 久久人人爽爽爽人久久久| 日日夜夜精品视频免费| 欧美主播一区二区三区美女| 欧美激情综合在线| 精品一区二区三区在线观看国产 | 亚洲综合一区二区| 99在线视频精品| 国产日本欧洲亚洲| 另类的小说在线视频另类成人小视频在线| 欧洲一区二区三区免费视频| 国产精品九色蝌蚪自拍| 成人免费观看视频| 国产亚洲欧美日韩日本| 国产在线精品免费| 日韩久久久精品| 日本午夜精品视频在线观看| 欧美视频日韩视频在线观看| 一区二区三区欧美久久| 99久久er热在这里只有精品15| 国产清纯美女被跳蛋高潮一区二区久久w | 精品一区二区三区免费观看| 日韩三级av在线播放| 丝袜美腿高跟呻吟高潮一区| 欧美亚洲精品一区| 亚洲一区在线观看免费| 欧美日韩精品一区二区天天拍小说| 一二三区精品视频| 欧美综合视频在线观看| 亚洲午夜激情av| 欧美久久久一区| 美女国产一区二区| 精品久久久久久亚洲综合网| 国产麻豆视频精品| 中文字幕欧美区| 成人黄色网址在线观看| 中文字幕亚洲一区二区av在线| jlzzjlzz欧美大全| 伊人婷婷欧美激情| 欧美日韩一区二区三区四区| 亚洲成人午夜电影| 欧美一级黄色大片| 国产麻豆精品95视频| 国产精品日产欧美久久久久| 99久久精品国产网站| 亚洲午夜精品一区二区三区他趣| 欧美军同video69gay| 黑人巨大精品欧美一区| 国产精品免费久久| 日本精品视频一区二区| 日韩精品欧美成人高清一区二区| 欧美mv日韩mv| 国产99精品国产| 一二三四区精品视频| 欧美一级一区二区| 91色.com| 亚洲mv在线观看| 精品国产乱码久久久久久浪潮 | 91免费视频网| 五月婷婷综合网| 欧美videofree性高清杂交| 风间由美一区二区av101 | 国产成人免费在线观看不卡| √…a在线天堂一区| 欧美日韩成人一区| 精品一区二区三区蜜桃| 亚洲欧美在线视频观看| 欧美日本在线看| 国产91精品在线观看| 亚洲一区二区视频在线| 久久综合一区二区| 欧美性猛交xxxx乱大交退制版| 蜜桃视频一区二区三区| 国产精品高清亚洲| 日韩一级片在线观看| 波多野结衣欧美| 久久精品国产在热久久| 国产精品区一区二区三区| 欧美剧情电影在线观看完整版免费励志电影 | 精品国产制服丝袜高跟| 97aⅴ精品视频一二三区| 蜜桃精品在线观看| 亚洲免费在线观看视频| 欧美成人在线直播| 色哟哟在线观看一区二区三区| 精品在线观看免费| 亚洲高清在线视频| 国产日韩欧美麻豆| 欧美一区在线视频| 91麻豆自制传媒国产之光| 国产一区二区免费视频| 亚洲gay无套男同| 亚洲视频在线一区| 26uuu精品一区二区| 欧美三区在线视频| 99re亚洲国产精品| 国产乱子伦视频一区二区三区| 五月婷婷欧美视频| 亚洲丝袜制服诱惑| 26uuuu精品一区二区| 欧美久久久一区| 色综合久久天天综合网| 成人深夜在线观看| 精品一区二区在线视频| 日韩和欧美的一区| 亚洲免费观看高清完整版在线观看熊 | 久久综合久久综合九色| 在线成人高清不卡| 欧美色图天堂网| 色综合视频一区二区三区高清| 国产精品一区在线观看乱码 | 99久久精品国产导航| 国产69精品久久777的优势| 久久精品国产精品亚洲综合| 日韩精品免费视频人成| 一区二区三区日韩欧美| 亚洲欧美综合网| 中文字幕在线观看不卡视频| 欧美国产日韩精品免费观看| 久久久国产一区二区三区四区小说 | 91美女精品福利| 91香蕉国产在线观看软件| 成人性生交大合| 成人99免费视频| 懂色av一区二区三区免费看|