1、餅圖繪制
2、如何添加動(dòng)畫效果
3、使用rollup構(gòu)建項(xiàng)目
關(guān)注我的 github 項(xiàng)目 查看完整代碼。
很久沒更新了,最近事情比較多,今天來把坑填上!
先看一下API

下面開始(使用ES6語法編寫,后面我們可以是用rollup編譯成ES5的語法)
假設(shè)我們有這樣的數(shù)據(jù)
const series = [
{data: 15, color: '#7cb5ec'},
{data: 35, color: '#f7a35c'},
{data: 78, color: '#434348'},
{data: 63, color: '#90ed7d'}
];
計(jì)算出各項(xiàng)所占的比例和開始的弧度
calPieData.js
export function calPieAngle (series) {
// 計(jì)算數(shù)據(jù)總和
let count = 0;
series.forEach((item) => {
count += item.data;
});
// 計(jì)算出開始的弧度和所占比例
let startAngle = 0;
return series.map((item) => {
item.proportion = item.data / count;
item.startAngle = startAngle;
startAngle += 2 * Math.PI * item.proportion;
return item;
});
}
數(shù)據(jù)已經(jīng)計(jì)算出來了,下面讓我開始繪制吧
drawPieChart.js
import { calPieAngle } from 'calPieData'
export default function drawPieChart (series) {
...
let pieSeries = calPieAngle(series);
pieSeries.forEach((item) => {
context.beginPath();
// 設(shè)置填充顏色
context.setFillStyle(item.color);
// 移動(dòng)到原點(diǎn)
context.moveTo(100, 100);
// 繪制弧度
context.arc(100, 100, 80, item.startAngle, item.startAngle + 2 * Math.PI * item.proportion);
context.closePath();
context.fill();
});
...
}
調(diào)用drawPieChart(series)就可以得到下面的結(jié)果:

很簡單是不是,下面我們給各區(qū)塊加上一個(gè)白色的分割線
因?yàn)閍rc實(shí)際上是繪制了一條路徑,所以我們簡單的stroke描邊一下就可以了
...
context.setLineWidth(2);
context.setStrokeStyle('#ffffff');
pieSeries.forEach((item) => {
context.beginPath();
context.setFillStyle(item.color);
context.moveTo(100, 100);
context.arc(100, 100, 80, item.startAngle, item.startAngle + 2 * Math.PI * item.proportion);
context.closePath();
context.fill();
context.stroke();
})
...

首先讓我們創(chuàng)建一個(gè)動(dòng)畫工具,這個(gè)動(dòng)畫工具能夠傳入一些自定義的參數(shù),比如動(dòng)畫時(shí)間,能夠有動(dòng)畫每一步的回調(diào)以及動(dòng)畫結(jié)束的回調(diào)
animation.js
export default function Animation (opts) {
// 處理用戶傳入的動(dòng)畫時(shí)間,默認(rèn)為1000ms
// 因?yàn)橛脩粲锌赡軅魅雂uration為0,所以不能用opts.duration = opts.duration || 1000 來做默認(rèn)值處理
// 否則用戶傳入0也會處理成默認(rèn)值1000
opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
let startTimeStamp = null;
function step (timestamp) {
if (startTimeStamp === null) {
startTimeStamp = timestamp;
}
if (timestamp - startTimeStamp < opts.duration) {
// 計(jì)算出動(dòng)畫的進(jìn)度
let process = (timestamp - startTimeStamp) / opts.duration;
// 觸發(fā)動(dòng)畫每一步的回調(diào),傳入進(jìn)度process
opts.onProcess && opts.onProcess(process);
// 動(dòng)畫進(jìn)行中,執(zhí)行下一次動(dòng)畫
requestAnimationFrame(step);
} else {
// 動(dòng)畫結(jié)束
opts.onProcess && opts.onProcess(1);
// 觸發(fā)動(dòng)畫結(jié)束回調(diào)
opts.onAnimationFinish && opts.onAnimationFinish();
}
}
requestAnimationFrame(step);
}
動(dòng)畫使用了requestAnimationFrame,并且已經(jīng)滿足了我們上面定義的需求
在實(shí)戰(zhàn)中,此處的動(dòng)畫都是線性的,一般我們還會加入緩動(dòng)選項(xiàng),比如緩入,緩出,還有一點(diǎn),在微信小程序真機(jī)中IOS設(shè)備是不支持requestAnimationFrame的,所以要做降級處理,使用setTimeout,查看完整的代碼
下面我們調(diào)用animation來完成動(dòng)畫效果
app.js
import Animation from 'animation'
import drawPieChart from 'drawPieChart'
Animation({
duration: 1000,
onProcess: (process) => {
drawPieDataChart(series, process);
}
});
修改一下drawPieDataChart function,能夠接受process參數(shù)
...
export default function drawPieChart (series, process = 1) {
...
// 將process傳入給calPieAngle,計(jì)算出對應(yīng)進(jìn)度下的圖表角度數(shù)據(jù)
let pieSeries = calPieAngle(series, process);
...
同樣,修改一下calPieAngle function,能夠接受process參數(shù)
export function calPieAngle (series, process = 1) {
...
// 計(jì)算出開始的弧度和所占比例
let startAngle = 0;
return series.map((item) => {
// 計(jì)算出當(dāng)前動(dòng)畫進(jìn)度的比例
item.proportion = item.data / count * process;
item.startAngle = startAngle;
startAngle += 2 * Math.PI * item.proportion;
return item;
});
}
好了,現(xiàn)在我們的動(dòng)畫就可以動(dòng)起來了,類似這樣

Rollup is a next-generation JavaScript module bundler. Author your app or library using ES2015 modules, then efficiently bundle them up into a single file for use in browsers and Node.js.
也就是說rollup是一個(gè)前端構(gòu)建工具,能夠?qū)⑽覀兊恼麄€(gè)項(xiàng)目合并輸出成一個(gè)最終的編譯結(jié)果,上面我們編寫代碼的時(shí)候都是按照不同的功能放到不同的文件中,這樣有利于后期的可持續(xù)性開發(fā)和維護(hù),rollup正好能幫助我們構(gòu)建出最后的編譯結(jié)果
先安裝rollup
npm install -g rollup
添加對ES6的支持
npm install --save-dev rollup-plugin-babel npm install --save-dev babel-preset-es2015-rollup
創(chuàng)建.babelrc文件在項(xiàng)目根目錄,告訴babel轉(zhuǎn)義時(shí)使用哪個(gè)presets
{
"presets": ["es2015-rollup"],
}
好了剩下最后一步,定義我們的rollup.config.js配置文件
import babel from 'rollup-plugin-babel';
export default {
// 入口文件
entry: 'app.js',
// 輸出格式,這里使用commonJS
format: 'cjs',
// 輸出文件
dest: 'dist/charts.js',
// 使用babel進(jìn)行ES6轉(zhuǎn)ES5
plugins: [
babel({
exclude: 'node_modules/**',
})
]
};
rollup會從入口文件開始,查找我們的依賴(import),逐級往下深入,把依賴的文件全部收集起來并合并到一起,最后輸出到我們定義的dest文件中
執(zhí)行
rollup -c
好了,我們就得到了我們最后的項(xiàng)目編譯文件charts.js
下一期中我一起討論下有技術(shù)含量的內(nèi)容,關(guān)于圖表中文案顯示的檢測碰撞問題,大概效果會是這樣的,紅框部分文案發(fā)生了碰撞,這里完成了避讓,能夠正常顯示
