@antv/g2
Version: 
the Grammar of Graphics in Javascript
161 lines • 5.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOrigin = exports.getTransform = exports.toOpacityKey = exports.getConnectStyle = exports.getArcObject = exports.reorder = exports.computeGradient = exports.appendArc = exports.arrowPoints = exports.appendPolygon = exports.applyStyle = void 0;
const scale_1 = require("@antv/scale");
const util_1 = require("@antv/util");
const d3_array_1 = require("d3-array");
const array_1 = require("../utils/array");
const coordinate_1 = require("../utils/coordinate");
const vector_1 = require("../utils/vector");
function applyStyle(selection, style) {
    for (const [key, value] of Object.entries(style)) {
        selection.style(key, value);
    }
}
exports.applyStyle = applyStyle;
/**
 * Draw polygon path with points.
 * @param path
 * @param points
 */
function appendPolygon(path, points) {
    points.forEach((p, idx) => idx === 0 ? path.moveTo(p[0], p[1]) : path.lineTo(p[0], p[1]));
    path.closePath();
    return path;
}
exports.appendPolygon = appendPolygon;
/**
 * Draw arrow between `from` and `to`.
 * @param from
 * @param to
 * @returns
 */
function arrowPoints(from, to, options) {
    const { arrowSize } = options;
    const size = typeof arrowSize === 'string'
        ? (+parseFloat(arrowSize) / 100) * (0, vector_1.dist)(from, to)
        : arrowSize;
    // TODO Use config from style.
    // Default arrow rotate is 30°.
    const arrowAngle = Math.PI / 6;
    const angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
    const arrowAngle1 = Math.PI / 2 - angle - arrowAngle;
    const arrow1 = [
        to[0] - size * Math.sin(arrowAngle1),
        to[1] - size * Math.cos(arrowAngle1),
    ];
    const arrowAngle2 = angle - arrowAngle;
    const arrow2 = [
        to[0] - size * Math.cos(arrowAngle2),
        to[1] - size * Math.sin(arrowAngle2),
    ];
    return [arrow1, arrow2];
}
exports.arrowPoints = arrowPoints;
/**
 * Draw arc by from -> to, with center and radius.
 * @param path
 * @param from
 * @param to
 * @param center
 * @param radius
 */
function appendArc(path, from, to, center, radius) {
    const startAngle = (0, vector_1.angle)((0, vector_1.sub)(center, from)) + Math.PI;
    const endAngle = (0, vector_1.angle)((0, vector_1.sub)(center, to)) + Math.PI;
    path.arc(center[0], center[1], radius, startAngle, endAngle, endAngle - startAngle < 0);
    return path;
}
exports.appendArc = appendArc;
/**
 * @todo Fix wrong key point.
 */
function computeGradient(C, X, Y, from = 'y', mode = 'between') {
    const P = from === 'y' || from === true ? Y : X;
    const theta = from === 'y' || from === true ? 90 : 0;
    const I = (0, array_1.indexOf)(P);
    const [min, max] = (0, d3_array_1.extent)(I, (i) => P[i]);
    // This need to improve for non-uniform distributed colors.
    const p = new scale_1.Linear({
        domain: [min, max],
        range: [0, 100],
    });
    const percentage = (i) => p.map(P[i]);
    const gradientMode = {
        // Interpolate the colors for this segment.
        between: (i) => `${C[i]} ${percentage(i)}%`,
        // Use the color of the start point as the color for this segment.
        start: (i) => i === 0
            ? `${C[i]} ${percentage(i)}%`
            : `${C[i - 1]} ${percentage(i)}%, ${C[i]} ${percentage(i)}%`,
        // Use the color of the end point as the color for this segment.
        end: (i) => i === C.length - 1
            ? `${C[i]} ${percentage(i)}%`
            : `${C[i]} ${percentage(i)}%, ${C[i + 1]} ${percentage(i)}%`,
    };
    const gradient = I.sort((a, b) => percentage(a) - percentage(b))
        .map(gradientMode[mode] || gradientMode['between'])
        .join(',');
    return `linear-gradient(${theta}deg, ${gradient})`;
}
exports.computeGradient = computeGradient;
function reorder(points) {
    const [p0, p1, p2, p3] = points;
    return [p3, p0, p1, p2];
}
exports.reorder = reorder;
function getArcObject(coordinate, points, Y) {
    const [p0, p1, , p3] = (0, coordinate_1.isTranspose)(coordinate) ? reorder(points) : points;
    const [y, y1] = Y;
    const center = coordinate.getCenter();
    const a1 = (0, vector_1.angleWithQuadrant)((0, vector_1.sub)(p0, center));
    const a2 = (0, vector_1.angleWithQuadrant)((0, vector_1.sub)(p1, center));
    // There are two situations that a2 === a1:
    // 1. a1 - a2 = 0
    // 2. |a1 - a2| = Math.PI * 2
    // Distinguish them by y and y1:
    const a3 = a2 === a1 && y !== y1 ? a2 + Math.PI * 2 : a2;
    return {
        startAngle: a1,
        endAngle: a3 - a1 >= 0 ? a3 : Math.PI * 2 + a3,
        innerRadius: (0, vector_1.dist)(p3, center),
        outerRadius: (0, vector_1.dist)(p0, center),
    };
}
exports.getArcObject = getArcObject;
/**
 * Pick connectStyle from style.
 * @param style
 */
function getConnectStyle(style) {
    const PREFIX = 'connect';
    return Object.fromEntries(Object.entries(style)
        .filter(([key]) => key.startsWith(PREFIX))
        .map(([key, value]) => [
        (0, util_1.lowerFirst)(key.replace(PREFIX, '').trim()),
        value,
    ])
        .filter(([key]) => key !== undefined));
}
exports.getConnectStyle = getConnectStyle;
function toOpacityKey(options) {
    const { colorAttribute, opacityAttribute = colorAttribute } = options;
    return `${opacityAttribute}Opacity`;
}
exports.toOpacityKey = toOpacityKey;
function getTransform(coordinate, value) {
    if (!(0, coordinate_1.isPolar)(coordinate))
        return '';
    const center = coordinate.getCenter();
    const { transform: suffix } = value;
    return `translate(${center[0]}, ${center[1]}) ${suffix || ''}`;
}
exports.getTransform = getTransform;
function getOrigin(points) {
    if (points.length === 1)
        return points[0];
    const [[x0, y0, z0 = 0], [x2, y2, z2 = 0]] = points;
    return [(x0 + x2) / 2, (y0 + y2) / 2, (z0 + z2) / 2];
}
exports.getOrigin = getOrigin;
//# sourceMappingURL=utils.js.map