Skip to content

Commit 558acc1

Browse files
author
杨骥
committed
优化饼图性能
1 parent bafb0f9 commit 558acc1

3 files changed

Lines changed: 6146 additions & 16 deletions

File tree

src/chart/pie/PieSeries.ts

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import createSeriesDataSimply from '../helper/createSeriesDataSimply';
2121
import * as zrUtil from 'zrender/src/core/util';
2222
import * as modelUtil from '../../util/model';
23-
import { getPercentWithPrecision } from '../../util/number';
23+
import { getPercentSeats } from '../../util/number';
2424
import { makeSeriesEncodeForNameBased } from '../../data/helper/sourceHelper';
2525
import LegendVisualProvider from '../../visual/LegendVisualProvider';
2626
import SeriesModel from '../../model/Series';
@@ -133,6 +133,8 @@ class PieSeriesModel extends SeriesModel<PieSeriesOption> {
133133

134134
static type = 'series.pie' as const;
135135

136+
seats: number[];
137+
136138
/**
137139
* @overwrite
138140
*/
@@ -159,31 +161,25 @@ class PieSeriesModel extends SeriesModel<PieSeriesOption> {
159161
* @overwrite
160162
*/
161163
getInitialData(this: PieSeriesModel): SeriesData {
162-
return createSeriesDataSimply(this, {
164+
const data = createSeriesDataSimply(this, {
163165
coordDimensions: ['value'],
164166
encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
165167
});
168+
const valueList:number[] = [];
169+
data.each(data.mapDimension('value'), function (value: number) {
170+
valueList.push(value);
171+
});
172+
173+
this.seats = getPercentSeats(valueList, data.hostModel.get('percentPrecision'));
174+
return data;
166175
}
167176

168177
/**
169178
* @overwrite
170179
*/
171180
getDataParams(dataIndex: number): PieCallbackDataParams {
172-
const data = this.getData();
173181
const params = super.getDataParams(dataIndex) as PieCallbackDataParams;
174-
// FIXME toFixed?
175-
176-
const valueList: number[] = [];
177-
data.each(data.mapDimension('value'), function (value: number) {
178-
valueList.push(value);
179-
});
180-
181-
params.percent = getPercentWithPrecision(
182-
valueList,
183-
dataIndex,
184-
data.hostModel.get('percentPrecision')
185-
);
186-
182+
params.percent = this.seats[dataIndex] / 100;
187183
params.$vars.push('percent');
188184
return params;
189185
}

src/util/number.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,63 @@ export function getPercentWithPrecision(valueList: number[], idx: number, precis
279279
return seats[idx] / digits;
280280
}
281281

282+
/**
283+
* Get a data of given precision, assuring the sum of percentages
284+
* in valueList is 1.
285+
* The largest remainer method is used.
286+
* https://en.wikipedia.org/wiki/Largest_remainder_method
287+
*
288+
* @param valueList a list of all data
289+
* @param precision integer number showing digits of precision
290+
* @return {Array<number>} percent ranging from 0 to 100
291+
*/
292+
export function getPercentSeats(valueList: number[], precision: number): number[] {
293+
const sum = zrUtil.reduce(valueList, function (acc, val) {
294+
return acc + (isNaN(val) ? 0 : val);
295+
}, 0);
296+
if (sum === 0) {
297+
return [];
298+
}
299+
300+
const digits = Math.pow(10, precision);
301+
const votesPerQuota = zrUtil.map(valueList, function (val) {
302+
return (isNaN(val) ? 0 : val) / sum * digits * 100;
303+
});
304+
const targetSeats = digits * 100;
305+
306+
const seats = zrUtil.map(votesPerQuota, function (votes) {
307+
// Assign automatic seats.
308+
return Math.floor(votes);
309+
});
310+
let currentSum = zrUtil.reduce(seats, function (acc, val) {
311+
return acc + val;
312+
}, 0);
313+
314+
const remainder = zrUtil.map(votesPerQuota, function (votes, idx) {
315+
return votes - seats[idx];
316+
});
317+
318+
// Has remainding votes.
319+
while (currentSum < targetSeats) {
320+
// Find next largest remainder.
321+
let max = Number.NEGATIVE_INFINITY;
322+
let maxId = null;
323+
for (let i = 0, len = remainder.length; i < len; ++i) {
324+
if (remainder[i] > max) {
325+
max = remainder[i];
326+
maxId = i;
327+
}
328+
}
329+
330+
// Add a vote to max remainder.
331+
++seats[maxId];
332+
remainder[maxId] = 0;
333+
++currentSum;
334+
}
335+
336+
return seats;
337+
}
338+
282339
/**
283340
* Solve the floating point adding problem like 0.1 + 0.2 === 0.30000000000000004
284341
* See <http://0.30000000000000004.com/>

0 commit comments

Comments
 (0)