径向渐变
function computedPieRadialGradient(array) {
const total = array.reduce((v1, v2) => v1 + v2.value, 0);
array.reduce((v1, v2) => {
v2.theta1 = v1;
v2.theta2 = Number((total != 0 ? v1 + v2.value / total : v1 + 1 / array.length).toFixed(2));
return v2.theta2;
}, 0);
function calc(info) {
let theta1 = info.theta1 * 2 * Math.PI;
let theta2 = info.theta2 * 2 * Math.PI;
let r = 0.5;
let inner = info.radius == undefined ? 0 : info.radius;
let bottom = 0;
let left = 2 * r;
let right = 0;
let y0 = r * (1 - Math.cos(theta1));
let y1 = r * (1 - Math.cos(theta2));
let _y0 = r * (1 - inner * Math.cos(theta1));
let _y1 = r * (1 - inner * Math.cos(theta2));
if (theta1 < Math.PI && theta2 > Math.PI) {
bottom = 2 * r;
}
let ymin = Math.min(_y0, _y1, y0, y1);
let ymax = Math.max(_y0, _y1, y0, y1, bottom);
let x0 = r * (1 + Math.sin(theta1));
let x1 = r * (1 + Math.sin(theta2));
let _x0 = r * (1 + inner * Math.sin(theta1));
let _x1 = r * (1 + inner * Math.sin(theta2));
if (theta1 < Math.PI / 2 && theta2 > Math.PI / 2) {
right = 2 * r;
}
if (theta1 < (Math.PI / 2) * 3 && theta2 > (Math.PI / 2) * 3) {
left = 0;
}
let xmin = Math.min(_x0, _x1, x0, x1, left);
let xmax = Math.max(_x0, _x1, x1, x0, right);
info.position = {
x: (r - xmin) / (xmax - xmin),
y: (r - ymin) / (ymax - ymin),
r: r / Math.min(xmax - xmin, ymax - ymin)
};
return info;
}
let startIndex = -1;
return array.map((item, index) => {
if (total != 0 && item.value == 0 && startIndex < 0) {
item.position = {};
return item;
}
startIndex = index;
return calc(item);
});
}
线性渐变
function computedPieLinearGradient(array) {
const total = array.reduce((v1, v2) => v1 + v2.value, 0);
array.reduce((v1, v2) => {
v2.theta1 = v1;
v2.theta2 = Number(
(total != 0 ? v1 + v2.value / total : v1 + 1 / array.length).toFixed(2)
);
return v2.theta2;
}, 0);
function calc(dx, dy) {
const tanV = dx / dy;
const directSign = Math.abs(tanV) < 1;
const t = directSign ? tanV : 1 / tanV;
const sign1 = t > 0 ? 1 : -1;
const sign2 = dx > 0 ? 1 : -1;
const sign = directSign ? sign1 * sign2 : sign2;
const group1 = [0.5 - (sign * t) / 2, 0.5 + (sign * t) / 2];
const group2 = sign > 0 ? [0, 1] : [1, 0];
const group = [...group1, ...group2];
const keys = directSign ? ["x", "x2", "y", "y2"] : ["y", "y2", "x", "x2"];
let res = {};
keys.forEach((k, idx) => {
res[k] = group[idx];
});
return res;
}
array.map((item) => {
const startArc = item.theta1 * 360 * (Math.PI / 180);
const endArc = item.theta2 * 360 * (Math.PI / 180);
const posi = [
Math.sin(startArc),
-Math.cos(startArc),
Math.sin(endArc),
-Math.cos(endArc)
];
const dx = posi[2] - posi[0];
const dy = posi[3] - posi[1];
item.position = calc(dx, dy);
return item;
});
return array;
}