UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

64 lines (59 loc) 5.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.correlation = void 0; const vutils_1 = require("@visactor/vutils"), correlation_1 = require("../../constant/correlation"), resolveOptionValue = option => (0, vutils_1.isFunction)(option) ? option() : option, correlation = (data, options) => { var _a, _b, _c, _d, _e, _f, _g, _h; if (!data || !(null == options ? void 0 : options.view) || !(0, vutils_1.isArray)(data)) return data; const dataList = data, viewBox = options.view(); if (viewBox.x1 - viewBox.x0 == 0 || viewBox.y1 - viewBox.y0 == 0 || viewBox.x1 - viewBox.x0 == -1 / 0 || viewBox.x1 - viewBox.x0 == 1 / 0 || viewBox.y1 - viewBox.y0 == -1 / 0 || viewBox.y1 - viewBox.y0 == 1 / 0) return data; const startAngle = (0, vutils_1.degreeToRadian)(null !== (_a = resolveOptionValue(options.startAngle)) && void 0 !== _a ? _a : -90), endAngle = (0, vutils_1.degreeToRadian)(null !== (_b = resolveOptionValue(options.endAngle)) && void 0 !== _b ? _b : 270), maxRadius = Math.max((viewBox.x1 - viewBox.x0) / 2, (viewBox.y1 - viewBox.y0) / 2), innerRadius = (0, vutils_1.toPercent)(null !== (_c = resolveOptionValue(options.innerRadius)) && void 0 !== _c ? _c : 0, maxRadius), outerRadius = (0, vutils_1.toPercent)(resolveOptionValue(options.outerRadius), maxRadius), centerOption = resolveOptionValue(options.center), center = [ (0, vutils_1.isNumber)(null == centerOption ? void 0 : centerOption[0]) ? centerOption[0] : viewBox.x0 + (0, vutils_1.toPercent)(null !== (_d = null == centerOption ? void 0 : centerOption[0]) && void 0 !== _d ? _d : "50%", viewBox.x1 - viewBox.x0), (0, vutils_1.isNumber)(null == centerOption ? void 0 : centerOption[1]) ? centerOption[1] : viewBox.y0 + (0, vutils_1.toPercent)(null !== (_e = null == centerOption ? void 0 : centerOption[1]) && void 0 !== _e ? _e : "50%", viewBox.y1 - viewBox.y0) ], fieldAccessor = (0, vutils_1.field)(resolveOptionValue(options.field)), values = dataList.map(fieldAccessor), [min, max] = (0, vutils_1.extent)(values), radiusScale = min === max ? val => (innerRadius + outerRadius) / 2 : val => innerRadius + (outerRadius - innerRadius) * (val - min) / (max - min), radiusField = resolveOptionValue(options.radiusField), radiusRange = resolveOptionValue(options.radiusRange), sizeAccessor = (0, vutils_1.isNil)(radiusField) ? fieldAccessor : (0, vutils_1.field)(radiusField), defaultSize = null !== (_f = null == radiusRange ? void 0 : radiusRange[1]) && void 0 !== _f ? _f : 5; let sizeScale = datum => defaultSize; if (sizeAccessor) { const [minSize, maxSize] = sizeAccessor !== fieldAccessor ? (0, vutils_1.extent)(dataList.map(sizeAccessor)) : [ min, max ], minR = null !== (_g = null == radiusRange ? void 0 : radiusRange[0]) && void 0 !== _g ? _g : 5, maxR = null !== (_h = null == radiusRange ? void 0 : radiusRange[1]) && void 0 !== _h ? _h : 5; minSize !== maxSize && (sizeScale = datum => minR + (maxR - minR) * (sizeAccessor(datum) - minSize) / (maxSize - minSize)); } const minAngle = Math.min(startAngle, endAngle), maxAngle = Math.max(startAngle, endAngle), angles = getPartialAngles(minAngle, maxAngle, dataList.length), res = [], searchAngle = (maxAngle - minAngle) / 60; return dataList.forEach(((datum, index) => { const radius = radiusScale(values[index]), size = sizeScale(datum); let x, y, angle = angles[index]; for (let i = 0; i < 60 && (x = center[0] + radius * Math.cos(angle), y = center[1] + radius * Math.sin(angle), hasOverlap({ x: x, y: y, size: size }, res) || x - size < viewBox.x0 || x + size > viewBox.x1 || y - size < viewBox.y0 || y + size > viewBox.y1); i++) i < 59 && (angle += searchAngle, angle > maxAngle ? angle = minAngle : angle < minAngle && (angle = maxAngle)); res.push(Object.assign({ [correlation_1.CORRELATION_X]: x, [correlation_1.CORRELATION_Y]: y, [correlation_1.CORRELATION_SIZE]: size }, datum)); })), res; }; exports.correlation = correlation; const getPartialAngles = (minAngle, maxAngle, count) => { let offsetAngle = 0, stepCount = Math.max(Math.ceil(2 * (maxAngle - minAngle) / Math.PI), 2), stepAngle = (maxAngle - minAngle) / stepCount, stepIndex = 0, stepSign = 1, i = 0, j = 0; const res = []; let startAngle = minAngle; for (;i < count; ) j < stepCount && (res.push(startAngle + (j % 2 ? Math.floor(j / 2) + Math.floor(stepCount / 2) : j / 2) * stepAngle * stepSign), j++), i++, j === stepCount && (j = 0, stepIndex += 1, stepSign *= -1, 0 === offsetAngle ? offsetAngle = stepAngle / 2 : offsetAngle /= 2, startAngle = -1 === stepSign ? maxAngle - offsetAngle : minAngle + offsetAngle, stepIndex >= 2 && (stepAngle /= 2, stepCount *= 2)); return res; }, hasOverlap = (item, arr) => !(!arr || !arr.length) && arr.some((entry => { const x = entry.x, y = entry.y, size = entry.size; return Math.pow(item.x - x, 2) + Math.pow(item.y - y, 2) < Math.pow(item.size + size, 2); })); //# sourceMappingURL=correlation.js.map