ECharts实现饼图径向渐变、线性渐变坐标计算

径向渐变

/**
 * 计算 饼图径向渐变 X,Y,R坐标
 * @param {*} array 数据 {value:0,radius:0}格式,radius 设置内径
 * @returns 返回 坐标信息{position:{x:0.5,y:0.5,r:0.5}}
 */
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));

        //开始角度小于90,结束角度大于90
        if (theta1 < Math.PI / 2 && theta2 > Math.PI / 2) {
            right = 2 * r;
        }

        //开始角度小于270,结束角度大于270
        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);
    });
}


线性渐变

/**
 * 计算 饼图线性渐变 X,Y,R坐标
 * @param {*} array 数据 {value:0}格式
 * @returns 返回 坐标信息{position:{x:0.5,y:0.5,x2:0.5,y2:0.5}}
 */
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;
}

你可能感兴趣的:(SOLUTION,echarts,javascript,前端)