From 2b66c21a8c10ce113eab72e0941951d53040419d Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Thu, 24 Oct 2024 09:56:36 +0200 Subject: [PATCH 01/19] feat: added radial axis --- package.json | 3 +- .../axis/axis-arc-label-node.js | 242 ++++++++++++++++++ .../chart-components/axis/axis-arc-node.js | 81 ++++++ .../axis/axis-arc-tick-node.js | 56 ++++ .../axis/axis-node-builder.js | 34 ++- 5 files changed, 410 insertions(+), 6 deletions(-) create mode 100644 packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js create mode 100644 packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js create mode 100644 packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js diff --git a/package.json b/package.json index 8bdfec8c4..6a8e494bb 100644 --- a/package.json +++ b/package.json @@ -72,5 +72,6 @@ "docs", "packages/*", "plugins/*" - ] + ], + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js new file mode 100644 index 000000000..28f9e129f --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -0,0 +1,242 @@ +import { rotate as rotateVector } from '../../math/vector'; + +function appendStyle(struct, buildOpts) { + ['fill', 'fontSize', 'fontFamily'].forEach((style) => { + struct[style] = buildOpts.style[style]; + }); +} + +function polarToCartesian(centerX, centerY, radius, angle) { + return { + x: centerX + radius * Math.cos(angle), + y: centerY + radius * Math.sin(angle), + }; +} + +function checkText(text) { + return typeof text === 'string' || typeof text === 'number' ? text : '-'; +} + +function clampEnds(struct, buildOpts) { + if (buildOpts.tilted || buildOpts.stepSize) { + return; + } + + if (buildOpts.align === 'top' || buildOpts.align === 'bottom') { + const leftBoundary = 0; + const rightBoundary = buildOpts.outerRect.width; + const textWidth = Math.min(buildOpts.maxWidth / 2, buildOpts.textRect.width / 2); + const leftTextBoundary = struct.x - textWidth; + const rightTextBoundary = struct.x + textWidth; + if (leftTextBoundary < leftBoundary) { + struct.anchor = 'start'; + struct.x = buildOpts.innerRect.x - buildOpts.outerRect.x; + } else if (rightTextBoundary > rightBoundary) { + struct.anchor = 'end'; + struct.x = buildOpts.innerRect.width + buildOpts.innerRect.x; + } + } else { + const topBoundary = 0; + const bottomBoundary = buildOpts.outerRect.height; + const textHeight = buildOpts.maxHeight / 2; + const topTextBoundary = struct.y - textHeight; + const bottomTextBoundary = struct.y + textHeight; + if (topTextBoundary < topBoundary) { + struct.y = buildOpts.innerRect.y - buildOpts.outerRect.y; + struct.baseline = 'text-before-edge'; + } else if (bottomTextBoundary > bottomBoundary) { + struct.y = buildOpts.innerRect.height + (buildOpts.innerRect.y - buildOpts.outerRect.y); + struct.baseline = 'text-after-edge'; + } + } +} + +function appendTilting(struct, buildOpts) { + if (buildOpts.tilted) { + const r = -buildOpts.angle; + const radians = r * (Math.PI / 180); + + if (buildOpts.align === 'bottom') { + struct.x -= (buildOpts.maxHeight * Math.sin(radians)) / 2; + struct.y -= buildOpts.maxHeight; + struct.y += (buildOpts.maxHeight * Math.cos(radians)) / 2; + } else { + struct.x -= (buildOpts.maxHeight * Math.sin(radians)) / 3; + } + + struct.transform = `rotate(${r}, ${struct.x}, ${struct.y})`; + struct.anchor = (buildOpts.align === 'bottom') === buildOpts.angle < 0 ? 'start' : 'end'; + + // adjustForEnds + const textWidth = Math.cos(radians) * buildOpts.maxWidth; + if ((buildOpts.align === 'bottom') === buildOpts.angle < 0) { + // right + const rightBoundary = buildOpts.outerRect.width - buildOpts.paddingEnd; + const rightTextBoundary = struct.x + textWidth; + if (rightTextBoundary > rightBoundary) { + struct.maxWidth = (rightBoundary - struct.x - 10) / Math.cos(radians); + } + } else { + // left + const leftBoundary = buildOpts.paddingEnd; + const leftTextBoundary = struct.x - textWidth; + if (leftTextBoundary < leftBoundary) { + struct.maxWidth = (struct.x - leftBoundary - 10) / Math.cos(radians); + } + } + } +} + +function bandwidthCollider(tick, struct, buildOpts) { + if (buildOpts.align === 'bottom' || buildOpts.align === 'top') { + const tickCenter = tick.position * buildOpts.innerRect.width; + const leftBoundary = tickCenter + (buildOpts.innerRect.x - buildOpts.outerRect.x - buildOpts.stepSize / 2); + struct.collider = { + type: 'rect', + x: leftBoundary, + y: 0, + width: leftBoundary < 0 ? buildOpts.stepSize + leftBoundary : buildOpts.stepSize, // Adjust collider so that it doesnt extend onto neighbor collider + height: buildOpts.innerRect.height, + }; + } else { + const tickCenter = tick.position * buildOpts.innerRect.height; + const topBoundary = tickCenter + (buildOpts.innerRect.y - buildOpts.outerRect.y - buildOpts.stepSize / 2); + struct.collider = { + type: 'rect', + x: 0, + y: topBoundary, + width: buildOpts.innerRect.width, + height: topBoundary < 0 ? buildOpts.stepSize + topBoundary : buildOpts.stepSize, // Adjust collider so that it doesnt extend onto neighbor collider + }; + } + + // Clip edges of the collider, should not extend beyoned the outerRect + const collider = struct.collider; + collider.x = Math.max(collider.x, 0); + collider.y = Math.max(collider.y, 0); + const widthClip = collider.x + collider.width - (buildOpts.outerRect.x + buildOpts.outerRect.width); + collider.width = widthClip > 0 ? collider.width - widthClip : collider.width; + const heightClip = collider.y + collider.height - (buildOpts.outerRect.y + buildOpts.outerRect.height); + collider.height = heightClip > 0 ? collider.height - heightClip : collider.height; +} + +function boundsCollider(tick, struct) { + struct.collider = { + type: 'polygon', + vertices: [ + { x: struct.boundingRect.x, y: struct.boundingRect.y }, + { x: struct.boundingRect.x + struct.boundingRect.width, y: struct.boundingRect.y }, + { x: struct.boundingRect.x + struct.boundingRect.width, y: struct.boundingRect.y + struct.boundingRect.height }, + { x: struct.boundingRect.x, y: struct.boundingRect.y + struct.boundingRect.height }, + ], + }; +} + +function tiltedCollider(tick, struct, buildOpts) { + const radians = buildOpts.angle * (Math.PI / 180); + const halfWidth = Math.max(buildOpts.stepSize / 2, struct.boundingRect.height / 2); // Handle if bandwidth is zero + const startAnchor = struct.anchor === 'start'; + const em = struct.anchor === 'end' && radians < 0; + const sp = struct.anchor === 'start' && radians >= 0; + const y = struct.boundingRect.y + (sp || em ? struct.boundingRect.height : 0); + // Generate starting points at bandwidth boundaries + const points = [ + { x: struct.x - halfWidth, y }, + { x: struct.x + halfWidth, y }, + ].map((p) => rotateVector(p, radians, { x: struct.x, y: struct.y })); // Rotate around center point to counteract labels rotation + + // Append points to wrap polygon around label + const margin = 10; // extend slightly to handle single char labels better + const leftPoint = { + x: startAnchor ? struct.boundingRect.x + struct.boundingRect.width + margin : struct.boundingRect.x - margin, + y: struct.boundingRect.y + struct.boundingRect.height, + }; + + const rightPoint = { + x: startAnchor ? struct.boundingRect.x + struct.boundingRect.width + margin : struct.boundingRect.x - margin, + y: struct.boundingRect.y, + }; + + const orderedPoints = radians >= 0 ? [leftPoint, rightPoint] : [rightPoint, leftPoint]; + points.push(...orderedPoints); + + struct.collider = { + type: 'polygon', + vertices: points, + }; +} + +function appendCollider(tick, struct, buildOpts) { + if (buildOpts.layered || !buildOpts.stepSize) { + boundsCollider(tick, struct); + } else if (buildOpts.tilted) { + tiltedCollider(tick, struct, buildOpts); + } else { + bandwidthCollider(tick, struct, buildOpts); + } +} + +function appendBounds(struct, buildOpts) { + struct.boundingRect = buildOpts.textBounds(struct); +} +export default function buildArcLabels(ticks, tick, idx, buildOpts) { + const rect = buildOpts.innerRect; + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const plotSize = Math.min(rect.height, rect.width) / 2; + + const innerRadius = plotSize * buildOpts.outerRadius; + const outerRadius = innerRadius + 1; + + const startAngle = buildOpts.startAngle || 0; // Start angle of the arc + const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc + + const tickLength = 6; + + const angleRange = endAngle - startAngle; + + // Generate labels + + const normalizedPosition = idx / (ticks.length - 1); + let angle = startAngle + normalizedPosition * angleRange; + let side; + if (angle < 0 && angle > -Math.PI) { + // Label should be on the left + side = 'left'; + } else if (angle > 0 && angle < Math.PI) { + side = 'right'; + } else { + side = 'center'; + } + angle -= Math.PI / 2; + const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength + 12.5, angle); + let textAnchor; + if (side === 'left') { + textAnchor = 'end'; // Align text to the right of the x-coordinate + } else if (side === 'right') { + textAnchor = 'start'; // Align text to the left of the x-coordinate + } else { + textAnchor = 'middle'; // Center align the text + } + // Add tick line to struct + const struct = { + type: 'text', + text: checkText(tick.label), + align: side, + fontSmooth: 'auto', + fontSize: 12, + padding: 50, + x: innerPos.x, + y: innerPos.y, + maxHeight: 16, + maxWidth: 89, + anchor: textAnchor, + baseline: 'middle', + }; + + appendStyle(struct, buildOpts); + clampEnds(struct, buildOpts); + appendTilting(struct, buildOpts); + appendBounds(struct, buildOpts); + appendCollider(tick, struct, buildOpts); + return struct; +} diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js new file mode 100644 index 000000000..7c5dec7a1 --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -0,0 +1,81 @@ +import extend from 'extend'; + +function appendStyle(struct, buildOpts) { + extend(struct, buildOpts.style); +} + +function polarToCartesian(centerX, centerY, radius, angle) { + return { + x: centerX + radius * Math.cos(angle), + y: centerY + radius * Math.sin(angle), + }; +} + +export default function buildArcLine(buildOpts) { + const rect = buildOpts.innerRect; + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const plotSize = Math.min(rect.height, rect.width) / 2; + + const innerRadius = plotSize * buildOpts.outerRadius; + const outerRadius = innerRadius + 1; + + const startAngle = buildOpts.startAngle || 0; // Start angle of the arc + const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc + + const numTicks = buildOpts.numTicks || 5; + const tickLength = 10; + const tickWidth = 2; + + const struct = { + visible: true, + type: 'path', + arc: 412.29, + arcDatum: { data: 412.29, value: 412.29, startAngle, endAngle }, // Arc data + transform: `translate(0, 0) translate(${centerPoint.cx}, ${centerPoint.cy})`, + desc: { + share: 1, + slice: { + cornerRadius: 0, + end: 6.283185307179586, + innerRadius, + offset: { x: 308, y: 207.5 }, + outerRadius, + }, + }, + innerRadius: 0.85, + outerRadius: 0.86, + ticks: [], + }; + const angleRange = endAngle - startAngle; + const angleStep = angleRange / numTicks; + + // Generate ticks + for (let i = 0; i <= numTicks; i++) { + const angle = startAngle + i * angleStep; + + // Calculate outer position for tick (on outer arc radius) + const outerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius, angle); + + // Calculate inner position for tick (closer to the arc center) + const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius - tickLength, angle); + + // Add tick line to struct + struct.ticks.push({ + type: 'line', + stroke: buildOpts.tickColor || '#000', // Default tick color or use from buildOpts + strokeWidth: tickWidth, + shape: { + x1: innerPos.x, + y1: innerPos.y, + x2: outerPos.x, + y2: outerPos.y, + }, + }); + } + + // Apply styles from buildOpts (optional, e.g., stroke, stroke-width) + appendStyle(struct, buildOpts); + + console.log('arc line', struct, buildOpts); + return struct; // Return the struct object containing the path definition +} diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js new file mode 100644 index 000000000..0fe1c42fe --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -0,0 +1,56 @@ +import extend from 'extend'; + +function appendStyle(struct, buildOpts) { + extend(struct, buildOpts.style); +} + +function polarToCartesian(centerX, centerY, radius, angle) { + return { + x: centerX + radius * Math.cos(angle), + y: centerY + radius * Math.sin(angle), + }; +} + +export default function buildArcTicks(ticks, buildOpts) { + const rect = buildOpts.innerRect; + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const plotSize = Math.min(rect.height, rect.width) / 2; + + const innerRadius = plotSize * buildOpts.outerRadius; + const outerRadius = innerRadius + 1; + + const startAngle = buildOpts.startAngle || 0; // Start angle of the arc + const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc + + const tickWidth = 1; + const tickLength = 6; + const struct = []; + const angleRange = endAngle - startAngle; + + // Generate ticks + ticks.forEach((tick, index) => { + const normalizedPosition = index / (ticks.length - 1); + let angle = startAngle + normalizedPosition * angleRange; + + angle -= Math.PI / 2; + const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength, angle); + + const outerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius, angle); + + // Add tick line to struct + struct.push({ + type: 'line', + stroke: buildOpts.tickColor || '#000', + strokeWidth: tickWidth, + padding: 5, + x1: innerPos.x, + y1: innerPos.y, + x2: outerPos.x, + y2: outerPos.y, + }); + }); + + // Apply styles from buildOpts (optional, e.g., stroke, stroke-width) + appendStyle(struct, buildOpts); + return struct; +} diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index 67c36b5bb..23b04bb3a 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -5,6 +5,9 @@ import { testRectRect } from '../../math/narrow-phase-collision'; import { getClampedValue } from './axis-label-size'; import getHorizontalContinuousWidth from './get-continuous-label-rect'; import { expandRect } from '../../geometry/util'; +import buildArcLine from './axis-arc-node'; +import buildArcTicks from './axis-arc-tick-node'; +import buildArcLabels from './axis-arc-label-node'; function tickSpacing(settings) { let spacing = 0; @@ -58,6 +61,15 @@ function labelBuilder(ticks, buildOpts, resolveTickOpts) { }); } +function arcLabelBuilder(ticks, buildOpts, resolveTickOpts) { + return ticks.map((tick, idx) => { + resolveTickOpts(tick, idx); + const label = buildArcLabels(ticks, tick, idx, buildOpts); + label.data = tick.data; + return label; + }); +} + function layeredLabelBuilder(ticks, buildOpts, settings, resolveTickOpts) { const padding = buildOpts.padding; const spacing = labelsSpacing(settings); @@ -213,12 +225,17 @@ export default function nodeBuilder(isDiscrete) { const tilted = state.labels.activeMode === 'tilted'; const layered = state.labels.activeMode === 'layered'; let majorTickNodes; - if (settings.line.show) { buildOpts.style = settings.line; buildOpts.padding = settings.paddingStart; - - nodes.push(buildLine(buildOpts)); + if (!settings.isRadial) { + nodes.push(buildLine(buildOpts)); + } else { + buildOpts.startAngle = settings.startAngle; + buildOpts.endAngle = settings.endAngle; + buildOpts.outerRadius = settings.outerRadius; + nodes.push(buildArcLine(buildOpts)); + } } if (settings.ticks.show) { buildOpts.style = settings.ticks; @@ -226,6 +243,12 @@ export default function nodeBuilder(isDiscrete) { buildOpts.padding = tickSpacing(settings); majorTickNodes = tickBuilder(major, buildOpts); + if (settings.isRadial) { + const arcTicks = buildArcTicks(ticks, buildOpts); + arcTicks.forEach((arcTick) => { + nodes.push(arcTick); + }); + } } if (settings.labels.show) { const padding = labelsSpacing(settings); @@ -262,7 +285,9 @@ export default function nodeBuilder(isDiscrete) { }; let labelNodes = []; - if (layered && (settings.align === 'top' || settings.align === 'bottom')) { + if (settings.isRadial) { + labelNodes = arcLabelBuilder(ticks, buildOpts, resolveTickOpts); + } else if (layered && (settings.align === 'top' || settings.align === 'bottom')) { labelNodes = layeredLabelBuilder(major, buildOpts, settings, resolveTickOpts); } else { labelNodes = labelBuilder(major, buildOpts, resolveTickOpts); @@ -280,7 +305,6 @@ export default function nodeBuilder(isDiscrete) { buildOpts.style = settings.minorTicks; buildOpts.tickSize = settings.minorTicks.tickSize; buildOpts.padding = tickMinorSpacing(settings); - nodes.push(...tickBuilder(minor, buildOpts)); } From 0ae60945994ef1c727b973233cd5ca85c13da8e4 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Fri, 1 Nov 2024 12:53:28 +0100 Subject: [PATCH 02/19] feat: added radial axis --- .../axis/axis-arc-label-node.js | 197 +++--------------- .../chart-components/axis/axis-arc-node.js | 61 +----- .../axis/axis-arc-tick-node.js | 51 ++--- .../axis/axis-node-builder.js | 19 +- 4 files changed, 64 insertions(+), 264 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 28f9e129f..704900fd4 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -1,5 +1,3 @@ -import { rotate as rotateVector } from '../../math/vector'; - function appendStyle(struct, buildOpts) { ['fill', 'fontSize', 'fontFamily'].forEach((style) => { struct[style] = buildOpts.style[style]; @@ -17,190 +15,44 @@ function checkText(text) { return typeof text === 'string' || typeof text === 'number' ? text : '-'; } -function clampEnds(struct, buildOpts) { - if (buildOpts.tilted || buildOpts.stepSize) { - return; - } - - if (buildOpts.align === 'top' || buildOpts.align === 'bottom') { - const leftBoundary = 0; - const rightBoundary = buildOpts.outerRect.width; - const textWidth = Math.min(buildOpts.maxWidth / 2, buildOpts.textRect.width / 2); - const leftTextBoundary = struct.x - textWidth; - const rightTextBoundary = struct.x + textWidth; - if (leftTextBoundary < leftBoundary) { - struct.anchor = 'start'; - struct.x = buildOpts.innerRect.x - buildOpts.outerRect.x; - } else if (rightTextBoundary > rightBoundary) { - struct.anchor = 'end'; - struct.x = buildOpts.innerRect.width + buildOpts.innerRect.x; - } - } else { - const topBoundary = 0; - const bottomBoundary = buildOpts.outerRect.height; - const textHeight = buildOpts.maxHeight / 2; - const topTextBoundary = struct.y - textHeight; - const bottomTextBoundary = struct.y + textHeight; - if (topTextBoundary < topBoundary) { - struct.y = buildOpts.innerRect.y - buildOpts.outerRect.y; - struct.baseline = 'text-before-edge'; - } else if (bottomTextBoundary > bottomBoundary) { - struct.y = buildOpts.innerRect.height + (buildOpts.innerRect.y - buildOpts.outerRect.y); - struct.baseline = 'text-after-edge'; - } - } -} - -function appendTilting(struct, buildOpts) { - if (buildOpts.tilted) { - const r = -buildOpts.angle; - const radians = r * (Math.PI / 180); - - if (buildOpts.align === 'bottom') { - struct.x -= (buildOpts.maxHeight * Math.sin(radians)) / 2; - struct.y -= buildOpts.maxHeight; - struct.y += (buildOpts.maxHeight * Math.cos(radians)) / 2; - } else { - struct.x -= (buildOpts.maxHeight * Math.sin(radians)) / 3; +function collider(struct, tickPos) { + if (struct.align === 'right') { + if (tickPos.x >= struct.x) { + struct.text = ''; } - - struct.transform = `rotate(${r}, ${struct.x}, ${struct.y})`; - struct.anchor = (buildOpts.align === 'bottom') === buildOpts.angle < 0 ? 'start' : 'end'; - - // adjustForEnds - const textWidth = Math.cos(radians) * buildOpts.maxWidth; - if ((buildOpts.align === 'bottom') === buildOpts.angle < 0) { - // right - const rightBoundary = buildOpts.outerRect.width - buildOpts.paddingEnd; - const rightTextBoundary = struct.x + textWidth; - if (rightTextBoundary > rightBoundary) { - struct.maxWidth = (rightBoundary - struct.x - 10) / Math.cos(radians); - } - } else { - // left - const leftBoundary = buildOpts.paddingEnd; - const leftTextBoundary = struct.x - textWidth; - if (leftTextBoundary < leftBoundary) { - struct.maxWidth = (struct.x - leftBoundary - 10) / Math.cos(radians); - } - } - } -} - -function bandwidthCollider(tick, struct, buildOpts) { - if (buildOpts.align === 'bottom' || buildOpts.align === 'top') { - const tickCenter = tick.position * buildOpts.innerRect.width; - const leftBoundary = tickCenter + (buildOpts.innerRect.x - buildOpts.outerRect.x - buildOpts.stepSize / 2); - struct.collider = { - type: 'rect', - x: leftBoundary, - y: 0, - width: leftBoundary < 0 ? buildOpts.stepSize + leftBoundary : buildOpts.stepSize, // Adjust collider so that it doesnt extend onto neighbor collider - height: buildOpts.innerRect.height, - }; - } else { - const tickCenter = tick.position * buildOpts.innerRect.height; - const topBoundary = tickCenter + (buildOpts.innerRect.y - buildOpts.outerRect.y - buildOpts.stepSize / 2); - struct.collider = { - type: 'rect', - x: 0, - y: topBoundary, - width: buildOpts.innerRect.width, - height: topBoundary < 0 ? buildOpts.stepSize + topBoundary : buildOpts.stepSize, // Adjust collider so that it doesnt extend onto neighbor collider - }; } - - // Clip edges of the collider, should not extend beyoned the outerRect - const collider = struct.collider; - collider.x = Math.max(collider.x, 0); - collider.y = Math.max(collider.y, 0); - const widthClip = collider.x + collider.width - (buildOpts.outerRect.x + buildOpts.outerRect.width); - collider.width = widthClip > 0 ? collider.width - widthClip : collider.width; - const heightClip = collider.y + collider.height - (buildOpts.outerRect.y + buildOpts.outerRect.height); - collider.height = heightClip > 0 ? collider.height - heightClip : collider.height; -} - -function boundsCollider(tick, struct) { - struct.collider = { - type: 'polygon', - vertices: [ - { x: struct.boundingRect.x, y: struct.boundingRect.y }, - { x: struct.boundingRect.x + struct.boundingRect.width, y: struct.boundingRect.y }, - { x: struct.boundingRect.x + struct.boundingRect.width, y: struct.boundingRect.y + struct.boundingRect.height }, - { x: struct.boundingRect.x, y: struct.boundingRect.y + struct.boundingRect.height }, - ], - }; -} - -function tiltedCollider(tick, struct, buildOpts) { - const radians = buildOpts.angle * (Math.PI / 180); - const halfWidth = Math.max(buildOpts.stepSize / 2, struct.boundingRect.height / 2); // Handle if bandwidth is zero - const startAnchor = struct.anchor === 'start'; - const em = struct.anchor === 'end' && radians < 0; - const sp = struct.anchor === 'start' && radians >= 0; - const y = struct.boundingRect.y + (sp || em ? struct.boundingRect.height : 0); - // Generate starting points at bandwidth boundaries - const points = [ - { x: struct.x - halfWidth, y }, - { x: struct.x + halfWidth, y }, - ].map((p) => rotateVector(p, radians, { x: struct.x, y: struct.y })); // Rotate around center point to counteract labels rotation - - // Append points to wrap polygon around label - const margin = 10; // extend slightly to handle single char labels better - const leftPoint = { - x: startAnchor ? struct.boundingRect.x + struct.boundingRect.width + margin : struct.boundingRect.x - margin, - y: struct.boundingRect.y + struct.boundingRect.height, - }; - - const rightPoint = { - x: startAnchor ? struct.boundingRect.x + struct.boundingRect.width + margin : struct.boundingRect.x - margin, - y: struct.boundingRect.y, - }; - - const orderedPoints = radians >= 0 ? [leftPoint, rightPoint] : [rightPoint, leftPoint]; - points.push(...orderedPoints); - - struct.collider = { - type: 'polygon', - vertices: points, - }; } -function appendCollider(tick, struct, buildOpts) { - if (buildOpts.layered || !buildOpts.stepSize) { - boundsCollider(tick, struct); - } else if (buildOpts.tilted) { - tiltedCollider(tick, struct, buildOpts); - } else { - bandwidthCollider(tick, struct, buildOpts); - } +function appendCollider(tick, struct, buildOpts, tickPos) { + collider(tick, struct, buildOpts, tickPos); } function appendBounds(struct, buildOpts) { struct.boundingRect = buildOpts.textBounds(struct); } -export default function buildArcLabels(ticks, tick, idx, buildOpts) { + +export default function buildArcLabels(tick, buildOpts) { const rect = buildOpts.innerRect; - const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.outerRadius; const outerRadius = innerRadius + 1; - const startAngle = buildOpts.startAngle || 0; // Start angle of the arc - const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc + const startAngle = buildOpts.startAngle || 0; + const endAngle = buildOpts.endAngle || Math.PI / 2; const tickLength = 6; const angleRange = endAngle - startAngle; - // Generate labels - - const normalizedPosition = idx / (ticks.length - 1); - let angle = startAngle + normalizedPosition * angleRange; + let angle; + if (buildOpts.align === 'top' || buildOpts.align === 'bottom') { + angle = endAngle - tick.position * angleRange; + } else { + angle = startAngle + tick.position * angleRange; + } let side; if (angle < 0 && angle > -Math.PI) { - // Label should be on the left side = 'left'; } else if (angle > 0 && angle < Math.PI) { side = 'right'; @@ -208,7 +60,8 @@ export default function buildArcLabels(ticks, tick, idx, buildOpts) { side = 'center'; } angle -= Math.PI / 2; - const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength + 12.5, angle); + const padding = 6; + const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength + padding, angle); let textAnchor; if (side === 'left') { textAnchor = 'end'; // Align text to the right of the x-coordinate @@ -217,26 +70,24 @@ export default function buildArcLabels(ticks, tick, idx, buildOpts) { } else { textAnchor = 'middle'; // Center align the text } - // Add tick line to struct + const struct = { type: 'text', text: checkText(tick.label), align: side, - fontSmooth: 'auto', fontSize: 12, padding: 50, x: innerPos.x, y: innerPos.y, - maxHeight: 16, - maxWidth: 89, + maxHeight: buildOpts.maxHeight, + maxWidth: buildOpts.maxWidth, anchor: textAnchor, baseline: 'middle', }; + const tickPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + 6, angle); appendStyle(struct, buildOpts); - clampEnds(struct, buildOpts); - appendTilting(struct, buildOpts); appendBounds(struct, buildOpts); - appendCollider(tick, struct, buildOpts); + appendCollider(struct, tickPos); return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index 7c5dec7a1..bc72db041 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -4,78 +4,37 @@ function appendStyle(struct, buildOpts) { extend(struct, buildOpts.style); } -function polarToCartesian(centerX, centerY, radius, angle) { - return { - x: centerX + radius * Math.cos(angle), - y: centerY + radius * Math.sin(angle), - }; -} - -export default function buildArcLine(buildOpts) { +export default function buildArcLine(buildOpts, ticks) { const rect = buildOpts.innerRect; - const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; const innerRadius = plotSize * buildOpts.outerRadius; const outerRadius = innerRadius + 1; - const startAngle = buildOpts.startAngle || 0; // Start angle of the arc - const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc - - const numTicks = buildOpts.numTicks || 5; - const tickLength = 10; - const tickWidth = 2; - + const startAngle = buildOpts.startAngle || 0; + const endAngle = buildOpts.endAngle || Math.PI / 2; + const arcValue = ticks[ticks.length - 1].value; const struct = { visible: true, type: 'path', - arc: 412.29, - arcDatum: { data: 412.29, value: 412.29, startAngle, endAngle }, // Arc data + arc: arcValue, + arcDatum: { data: arcValue, value: arcValue, startAngle, endAngle }, transform: `translate(0, 0) translate(${centerPoint.cx}, ${centerPoint.cy})`, desc: { share: 1, slice: { cornerRadius: 0, - end: 6.283185307179586, innerRadius, - offset: { x: 308, y: 207.5 }, outerRadius, }, }, - innerRadius: 0.85, - outerRadius: 0.86, + innerRadius, + outerRadius, ticks: [], }; - const angleRange = endAngle - startAngle; - const angleStep = angleRange / numTicks; - - // Generate ticks - for (let i = 0; i <= numTicks; i++) { - const angle = startAngle + i * angleStep; - - // Calculate outer position for tick (on outer arc radius) - const outerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius, angle); - - // Calculate inner position for tick (closer to the arc center) - const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius - tickLength, angle); - - // Add tick line to struct - struct.ticks.push({ - type: 'line', - stroke: buildOpts.tickColor || '#000', // Default tick color or use from buildOpts - strokeWidth: tickWidth, - shape: { - x1: innerPos.x, - y1: innerPos.y, - x2: outerPos.x, - y2: outerPos.y, - }, - }); - } - // Apply styles from buildOpts (optional, e.g., stroke, stroke-width) appendStyle(struct, buildOpts); - console.log('arc line', struct, buildOpts); - return struct; // Return the struct object containing the path definition + return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 0fe1c42fe..6f44f0ac2 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -11,46 +11,35 @@ function polarToCartesian(centerX, centerY, radius, angle) { }; } -export default function buildArcTicks(ticks, buildOpts) { +export default function buildArcTicks(tick, buildOpts) { const rect = buildOpts.innerRect; - const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; // Center of the container + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.outerRadius; const outerRadius = innerRadius + 1; - - const startAngle = buildOpts.startAngle || 0; // Start angle of the arc - const endAngle = buildOpts.endAngle || Math.PI / 2; // End angle of the arc - + const startAngle = buildOpts.startAngle || 0; + const endAngle = buildOpts.endAngle || Math.PI / 2; const tickWidth = 1; const tickLength = 6; - const struct = []; const angleRange = endAngle - startAngle; - // Generate ticks - ticks.forEach((tick, index) => { - const normalizedPosition = index / (ticks.length - 1); - let angle = startAngle + normalizedPosition * angleRange; - - angle -= Math.PI / 2; - const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength, angle); - - const outerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius, angle); - - // Add tick line to struct - struct.push({ - type: 'line', - stroke: buildOpts.tickColor || '#000', - strokeWidth: tickWidth, - padding: 5, - x1: innerPos.x, - y1: innerPos.y, - x2: outerPos.x, - y2: outerPos.y, - }); - }); + let angle = endAngle - tick.position * angleRange; + + angle -= Math.PI / 2; + const innerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + tickLength, angle); + const outerPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius, angle); + + const struct = { + type: 'line', + stroke: buildOpts.tickColor || '#000', + strokeWidth: tickWidth, + padding: 5, + x1: innerPos.x, + y1: innerPos.y, + x2: outerPos.x, + y2: outerPos.y, + }; - // Apply styles from buildOpts (optional, e.g., stroke, stroke-width) appendStyle(struct, buildOpts); return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index 23b04bb3a..aec60d723 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -48,6 +48,10 @@ function tickBuilder(ticks, buildOpts) { return ticks.map((tick) => buildTick(tick, buildOpts)); } +function arcTickBuilder(ticks, buildOpts) { + return ticks.map((tick) => buildArcTicks(tick, buildOpts)); +} + function tickBandwidth(scale, tick) { return tick ? Math.abs(tick.end - tick.start) : scale.bandwidth(); } @@ -64,7 +68,7 @@ function labelBuilder(ticks, buildOpts, resolveTickOpts) { function arcLabelBuilder(ticks, buildOpts, resolveTickOpts) { return ticks.map((tick, idx) => { resolveTickOpts(tick, idx); - const label = buildArcLabels(ticks, tick, idx, buildOpts); + const label = buildArcLabels(tick, buildOpts); label.data = tick.data; return label; }); @@ -234,20 +238,17 @@ export default function nodeBuilder(isDiscrete) { buildOpts.startAngle = settings.startAngle; buildOpts.endAngle = settings.endAngle; buildOpts.outerRadius = settings.outerRadius; - nodes.push(buildArcLine(buildOpts)); + nodes.push(buildArcLine(buildOpts, ticks)); } } if (settings.ticks.show) { buildOpts.style = settings.ticks; buildOpts.tickSize = settings.ticks.tickSize; buildOpts.padding = tickSpacing(settings); - - majorTickNodes = tickBuilder(major, buildOpts); if (settings.isRadial) { - const arcTicks = buildArcTicks(ticks, buildOpts); - arcTicks.forEach((arcTick) => { - nodes.push(arcTick); - }); + majorTickNodes = arcTickBuilder(ticks, buildOpts); + } else { + majorTickNodes = tickBuilder(major, buildOpts); } } if (settings.labels.show) { @@ -286,7 +287,7 @@ export default function nodeBuilder(isDiscrete) { let labelNodes = []; if (settings.isRadial) { - labelNodes = arcLabelBuilder(ticks, buildOpts, resolveTickOpts); + labelNodes = arcLabelBuilder(major, buildOpts, resolveTickOpts); } else if (layered && (settings.align === 'top' || settings.align === 'bottom')) { labelNodes = layeredLabelBuilder(major, buildOpts, settings, resolveTickOpts); } else { From d67fda4ef61e446484cbe67ce9fd902768a9a346 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 11:17:31 +0100 Subject: [PATCH 03/19] feat: added center offset for label positioning --- .../chart-components/axis/axis-arc-label-node.js | 13 ++++++------- .../core/chart-components/axis/axis-arc-node.js | 4 +--- .../chart-components/axis/axis-arc-tick-node.js | 1 - .../chart-components/axis/axis-node-builder.js | 15 +++++++++------ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 704900fd4..12d49cf76 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -37,24 +37,23 @@ export default function buildArcLabels(tick, buildOpts) { const plotSize = Math.min(rect.height, rect.width) / 2; const innerRadius = plotSize * buildOpts.outerRadius; const outerRadius = innerRadius + 1; - - const startAngle = buildOpts.startAngle || 0; + const startAngle = buildOpts.startAngle || -Math.PI / 2; const endAngle = buildOpts.endAngle || Math.PI / 2; - const tickLength = 6; - const angleRange = endAngle - startAngle; + const centerOffset = 0.2; let angle; + let side; + if (buildOpts.align === 'top' || buildOpts.align === 'bottom') { angle = endAngle - tick.position * angleRange; } else { angle = startAngle + tick.position * angleRange; } - let side; - if (angle < 0 && angle > -Math.PI) { + if (angle < 0 - centerOffset && angle > -Math.PI + centerOffset) { side = 'left'; - } else if (angle > 0 && angle < Math.PI) { + } else if (angle > 0 + centerOffset && angle < Math.PI - centerOffset) { side = 'right'; } else { side = 'center'; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index bc72db041..e2c3e185d 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -14,7 +14,7 @@ export default function buildArcLine(buildOpts, ticks) { const startAngle = buildOpts.startAngle || 0; const endAngle = buildOpts.endAngle || Math.PI / 2; - const arcValue = ticks[ticks.length - 1].value; + const arcValue = ticks && ticks.length > 0 ? ticks[ticks.length - 1].value : 0; const struct = { visible: true, type: 'path', @@ -33,8 +33,6 @@ export default function buildArcLine(buildOpts, ticks) { outerRadius, ticks: [], }; - appendStyle(struct, buildOpts); - return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 6f44f0ac2..7b4c4ae35 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -39,7 +39,6 @@ export default function buildArcTicks(tick, buildOpts) { x2: outerPos.x, y2: outerPos.y, }; - appendStyle(struct, buildOpts); return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index aec60d723..e71695b49 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -229,16 +229,19 @@ export default function nodeBuilder(isDiscrete) { const tilted = state.labels.activeMode === 'tilted'; const layered = state.labels.activeMode === 'layered'; let majorTickNodes; + + if (settings.isRadial) { + buildOpts.startAngle = settings.startAngle; + buildOpts.endAngle = settings.endAngle; + buildOpts.outerRadius = settings.outerRadius; + } if (settings.line.show) { buildOpts.style = settings.line; buildOpts.padding = settings.paddingStart; - if (!settings.isRadial) { - nodes.push(buildLine(buildOpts)); - } else { - buildOpts.startAngle = settings.startAngle; - buildOpts.endAngle = settings.endAngle; - buildOpts.outerRadius = settings.outerRadius; + if (settings.isRadial) { nodes.push(buildArcLine(buildOpts, ticks)); + } else { + nodes.push(buildLine(buildOpts)); } } if (settings.ticks.show) { From d16254546c377e4b1bde661484a73c62ca979a42 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 13:34:26 +0100 Subject: [PATCH 04/19] feat: updating arc tick color --- .../src/core/chart-components/axis/axis-arc-label-node.js | 2 -- .../src/core/chart-components/axis/axis-arc-tick-node.js | 8 +++----- .../src/core/chart-components/axis/axis-node-builder.js | 1 + 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 12d49cf76..d7811a51c 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -74,8 +74,6 @@ export default function buildArcLabels(tick, buildOpts) { type: 'text', text: checkText(tick.label), align: side, - fontSize: 12, - padding: 50, x: innerPos.x, y: innerPos.y, maxHeight: buildOpts.maxHeight, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 7b4c4ae35..3742e5b14 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -19,8 +19,7 @@ export default function buildArcTicks(tick, buildOpts) { const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle || 0; const endAngle = buildOpts.endAngle || Math.PI / 2; - const tickWidth = 1; - const tickLength = 6; + const tickLength = buildOpts.tickSize; const angleRange = endAngle - startAngle; let angle = endAngle - tick.position * angleRange; @@ -31,13 +30,12 @@ export default function buildArcTicks(tick, buildOpts) { const struct = { type: 'line', - stroke: buildOpts.tickColor || '#000', - strokeWidth: tickWidth, - padding: 5, + stroke: buildOpts.tickColor, x1: innerPos.x, y1: innerPos.y, x2: outerPos.x, y2: outerPos.y, + value: tick.value, }; appendStyle(struct, buildOpts); return struct; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index e71695b49..c0fced247 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -248,6 +248,7 @@ export default function nodeBuilder(isDiscrete) { buildOpts.style = settings.ticks; buildOpts.tickSize = settings.ticks.tickSize; buildOpts.padding = tickSpacing(settings); + buildOpts.tickColor = settings.ticks.tickColor || '#000'; if (settings.isRadial) { majorTickNodes = arcTickBuilder(ticks, buildOpts); } else { From 81a039283a7670766467ce718ac9ef759971a6af Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 14:39:39 +0100 Subject: [PATCH 05/19] fix: fixed a bug with labelplacement --- .../src/core/chart-components/axis/axis-arc-label-node.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index d7811a51c..1772c697c 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -37,8 +37,8 @@ export default function buildArcLabels(tick, buildOpts) { const plotSize = Math.min(rect.height, rect.width) / 2; const innerRadius = plotSize * buildOpts.outerRadius; const outerRadius = innerRadius + 1; - const startAngle = buildOpts.startAngle || -Math.PI / 2; - const endAngle = buildOpts.endAngle || Math.PI / 2; + const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; + const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const tickLength = 6; const angleRange = endAngle - startAngle; const centerOffset = 0.2; From e92bb28e828fc547a3e70d6933838ae4e82a0d23 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 15:04:04 +0100 Subject: [PATCH 06/19] refactor: changed name of radius property in arc-axis --- .../src/core/chart-components/axis/axis-arc-label-node.js | 2 +- .../picasso.js/src/core/chart-components/axis/axis-arc-node.js | 2 +- .../src/core/chart-components/axis/axis-arc-tick-node.js | 2 +- .../src/core/chart-components/axis/axis-node-builder.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 1772c697c..6bb28ffa1 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -35,7 +35,7 @@ export default function buildArcLabels(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.outerRadius; + const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index e2c3e185d..38fa16da4 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -9,7 +9,7 @@ export default function buildArcLine(buildOpts, ticks) { const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.outerRadius; + const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle || 0; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 3742e5b14..5ee01222e 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -15,7 +15,7 @@ export default function buildArcTicks(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.outerRadius; + const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle || 0; const endAngle = buildOpts.endAngle || Math.PI / 2; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index c0fced247..49d559e26 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -233,7 +233,7 @@ export default function nodeBuilder(isDiscrete) { if (settings.isRadial) { buildOpts.startAngle = settings.startAngle; buildOpts.endAngle = settings.endAngle; - buildOpts.outerRadius = settings.outerRadius; + buildOpts.radius = settings.radius; } if (settings.line.show) { buildOpts.style = settings.line; From 7f8232fcaa8d185568257fcde13902f66dc20beb Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 15:08:44 +0100 Subject: [PATCH 07/19] fix: added default value to radius property --- .../src/core/chart-components/axis/axis-arc-label-node.js | 2 +- .../src/core/chart-components/axis/axis-arc-node.js | 6 +++--- .../src/core/chart-components/axis/axis-arc-tick-node.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 6bb28ffa1..ed894453e 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -35,7 +35,7 @@ export default function buildArcLabels(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index 38fa16da4..e69df1716 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -9,11 +9,11 @@ export default function buildArcLine(buildOpts, ticks) { const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; const outerRadius = innerRadius + 1; - const startAngle = buildOpts.startAngle || 0; - const endAngle = buildOpts.endAngle || Math.PI / 2; + const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; + const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const arcValue = ticks && ticks.length > 0 ? ticks[ticks.length - 1].value : 0; const struct = { visible: true, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 5ee01222e..781025bc0 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -15,10 +15,10 @@ export default function buildArcTicks(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; const outerRadius = innerRadius + 1; - const startAngle = buildOpts.startAngle || 0; - const endAngle = buildOpts.endAngle || Math.PI / 2; + const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; + const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const tickLength = buildOpts.tickSize; const angleRange = endAngle - startAngle; From f83fbde521f5441c8d00526f70635d993f8101cd Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 4 Nov 2024 15:27:33 +0100 Subject: [PATCH 08/19] fix: arc axis ticklength --- .../src/core/chart-components/axis/axis-arc-label-node.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index ed894453e..b2298a0ab 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -39,7 +39,7 @@ export default function buildArcLabels(tick, buildOpts) { const outerRadius = innerRadius + 1; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; - const tickLength = 6; + const tickLength = buildOpts.tickSize; const angleRange = endAngle - startAngle; const centerOffset = 0.2; From d3cf2bbb582a2aa3b2a8a39dbac24f3fec76a37e Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Tue, 5 Nov 2024 13:12:26 +0100 Subject: [PATCH 09/19] refactor: removed unnecessary props in arc-node --- .../src/core/chart-components/axis/axis-arc-node.js | 6 ++---- .../src/core/chart-components/axis/axis-node-builder.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index e69df1716..4e3ac9e67 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -4,7 +4,7 @@ function appendStyle(struct, buildOpts) { extend(struct, buildOpts.style); } -export default function buildArcLine(buildOpts, ticks) { +export default function buildArcLine(buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; @@ -14,12 +14,10 @@ export default function buildArcLine(buildOpts, ticks) { const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; - const arcValue = ticks && ticks.length > 0 ? ticks[ticks.length - 1].value : 0; const struct = { visible: true, type: 'path', - arc: arcValue, - arcDatum: { data: arcValue, value: arcValue, startAngle, endAngle }, + arcDatum: { startAngle, endAngle }, transform: `translate(0, 0) translate(${centerPoint.cx}, ${centerPoint.cy})`, desc: { share: 1, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index 49d559e26..e37178781 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -239,7 +239,7 @@ export default function nodeBuilder(isDiscrete) { buildOpts.style = settings.line; buildOpts.padding = settings.paddingStart; if (settings.isRadial) { - nodes.push(buildArcLine(buildOpts, ticks)); + nodes.push(buildArcLine(buildOpts)); } else { nodes.push(buildLine(buildOpts)); } From 6a245d4c44773d01f019fb4c76dbbd3103376ab9 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Tue, 5 Nov 2024 15:03:23 +0100 Subject: [PATCH 10/19] fix: fixed out of bounds bug in axis-arc-label --- .../chart-components/axis/axis-arc-label-node.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index b2298a0ab..617e2a706 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -23,6 +23,18 @@ function collider(struct, tickPos) { } } +function calculateMaxWidth(buildOpts, side, innerPos) { + let maxWidth; + if (side === 'left') { + maxWidth = innerPos.x; + } else if (side === 'right') { + maxWidth = buildOpts.outerRect.width - innerPos.x; + } else { + maxWidth = Math.max(innerPos.x, buildOpts.outerRect.width - innerPos.x); + } + return maxWidth; +} + function appendCollider(tick, struct, buildOpts, tickPos) { collider(tick, struct, buildOpts, tickPos); } @@ -77,7 +89,6 @@ export default function buildArcLabels(tick, buildOpts) { x: innerPos.x, y: innerPos.y, maxHeight: buildOpts.maxHeight, - maxWidth: buildOpts.maxWidth, anchor: textAnchor, baseline: 'middle', }; @@ -86,5 +97,6 @@ export default function buildArcLabels(tick, buildOpts) { appendStyle(struct, buildOpts); appendBounds(struct, buildOpts); appendCollider(struct, tickPos); + struct.maxWidth = calculateMaxWidth(buildOpts, side, innerPos); return struct; } From 336f4e61d03e5de73af8ff7214ade0d3206a4732 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Wed, 6 Nov 2024 12:37:37 +0100 Subject: [PATCH 11/19] fix: removed tickColor, updated axis-default-settings and added arc-padding --- docs/scriptappy.json | 27 ++++++++++++++++ .../axis/axis-arc-label-node.js | 2 +- .../chart-components/axis/axis-arc-node.js | 4 +-- .../axis/axis-arc-tick-node.js | 3 +- .../axis/axis-default-settings.js | 17 ++++++++++ .../axis/axis-node-builder.js | 32 +++++++++++++------ packages/picasso.js/types/index.d.ts | 6 ++++ 7 files changed, 76 insertions(+), 15 deletions(-) diff --git a/docs/scriptappy.json b/docs/scriptappy.json index 424f49809..53b954294 100644 --- a/docs/scriptappy.json +++ b/docs/scriptappy.json @@ -1681,6 +1681,33 @@ "defaultValue": "auto", "type": "string" }, + "arc": { + "kind": "object", + "entries": { + "endAngle": { + "description": "End of arc line", + "optional": true, + "type": "number" + }, + "isRadial": { + "description": "Flag that determines if axis is radial", + "optional": true, + "defaultValue": false, + "type": "boolean" + }, + "radius": { + "description": "Radius of arc line", + "optional": true, + "defaultValue": 0.5, + "type": "number" + }, + "startAngle": { + "description": "Start of arc line", + "optional": true, + "type": "number" + } + } + }, "labels": { "kind": "object", "entries": { diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 617e2a706..6ac95a4df 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -48,7 +48,7 @@ export default function buildArcLabels(tick, buildOpts) { const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; - const outerRadius = innerRadius + 1; + const outerRadius = innerRadius + buildOpts.padding; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const tickLength = buildOpts.tickSize; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index 4e3ac9e67..fb8927e02 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -9,8 +9,8 @@ export default function buildArcLine(buildOpts) { const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; - const outerRadius = innerRadius + 1; + const innerRadius = plotSize * buildOpts.radius; + const outerRadius = innerRadius + buildOpts.style.strokeWidth; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 781025bc0..0ffa9ed0a 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -16,7 +16,7 @@ export default function buildArcTicks(tick, buildOpts) { const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; - const outerRadius = innerRadius + 1; + const outerRadius = innerRadius + buildOpts.padding; const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const tickLength = buildOpts.tickSize; @@ -30,7 +30,6 @@ export default function buildArcTicks(tick, buildOpts) { const struct = { type: 'line', - stroke: buildOpts.tickColor, x1: innerPos.x, y1: innerPos.y, x2: outerPos.x, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js b/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js index 13c2bfe1b..500385eec 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js @@ -199,6 +199,23 @@ const DEFAULT_CONTINUOUS_SETTINGS = { * @type {boolean=} */ show: true, }, + /** + * @typedef {object} + */ + arc: { + /** Flag that determines if axis is radial + * @type {boolean=} */ + isRadial: false, + /** Start of arc line + * @type {number=} */ + startAngle: -Math.PI / 2, + /** End of arc line + * @type {number=} */ + endAngle: Math.PI / 2, + /** Radius of arc line + * @type {number=} */ + radius: 0.5, + }, /** Padding in direction perpendicular to the axis * @type {number=} */ paddingStart: 0, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index e37178781..84480cbe2 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -16,6 +16,12 @@ function tickSpacing(settings) { spacing += settings.ticks.show ? settings.ticks.margin : 0; return spacing; } +function arcTickSpacing(settings) { + let spacing = 0; + spacing += settings.line.show ? settings.line.strokeWidth / 2 : 0; + spacing += settings.ticks.show ? settings.ticks.margin : 0; + return spacing; +} function tickMinorSpacing(settings) { return settings.line.strokeWidth + settings.minorTicks.margin; @@ -27,6 +33,12 @@ function labelsSpacing(settings) { spacing += tickSpacing(settings) + settings.labels.margin; return spacing; } +function arcLabelSpacing(settings) { + let spacing = 0; + spacing += settings.ticks.show ? settings.ticks.tickSize : 0; + spacing += arcTickSpacing(settings) + settings.labels.margin; + return spacing; +} function calcActualTextRect({ style, measureText, tick }) { return measureText({ @@ -230,15 +242,15 @@ export default function nodeBuilder(isDiscrete) { const layered = state.labels.activeMode === 'layered'; let majorTickNodes; - if (settings.isRadial) { - buildOpts.startAngle = settings.startAngle; - buildOpts.endAngle = settings.endAngle; - buildOpts.radius = settings.radius; + if (settings.arc.isRadial) { + buildOpts.startAngle = settings.arc.startAngle; + buildOpts.endAngle = settings.arc.endAngle; + buildOpts.radius = settings.arc.radius; } if (settings.line.show) { buildOpts.style = settings.line; buildOpts.padding = settings.paddingStart; - if (settings.isRadial) { + if (settings.arc.isRadial) { nodes.push(buildArcLine(buildOpts)); } else { nodes.push(buildLine(buildOpts)); @@ -248,9 +260,9 @@ export default function nodeBuilder(isDiscrete) { buildOpts.style = settings.ticks; buildOpts.tickSize = settings.ticks.tickSize; buildOpts.padding = tickSpacing(settings); - buildOpts.tickColor = settings.ticks.tickColor || '#000'; - if (settings.isRadial) { - majorTickNodes = arcTickBuilder(ticks, buildOpts); + if (settings.arc.isRadial) { + buildOpts.padding = arcTickSpacing(settings); + majorTickNodes = arcTickBuilder(major, buildOpts); } else { majorTickNodes = tickBuilder(major, buildOpts); } @@ -288,9 +300,9 @@ export default function nodeBuilder(isDiscrete) { tick, }); }; - let labelNodes = []; - if (settings.isRadial) { + if (settings.arc.isRadial) { + buildOpts.padding = arcLabelSpacing(settings); labelNodes = arcLabelBuilder(major, buildOpts, resolveTickOpts); } else if (layered && (settings.align === 'top' || settings.align === 'bottom')) { labelNodes = layeredLabelBuilder(major, buildOpts, settings, resolveTickOpts); diff --git a/packages/picasso.js/types/index.d.ts b/packages/picasso.js/types/index.d.ts index e8b9f4e2f..0992b4369 100644 --- a/packages/picasso.js/types/index.d.ts +++ b/packages/picasso.js/types/index.d.ts @@ -553,6 +553,12 @@ declare namespace picassojs { namespace ComponentAxis { type ContinuousSettings = { align?: string; + arc: { + endAngle?: number; + isRadial?: boolean; + radius?: number; + startAngle?: number; + }; labels: { align?: number; filterOverlapping?: boolean; From b2529bae6fbd24f359cb3fdc728d23f9dd6ece1d Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Wed, 6 Nov 2024 13:23:22 +0100 Subject: [PATCH 12/19] refactor: removed unecessary use of radius --- .../picasso.js/src/core/chart-components/axis/axis-arc-node.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index fb8927e02..0ba82a1ab 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -27,8 +27,6 @@ export default function buildArcLine(buildOpts) { outerRadius, }, }, - innerRadius, - outerRadius, ticks: [], }; appendStyle(struct, buildOpts); From 1927220af22dfe3a5401a02e8ec8df3c0beb36f3 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Thu, 7 Nov 2024 14:19:42 +0100 Subject: [PATCH 13/19] docs: doc for radial axis --- docs/scriptappy.json | 49 +++++++++---------- .../axis/axis-arc-label-node.js | 8 +-- .../chart-components/axis/axis-arc-node.js | 5 +- .../axis/axis-arc-tick-node.js | 6 +-- .../axis/axis-default-settings.js | 25 +++------- .../axis/axis-node-builder.js | 9 ++-- packages/picasso.js/types/index.d.ts | 13 ++--- 7 files changed, 50 insertions(+), 65 deletions(-) diff --git a/docs/scriptappy.json b/docs/scriptappy.json index 53b954294..a82bfa7c9 100644 --- a/docs/scriptappy.json +++ b/docs/scriptappy.json @@ -148,6 +148,23 @@ } }, "definitions": { + "ArcSettings": { + "kind": "object", + "entries": { + "startAngle": { + "description": "Start of arc line, in radians", + "type": "number" + }, + "endAngle": { + "description": "End of arc line, in radians", + "type": "number" + }, + "radius": { + "description": "Radius of arc line", + "type": "number" + } + } + }, "Brush": { "description": "A brush context", "kind": "interface", @@ -1675,39 +1692,17 @@ "description": "Continuous axis settings", "kind": "object", "entries": { + "arc": { + "description": "Optional arc settings", + "optional": true, + "type": "#/definitions/ArcSettings" + }, "align": { "description": "Set the anchoring point of the axis. Available options are `auto/left/right/bottom/top`. In `auto` the axis determines the best option. The options are restricted based on the axis orientation, a vertical axis may only anchor on `left` or `right`", "optional": true, "defaultValue": "auto", "type": "string" }, - "arc": { - "kind": "object", - "entries": { - "endAngle": { - "description": "End of arc line", - "optional": true, - "type": "number" - }, - "isRadial": { - "description": "Flag that determines if axis is radial", - "optional": true, - "defaultValue": false, - "type": "boolean" - }, - "radius": { - "description": "Radius of arc line", - "optional": true, - "defaultValue": 0.5, - "type": "number" - }, - "startAngle": { - "description": "Start of arc line", - "optional": true, - "type": "number" - } - } - }, "labels": { "kind": "object", "entries": { diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 6ac95a4df..4beef4c73 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -47,10 +47,10 @@ export default function buildArcLabels(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; + const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.padding; - const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; - const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; + const startAngle = buildOpts.startAngle; + const endAngle = buildOpts.endAngle; const tickLength = buildOpts.tickSize; const angleRange = endAngle - startAngle; const centerOffset = 0.2; @@ -89,6 +89,7 @@ export default function buildArcLabels(tick, buildOpts) { x: innerPos.x, y: innerPos.y, maxHeight: buildOpts.maxHeight, + maxWidth: calculateMaxWidth(buildOpts, side, innerPos), anchor: textAnchor, baseline: 'middle', }; @@ -97,6 +98,5 @@ export default function buildArcLabels(tick, buildOpts) { appendStyle(struct, buildOpts); appendBounds(struct, buildOpts); appendCollider(struct, tickPos); - struct.maxWidth = calculateMaxWidth(buildOpts, side, innerPos); return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index 0ba82a1ab..154d7a3fb 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -8,12 +8,11 @@ export default function buildArcLine(buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.style.strokeWidth; + const startAngle = buildOpts.startAngle; + const endAngle = buildOpts.endAngle; - const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; - const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; const struct = { visible: true, type: 'path', diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 0ffa9ed0a..18b99822d 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -15,10 +15,10 @@ export default function buildArcTicks(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = buildOpts.radius !== undefined ? plotSize * buildOpts.radius : plotSize * 0.5; + const innerRadius = plotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.padding; - const startAngle = buildOpts.startAngle !== undefined ? buildOpts.startAngle : -Math.PI / 2; - const endAngle = buildOpts.endAngle !== undefined ? buildOpts.endAngle : Math.PI / 2; + const startAngle = buildOpts.startAngle; + const endAngle = buildOpts.endAngle; const tickLength = buildOpts.tickSize; const angleRange = endAngle - startAngle; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js b/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js index 500385eec..4bbf2ce83 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-default-settings.js @@ -118,10 +118,18 @@ const DEFAULT_DISCRETE_SETTINGS = { align: 'auto', }; +/** + * @typedef {object} ArcSettings + * @property {number} startAngle - Start of arc line, in radians + * @property {number} endAngle - End of arc line, in radians + * @property {number} radius - Radius of arc line + */ + /** * Continuous axis settings * @typedef {object} * @alias ComponentAxis~ContinuousSettings + * @property {ArcSettings=} arc - Optional arc settings * @example * { * type: 'axis', @@ -199,23 +207,6 @@ const DEFAULT_CONTINUOUS_SETTINGS = { * @type {boolean=} */ show: true, }, - /** - * @typedef {object} - */ - arc: { - /** Flag that determines if axis is radial - * @type {boolean=} */ - isRadial: false, - /** Start of arc line - * @type {number=} */ - startAngle: -Math.PI / 2, - /** End of arc line - * @type {number=} */ - endAngle: Math.PI / 2, - /** Radius of arc line - * @type {number=} */ - radius: 0.5, - }, /** Padding in direction perpendicular to the axis * @type {number=} */ paddingStart: 0, diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js index 84480cbe2..287173c99 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-node-builder.js @@ -241,8 +241,7 @@ export default function nodeBuilder(isDiscrete) { const tilted = state.labels.activeMode === 'tilted'; const layered = state.labels.activeMode === 'layered'; let majorTickNodes; - - if (settings.arc.isRadial) { + if (settings.arc) { buildOpts.startAngle = settings.arc.startAngle; buildOpts.endAngle = settings.arc.endAngle; buildOpts.radius = settings.arc.radius; @@ -250,7 +249,7 @@ export default function nodeBuilder(isDiscrete) { if (settings.line.show) { buildOpts.style = settings.line; buildOpts.padding = settings.paddingStart; - if (settings.arc.isRadial) { + if (settings.arc) { nodes.push(buildArcLine(buildOpts)); } else { nodes.push(buildLine(buildOpts)); @@ -260,7 +259,7 @@ export default function nodeBuilder(isDiscrete) { buildOpts.style = settings.ticks; buildOpts.tickSize = settings.ticks.tickSize; buildOpts.padding = tickSpacing(settings); - if (settings.arc.isRadial) { + if (settings.arc) { buildOpts.padding = arcTickSpacing(settings); majorTickNodes = arcTickBuilder(major, buildOpts); } else { @@ -301,7 +300,7 @@ export default function nodeBuilder(isDiscrete) { }); }; let labelNodes = []; - if (settings.arc.isRadial) { + if (settings.arc) { buildOpts.padding = arcLabelSpacing(settings); labelNodes = arcLabelBuilder(major, buildOpts, resolveTickOpts); } else if (layered && (settings.align === 'top' || settings.align === 'bottom')) { diff --git a/packages/picasso.js/types/index.d.ts b/packages/picasso.js/types/index.d.ts index 0992b4369..975c75806 100644 --- a/packages/picasso.js/types/index.d.ts +++ b/packages/picasso.js/types/index.d.ts @@ -67,6 +67,12 @@ declare namespace picassojs { } declare namespace picassojs { + type ArcSettings = { + startAngle: number; + endAngle: number; + radius: number; + }; + /** * A brush context */ @@ -552,13 +558,8 @@ declare namespace picassojs { namespace ComponentAxis { type ContinuousSettings = { + arc?: picassojs.ArcSettings; align?: string; - arc: { - endAngle?: number; - isRadial?: boolean; - radius?: number; - startAngle?: number; - }; labels: { align?: number; filterOverlapping?: boolean; From d9852c743a122508a0e8fde85dc5d08ffc9e59a3 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Tue, 12 Nov 2024 13:49:08 +0100 Subject: [PATCH 14/19] feat: added unit tests --- junit.xml | 5333 +++++++++++++++++ .../__tests__/axis-arc-label-node.spec.js | 114 + .../axis/__tests__/axis-arc-node.spec.js | 71 + .../axis/__tests__/axis-arc-tick-node.spec.js | 89 + .../axis/axis-arc-tick-node.js | 3 +- 5 files changed, 5609 insertions(+), 1 deletion(-) create mode 100644 junit.xml create mode 100644 packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js create mode 100644 packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js create mode 100644 packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js diff --git a/junit.xml b/junit.xml new file mode 100644 index 000000000..3e2ac222b --- /dev/null +++ b/junit.xml @@ -0,0 +1,5333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js new file mode 100644 index 000000000..e56457094 --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js @@ -0,0 +1,114 @@ +import { textBounds } from '../../../../web/text-manipulation'; +import buildArcLabels from '../axis-arc-label-node'; + +function createTick(position, label) { + return { + position, + label, + value: 1.23, // just some dummy value to test node value for tracking animation + }; +} + +describe('Axis Label Node', () => { + const innerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + const outerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + const textRect = { height: 16, width: 18 }; + const measureTextMock = ({ text }) => ({ width: text.length, height: 1 }); + + beforeEach(() => { + innerRect.width = 400; + innerRect.height = 425; + innerRect.x = 0; + innerRect.y = 425; + outerRect.width = 400; + outerRect.height = 425; + outerRect.x = 0; + outerRect.y = 0; + }); + + describe('Label', () => { + let buildOpts, tick; + + beforeEach(() => { + buildOpts = { + align: 'top', + radius: 0.85, + startAngle: (-2 * Math.PI) / 3, + endAngle: (2 * Math.PI) / 3, + innerRect, + outerRect, + padding: 3.5, + paddingEnd: 10, + stepSize: 0, + style: { + align: 0.5, + fontFamily: 'Arial', + fontSize: '12px', + margin: -5, + }, + textBounds: (node) => textBounds(node, measureTextMock), + textRect, + tickSize: 6, + }; + tick = createTick(0); + }); + + describe('Style align', () => { + it('start on left side of tick', () => { + buildOpts.align = 'top'; + tick = createTick(1, '0'); + const result = buildArcLabels(tick, buildOpts); + expect(result.x).to.be.closeTo(40, 2); + expect(result.y).to.be.closeTo(305, 2); + expect(result.anchor).to.equal('end'); + }); + + it('start on left side of tick', () => { + buildOpts.align = 'top'; + tick = createTick(0.7, '100'); + const result = buildArcLabels(tick, buildOpts); + expect(result.x).to.be.closeTo(62, 2); + expect(result.y).to.be.closeTo(88, 2); + expect(result.anchor).to.equal('end'); + }); + + it('start on right side of tick', () => { + buildOpts.align = 'top'; + tick = createTick(0.4, '250'); + const result = buildArcLabels(tick, buildOpts); + expect(result.x).to.be.closeTo(275, 2); + expect(result.y).to.be.closeTo(43, 2); + expect(result.anchor).to.equal('start'); + }); + it('the label should be centered on the tick', () => { + buildOpts.align = 'top'; + buildOpts.innerRect = { width: 213, height: 595 }; + tick = createTick(0.5, '300'); + const result = buildArcLabels(tick, buildOpts); + console.log(result); + expect(result.x).to.be.closeTo(106.5, 2); + expect(result.y).to.be.closeTo(191, 2); + expect(result.anchor).to.equal('middle'); + }); + }); + + describe('Not text in tick label', () => { + it('tick.label is undefined', () => { + buildOpts.align = 'top'; + tick = createTick(0, undefined); + const result = buildArcLabels(tick, buildOpts); + expect(result.text).to.equal('-'); + }); + }); + }); +}); diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js new file mode 100644 index 000000000..ef15f0cd5 --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js @@ -0,0 +1,71 @@ +import buildArcLine from '../axis-arc-node'; + +describe('Axis Arc Line Node', () => { + const innerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + const outerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + + describe('Arc', () => { + let buildOpts, expected; + + beforeEach(() => { + innerRect.width = 50; + innerRect.height = 100; + innerRect.x = 0; + innerRect.y = 0; + outerRect.width = 50; + outerRect.height = 100; + outerRect.x = 0; + outerRect.y = 0; + + buildOpts = { + style: { stroke: 'red', strokeWidth: 1 }, + align: 'bottom', + innerRect, + outerRect, + padding: 10, + startAngle: -Math.PI / 3, + endAngle: Math.PI / 3, + radius: 0.5, + }; + expected = { + visible: true, + type: 'path', + arcDatum: { startAngle: 0, endAngle: 0 }, + transform: `translate(0, 0) translate(${0}, ${0})`, + desc: { + share: 1, + slice: { + cornerRadius: 0, + innerRadius: 0, + outerRadius: 0, + }, + }, + stroke: 'red', + strokeWidth: 1, + ticks: [], + }; + }); + + it('Structure Properties', () => { + const rect = buildOpts.innerRect; + const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; + const plotSize = Math.min(rect.height, rect.width) / 2; + expected.transform = `translate(0, 0) translate(${centerPoint.cx}, ${centerPoint.cy})`; + expected.arcDatum.startAngle = buildOpts.startAngle; + expected.arcDatum.endAngle = buildOpts.endAngle; + expected.desc.slice.innerRadius = buildOpts.radius * plotSize; + expected.desc.slice.outerRadius = buildOpts.radius * plotSize + buildOpts.style.strokeWidth; + expect(buildArcLine(buildOpts)).to.deep.equal(expected); + }); + }); +}); diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js new file mode 100644 index 000000000..9eb4d07f7 --- /dev/null +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js @@ -0,0 +1,89 @@ +import { expect } from 'chai'; +import buildArcTicks from '../axis-arc-tick-node'; + +function createTick(position, value) { + return { + position, + value, // just some dummy value to test node value for tracking animation + }; +} + +describe('Axis Arc Tick Node', () => { + const innerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + const outerRect = { + x: 0, + y: 0, + width: 0, + height: 0, + }; + describe('Tick', () => { + let buildOpts, tick, tickValue; + beforeEach(() => { + innerRect.width = 400; + innerRect.height = 417; + innerRect.x = 0; + innerRect.y = 417; + outerRect.width = 400; + outerRect.height = 417; + outerRect.x = 0; + outerRect.y = 0; + buildOpts = { + align: 'top', + radius: 0.85, + startAngle: (-2 * Math.PI) / 3, + endAngle: (2 * Math.PI) / 3, + innerRect, + outerRect, + padding: 2.5, + paddingEnd: 10, + stepSize: 0, + style: { + fontFamily: "'Source Sans Pro', Arial, sans-serif", + fontSize: '12px', + margin: 2, + strokeWidth: 1, + stroke: '#cdcdcd', + tickSize: 6, + }, + tickSize: 6, + }; + }); + it('Start Tick', () => { + tickValue = 0; + tick = createTick(1, tickValue); + const result = buildArcTicks(tick, buildOpts); + console.log(result); + expect(result.x1).to.be.closeTo(45, 1); + expect(result.x2).to.be.closeTo(51, 1); + expect(result.y1).to.be.closeTo(298, 1); + expect(result.y2).to.be.closeTo(295, 1); + expect(result.value).to.equal(tickValue); + }); + it('End Tick', () => { + tickValue = 500; + tick = createTick(0, tickValue); + const result = buildArcTicks(tick, buildOpts); + expect(result.x1).to.be.closeTo(355, 1); + expect(result.x2).to.be.closeTo(349, 1); + expect(result.y1).to.be.closeTo(298, 1); + expect(result.y2).to.be.closeTo(295, 1); + expect(result.value).to.equal(tickValue); + }); + it('Middle Tick', () => { + tickValue = 250; + tick = createTick(0.5, tickValue); + buildOpts.innerRect = { width: 232, height: 390 }; + const result = buildArcTicks(tick, buildOpts); + expect(result.x1).to.be.closeTo(115.5, 1); + expect(result.x2).to.be.closeTo(115.5, 1); + expect(result.y1).to.be.closeTo(87.5, 1); + expect(result.y2).to.be.closeTo(93.5, 1); + expect(result.value).to.equal(tickValue); + }); + }); +}); diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 18b99822d..7458d8e4f 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -1,7 +1,8 @@ import extend from 'extend'; function appendStyle(struct, buildOpts) { - extend(struct, buildOpts.style); + const styleClone = { ...buildOpts.style }; // Shallow clone + extend(struct, styleClone); } function polarToCartesian(centerX, centerY, radius, angle) { From a3dfb75486d2d43903aef7f5f8914351b04e9694 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Thu, 14 Nov 2024 12:49:10 +0100 Subject: [PATCH 15/19] feat: unit test for rendering radial axis --- junit.xml | 5530 +++++++++-------- .../axis/__tests__/axis.spec.js | 61 + 2 files changed, 2829 insertions(+), 2762 deletions(-) diff --git a/junit.xml b/junit.xml index 3e2ac222b..3b83516d4 100644 --- a/junit.xml +++ b/junit.xml @@ -1,19 +1,179 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + @@ -21,9 +181,9 @@ - + - + @@ -37,7 +197,7 @@ - + @@ -45,7 +205,7 @@ - + @@ -57,7 +217,7 @@ - + @@ -101,13 +261,13 @@ - + - + @@ -127,13 +287,13 @@ - + - + @@ -148,286 +308,226 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - - - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -449,9 +549,9 @@ - + - + @@ -463,7 +563,7 @@ - + @@ -474,1144 +574,1172 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + + + - + - + - - - + - + - + - + - + - + - + - + - - - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + + + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + + + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + + + - + - + - + + + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + + + - + - + + + - + - + - + - - - + - + - - - + - + - + - + - + - - - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + + + - + - + - + - + - - - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + + + - + - - + + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - + - + - + - + - + - + - + - + - + - + - + - - - - + + - + - + - + - + - + - - - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -1619,7 +1747,7 @@ - + @@ -1629,11 +1757,11 @@ - + - + @@ -1643,342 +1771,366 @@ - + - + - + - + - - + + - + - + - + - + + + - + - + - + - + - + - + - + - + - - - + - + - + - + - + + + - + - + - + - + - + - + + + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - - - + - + - - - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + - + @@ -2003,21 +2155,21 @@ - + - + - + - + - + - + @@ -2027,15 +2179,15 @@ - + - + - + - + @@ -2043,37 +2195,37 @@ - + - + - + - + - + - + - + - + - + @@ -2083,25 +2235,25 @@ - + - + - + - + - + - + - + - + - + @@ -2113,931 +2265,574 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + + + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - - - + - + - - - + - + - - - + - + - + - + - + - - - + - + - + + + - + - + - + - + - + - + - + - + - + - - - + - - - + - + - + - + - + - + - + + + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - - - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - + - + - + - - - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + @@ -3061,730 +2856,804 @@ - - + + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - - + + - + - + - + - + - + + + - + - + - + - + - + - + - + - + + + - + + + - + - + - + - + - + + + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - - - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - - - + - + - + - + - - - - + + - + + + - + - + - + - + - + - - + + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - - - + - + - + - + + + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + + + - + - - + - + - + - - - - + + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + - - + + @@ -3808,7 +3677,7 @@ - + @@ -3816,7 +3685,7 @@ - + @@ -3834,11 +3703,11 @@ - + - + @@ -3861,412 +3730,503 @@ - - + + + + + + + + + + + + + + + + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + + + - + - + - - + + - + - + - + - + - + - + + + - - + + - + - + - + - + - + - - - + - + - + - + - + + + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + + + - + - + - + - + + + - + + + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - - + + - + - - - + + + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - - - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - - - - - + + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - - - + - - + - + - + - + - + @@ -4288,705 +4248,692 @@ - - - - - - - - - - - - + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + - + - + - + - + - + + + - + - + - + - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + + - + - + - - - - + + - + - + + + - + - + - + - + - + - + - + - + - + + + - + - + + + - + - + + + - + - + - + - + - + - + - + - + - + + + - + - + - + + + - + - + - + - + - + + + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - - - + - + - + - + + - - - + - - - + - - + + - + - + - + - + - + - + - + - + - + - - - - + + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - - - + - + - - - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - - + + - + - + - + - + - + - + - + + + - + - - + + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + + + - + - + - - + + - + - - - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - - - + - + - + - + - + - - - + - + - + - + - + - + - + + + - + - + - + + + + + - - + + - + - + - + - + - + - + + + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + + + + + - - + + + + + + - + - + - + - + - + - + @@ -4997,7 +4944,7 @@ - + @@ -5022,238 +4969,319 @@ - - + + - + + - + - + - + - + + + - + - + - + - - - + - + - + - - - + - + - + + + + + - - + + - + - + - + - + - + - - - + - + - + - + - - - + - + - + - + - + + + - - + + - + - + + + - + - + + + - + - + - + - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + + + + + + + + + - - + + - + - + - + + + - + - + - - + + - + - + - - + + - + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + - - + + - + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - - + + - + + + + + - - + + @@ -5275,26 +5303,16 @@ - + - - - - - - - - - - - - + + - + - + @@ -5304,30 +5322,18 @@ - - + + - - - + - - - - - - - - + + - - - - - - + + \ No newline at end of file diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis.spec.js index 21ebd243f..00bc84247 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis.spec.js @@ -283,7 +283,68 @@ describe('Axis', () => { }); }); }); + describe('continuous arc axis', () => { + beforeEach(() => { + scale = linear(); + chart.scale.returns(scale); + opts = { + inner: { + x: 0, + y: 425, + width: 400, + height: 425, + }, + outer: { + x: 0, + y: 0, + width: 400, + height: 425, + }, + }; + config.settings.arc = { + radius: 0.5, + startAngle: (-2 * Math.PI) / 3, + endAngle: (2 * Math.PI) / 3, + }; + }); + it('should render arc axis', () => { + config.settings.labels = { show: true }; + config.settings.line = { show: true }; + componentFixture.simulateCreate(axisComponent, config); + componentFixture.simulateRender(opts); + verifyNumberOfNodes('text', 1); + verifyNumberOfNodes('line', 1); + }); + it('should not render arc axis labels when disabled', () => { + config.settings.labels = { show: false }; + config.settings.arc = { + radius: 0.5, + startAngle: (-2 * Math.PI) / 3, + endAngle: (2 * Math.PI) / 3, + }; + componentFixture.simulateCreate(axisComponent, config); + componentFixture.simulateRender(opts); + + verifyNumberOfNodes('text', 0); + verifyNumberOfNodes('line', 6); + }); + + it('should not render arc axis line when disabled', () => { + config.settings.labels = { show: true }; + config.settings.line = { show: false }; + config.settings.arc = { + radius: 0.5, + startAngle: (-2 * Math.PI) / 3, + endAngle: (2 * Math.PI) / 3, + }; + componentFixture.simulateCreate(axisComponent, config); + componentFixture.simulateRender(opts); + + verifyNumberOfNodes('text', 6); + verifyNumberOfNodes('line', 6); + }); + }); describe('continuous', () => { beforeEach(() => { scale = linear(); From 21270e7390f9aed7a00677f9fe0445563d7499a6 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Thu, 14 Nov 2024 12:55:39 +0100 Subject: [PATCH 16/19] fix: removed logs --- .../chart-components/axis/__tests__/axis-arc-label-node.spec.js | 1 - .../chart-components/axis/__tests__/axis-arc-tick-node.spec.js | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js index e56457094..ae9ac25ff 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js @@ -95,7 +95,6 @@ describe('Axis Label Node', () => { buildOpts.innerRect = { width: 213, height: 595 }; tick = createTick(0.5, '300'); const result = buildArcLabels(tick, buildOpts); - console.log(result); expect(result.x).to.be.closeTo(106.5, 2); expect(result.y).to.be.closeTo(191, 2); expect(result.anchor).to.equal('middle'); diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js index 9eb4d07f7..94e9ec1b7 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js @@ -57,7 +57,6 @@ describe('Axis Arc Tick Node', () => { tickValue = 0; tick = createTick(1, tickValue); const result = buildArcTicks(tick, buildOpts); - console.log(result); expect(result.x1).to.be.closeTo(45, 1); expect(result.x2).to.be.closeTo(51, 1); expect(result.y1).to.be.closeTo(298, 1); From ee1409526350aba0185f8e51e45064c5d1ae7c5d Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Thu, 14 Nov 2024 13:06:07 +0100 Subject: [PATCH 17/19] fix: removed chai import in unit test --- .../chart-components/axis/__tests__/axis-arc-tick-node.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js index 94e9ec1b7..f55eb1edd 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js @@ -1,4 +1,3 @@ -import { expect } from 'chai'; import buildArcTicks from '../axis-arc-tick-node'; function createTick(position, value) { From 49d2859ae387ed0e054adbbf327815ead7dae9b2 Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 18 Nov 2024 08:44:31 +0100 Subject: [PATCH 18/19] feat: added radialboundschecking and corrected unit tests --- .gitignore | 1 + .../axis/__tests__/axis-arc-label-node.spec.js | 12 ++++++------ .../axis/__tests__/axis-arc-node.spec.js | 6 +++--- .../axis/__tests__/axis-arc-tick-node.spec.js | 2 +- .../axis/axis-arc-label-node.js | 17 +++++++++++++++-- .../core/chart-components/axis/axis-arc-node.js | 4 ++-- .../chart-components/axis/axis-arc-tick-node.js | 4 ++-- 7 files changed, 30 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 026fc4e25..c34747f20 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.tmp *.log .DS_Store +junit.xml stats.json .idea/ .vscode/ diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js index ae9ac25ff..a07db5fd5 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-label-node.spec.js @@ -5,11 +5,11 @@ function createTick(position, label) { return { position, label, - value: 1.23, // just some dummy value to test node value for tracking animation + value: 1.23, }; } -describe('Axis Label Node', () => { +describe('Axis Arc Label Node', () => { const innerRect = { x: 0, y: 0, @@ -64,7 +64,7 @@ describe('Axis Label Node', () => { }); describe('Style align', () => { - it('start on left side of tick', () => { + it('the label should be placed on the left side of the tick', () => { buildOpts.align = 'top'; tick = createTick(1, '0'); const result = buildArcLabels(tick, buildOpts); @@ -73,7 +73,7 @@ describe('Axis Label Node', () => { expect(result.anchor).to.equal('end'); }); - it('start on left side of tick', () => { + it('label with different position, but should still be placed in the left side of the tick', () => { buildOpts.align = 'top'; tick = createTick(0.7, '100'); const result = buildArcLabels(tick, buildOpts); @@ -82,7 +82,7 @@ describe('Axis Label Node', () => { expect(result.anchor).to.equal('end'); }); - it('start on right side of tick', () => { + it('the label should be placed on the right side of the tick', () => { buildOpts.align = 'top'; tick = createTick(0.4, '250'); const result = buildArcLabels(tick, buildOpts); @@ -101,7 +101,7 @@ describe('Axis Label Node', () => { }); }); - describe('Not text in tick label', () => { + describe('Not text in tick label-property', () => { it('tick.label is undefined', () => { buildOpts.align = 'top'; tick = createTick(0, undefined); diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js index ef15f0cd5..74f650a82 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-node.spec.js @@ -59,12 +59,12 @@ describe('Axis Arc Line Node', () => { it('Structure Properties', () => { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; - const plotSize = Math.min(rect.height, rect.width) / 2; + const halfPlotSize = Math.min(rect.height, rect.width) / 2; expected.transform = `translate(0, 0) translate(${centerPoint.cx}, ${centerPoint.cy})`; expected.arcDatum.startAngle = buildOpts.startAngle; expected.arcDatum.endAngle = buildOpts.endAngle; - expected.desc.slice.innerRadius = buildOpts.radius * plotSize; - expected.desc.slice.outerRadius = buildOpts.radius * plotSize + buildOpts.style.strokeWidth; + expected.desc.slice.innerRadius = buildOpts.radius * halfPlotSize; + expected.desc.slice.outerRadius = buildOpts.radius * halfPlotSize + buildOpts.style.strokeWidth; expect(buildArcLine(buildOpts)).to.deep.equal(expected); }); }); diff --git a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js index f55eb1edd..d636fd886 100644 --- a/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js +++ b/packages/picasso.js/src/core/chart-components/axis/__tests__/axis-arc-tick-node.spec.js @@ -3,7 +3,7 @@ import buildArcTicks from '../axis-arc-tick-node'; function createTick(position, value) { return { position, - value, // just some dummy value to test node value for tracking animation + value, }; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index 4beef4c73..a4690fbec 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -35,6 +35,18 @@ function calculateMaxWidth(buildOpts, side, innerPos) { return maxWidth; } +function checkRadialOutOfBounds(buildOpts, innerPos, struct) { + let maxHeightTop; + let maxHeightBottom; + const textHeight = parseFloat(struct.fontSize) || 0; + maxHeightTop = innerPos.y - textHeight / 2; + maxHeightBottom = buildOpts.innerRect.height - (innerPos.y + textHeight / 2); + if (maxHeightTop < 0 || maxHeightBottom < 0) { + struct.text = ''; + } + return maxHeightBottom; +} + function appendCollider(tick, struct, buildOpts, tickPos) { collider(tick, struct, buildOpts, tickPos); } @@ -46,8 +58,8 @@ function appendBounds(struct, buildOpts) { export default function buildArcLabels(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; - const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const halfPlotSize = Math.min(rect.height, rect.width) / 2; + const innerRadius = halfPlotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.padding; const startAngle = buildOpts.startAngle; const endAngle = buildOpts.endAngle; @@ -98,5 +110,6 @@ export default function buildArcLabels(tick, buildOpts) { appendStyle(struct, buildOpts); appendBounds(struct, buildOpts); appendCollider(struct, tickPos); + checkRadialOutOfBounds(buildOpts, innerPos, struct); return struct; } diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js index 154d7a3fb..36363549a 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-node.js @@ -7,8 +7,8 @@ function appendStyle(struct, buildOpts) { export default function buildArcLine(buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; - const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const halfPlotSize = Math.min(rect.height, rect.width) / 2; + const innerRadius = halfPlotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.style.strokeWidth; const startAngle = buildOpts.startAngle; const endAngle = buildOpts.endAngle; diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js index 7458d8e4f..c4f389913 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-tick-node.js @@ -15,8 +15,8 @@ function polarToCartesian(centerX, centerY, radius, angle) { export default function buildArcTicks(tick, buildOpts) { const rect = buildOpts.innerRect; const centerPoint = { cx: rect.width / 2, cy: rect.height / 2 }; - const plotSize = Math.min(rect.height, rect.width) / 2; - const innerRadius = plotSize * buildOpts.radius; + const halfPlotSize = Math.min(rect.height, rect.width) / 2; + const innerRadius = halfPlotSize * buildOpts.radius; const outerRadius = innerRadius + buildOpts.padding; const startAngle = buildOpts.startAngle; const endAngle = buildOpts.endAngle; From 9bdd5e4dc41cebcbc7fd835f194d7a1b1ddc348e Mon Sep 17 00:00:00 2001 From: Axel Nilsson Date: Mon, 18 Nov 2024 13:35:50 +0100 Subject: [PATCH 19/19] fix: removed unnecessary collider --- .../chart-components/axis/axis-arc-label-node.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js index a4690fbec..4906402f2 100644 --- a/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js +++ b/packages/picasso.js/src/core/chart-components/axis/axis-arc-label-node.js @@ -15,14 +15,6 @@ function checkText(text) { return typeof text === 'string' || typeof text === 'number' ? text : '-'; } -function collider(struct, tickPos) { - if (struct.align === 'right') { - if (tickPos.x >= struct.x) { - struct.text = ''; - } - } -} - function calculateMaxWidth(buildOpts, side, innerPos) { let maxWidth; if (side === 'left') { @@ -47,10 +39,6 @@ function checkRadialOutOfBounds(buildOpts, innerPos, struct) { return maxHeightBottom; } -function appendCollider(tick, struct, buildOpts, tickPos) { - collider(tick, struct, buildOpts, tickPos); -} - function appendBounds(struct, buildOpts) { struct.boundingRect = buildOpts.textBounds(struct); } @@ -106,10 +94,8 @@ export default function buildArcLabels(tick, buildOpts) { baseline: 'middle', }; - const tickPos = polarToCartesian(centerPoint.cx, centerPoint.cy, outerRadius + 6, angle); appendStyle(struct, buildOpts); appendBounds(struct, buildOpts); - appendCollider(struct, tickPos); checkRadialOutOfBounds(buildOpts, innerPos, struct); return struct; }