From eac185b09afd5fb74e09bc0b9fbde4dd29501754 Mon Sep 17 00:00:00 2001 From: Soundar Date: Tue, 26 May 2026 01:03:18 +0530 Subject: [PATCH 1/8] phase 1 - bubble chart related implementation --- demo/bubble-chart.html | 72 ++++++++++++++++++ demo/chart.html | 75 +++++++++++++++++++ src/Chart/bar.js | 4 +- src/Chart/bubble.js | 117 ++++++++++++++++++++++++++++++ src/Chart/chart.js | 22 +++++- src/Chart/graph.js | 3 +- src/Chart/line.js | 4 +- src/Chart/series.js | 4 +- src/Chart/styles/bubble-chart.css | 29 ++++++++ src/Chart/styles/index.css | 1 + src/Chart/styles/variables.css | 6 ++ 11 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 demo/bubble-chart.html create mode 100644 demo/chart.html create mode 100644 src/Chart/bubble.js create mode 100644 src/Chart/styles/bubble-chart.css diff --git a/demo/bubble-chart.html b/demo/bubble-chart.html new file mode 100644 index 0000000..7e663ab --- /dev/null +++ b/demo/bubble-chart.html @@ -0,0 +1,72 @@ + + + + + + + Bubble Chart + + + + + + +

SingleDivUI

+ +
+
+

Bubble Chart

+
+
+
+ + + + + + + \ No newline at end of file diff --git a/demo/chart.html b/demo/chart.html new file mode 100644 index 0000000..007bc54 --- /dev/null +++ b/demo/chart.html @@ -0,0 +1,75 @@ + + + + + + + Charts + + + + + + +

SingleDivUI

+ +
+
+

Line Chart

+
+
+
+

Bar Chart

+
+
+
+

Area Chart

+
+
+
+ + + + + + + \ No newline at end of file diff --git a/src/Chart/bar.js b/src/Chart/bar.js index bc3e362..04a8cad 100644 --- a/src/Chart/bar.js +++ b/src/Chart/bar.js @@ -3,7 +3,7 @@ import { convertRange, unitValue } from '../Base/util'; const BACKGROUND = '--background-'; const defaultBarSize = '60%'; -export default function Bar({ points, barSize, barColor }, { yMin, yMax, chartMax, columnSize, startPosition }) { +export default function Bar({ points, barSize, barColor }, { yMin, yMax, chartHeight, columnSize, startPosition }) { var backgroundImage = [], backgroundSize = [], backgroundPositionX = [], @@ -26,7 +26,7 @@ export default function Bar({ points, barSize, barColor }, { yMin, yMax, chartMa } points.forEach((point, index) => { - var barHeight = convertRange(point, yMin, yMax, 0, chartMax); + var barHeight = convertRange(point, yMin, yMax, 0, chartHeight); if (!(barHeight >= 0)) barHeight = 0; // '>=' is to handle the NaN as well var barPosition = (columnSize * index) + barStart; diff --git a/src/Chart/bubble.js b/src/Chart/bubble.js new file mode 100644 index 0000000..ab608f0 --- /dev/null +++ b/src/Chart/bubble.js @@ -0,0 +1,117 @@ +import { convertRange, unitValue } from '../Base/util'; + +const BACKGROUND = '--background-'; +const defaultBubbleRadius = 10; + +export default function Bubble( + { + points, + bubbleColor, + bubbleBorderColor, + bubbleBorderWidth, + bubbleOpacity + }, + { + yMin, + yMax, + chartHeight, + chartWidth, + startPosition + } +) { + var backgroundImage = [], + backgroundSize = [], + backgroundPosition = [], + styles = {}; + + // TEMPORARY + // later this should come from graph.js + var xMin = 0; + var xMax = 4; + + // usable graph width + // var chartWidth = chartHeight; + + points.forEach(function(point, index) { + var xValue, yValue, radius; + + if (point !== null && typeof point === 'object') { + xValue = point.x; + yValue = point.y; + + radius = parseFloat(point.r) > 0 + ? parseFloat(point.r) + : defaultBubbleRadius; + } + else { + xValue = index; + yValue = point; + radius = defaultBubbleRadius; + } + + // convert x coordinate + var bubbleX = convertRange( + xValue, + xMin, + xMax, + 0, + chartWidth + ); + + // convert y coordinate + var bubbleY = convertRange( + yValue, + yMin, + yMax, + 0, + chartHeight + ); + + if (!(bubbleX >= 0)) { + bubbleX = 0; + } + + if (!(bubbleY >= 0)) { + bubbleY = 0; + } + + var diameter = radius * 2; + + // final render positions + var posX = startPosition + bubbleX - radius; + + var posY = chartHeight - bubbleY - radius; + + // bubble style + var getBubbleImage = function() { + // return ` + // radial-gradient( + // circle, + // ${bubbleColor} 62%, + // ${bubbleBorderColor} 62%, + // ${bubbleBorderColor} calc(62% + ${bubbleBorderWidth}), + // transparent calc(62% + ${bubbleBorderWidth}) + // ) + // `; + + return 'var(--bubble)'; + }; + + backgroundImage.push(getBubbleImage()); + + backgroundSize.push( + unitValue(diameter) + ' ' + unitValue(diameter) + ); + + backgroundPosition.push( + unitValue(posX) + ' ' + unitValue(posY) + ); + }); + + styles[BACKGROUND + 'image'] = backgroundImage.join(', '); + styles[BACKGROUND + 'size'] = backgroundSize.join(', '); + styles[BACKGROUND + 'position'] = backgroundPosition.join(', '); + styles['--bubble-opacity'] = bubbleOpacity || 1; + + return styles; +} \ No newline at end of file diff --git a/src/Chart/chart.js b/src/Chart/chart.js index d4134b7..7d516a2 100644 --- a/src/Chart/chart.js +++ b/src/Chart/chart.js @@ -68,7 +68,16 @@ Chart.prototype = { xAxis: { verticalLabel: false, padding: [0, 0], - labelFormatter: null + labelFormatter: null, + + maxTicks: 10, + startFromZero: false, + + customScale: { + min: null, + max: null, + interval: null + } }, yAxis: { maxTicks: 10, @@ -134,6 +143,17 @@ Chart.prototype = { var xAxisData = data.labels; var yAxisData = seriesObj.points; + // bubble chart uses true XY coordinates + if (type === 'bubble') { + xAxisData = seriesObj.points.map(function(p) { + return (p !== null && typeof p === 'object') ? p.x : p; + }); + + yAxisData = seriesObj.points.map(function(p) { + return (p !== null && typeof p === 'object') ? p.y : p; + }); + } + // bar chart needs an additional column, since each bar renders in-between the column var needExtraColumn = (type === 'bar'); diff --git a/src/Chart/graph.js b/src/Chart/graph.js index 5c98afb..c4fae8a 100644 --- a/src/Chart/graph.js +++ b/src/Chart/graph.js @@ -60,7 +60,8 @@ export default function Graph(height, width, xData, yData, graphSettings, extraC row, col, rowSize, columnSize, yMin, yMax, - chartMax: height, + chartHeight: height, + chartWidth: width, startPosition, styles: { common: commonStyles, diff --git a/src/Chart/line.js b/src/Chart/line.js index ef6663d..9a04051 100644 --- a/src/Chart/line.js +++ b/src/Chart/line.js @@ -2,7 +2,7 @@ import { convertRange, calculateAngle, unitValue } from '../Base/util'; const BACKGROUND = '--background-'; -export default function Line({ points, pointRadius, pointStyle, lineSize, isArea }, { columnSize, yMin, yMax, chartMax, startPosition } +export default function Line({ points, pointRadius, pointStyle, lineSize, isArea }, { columnSize, yMin, yMax, chartHeight, startPosition } ) { var defaultPointRadius = isArea ? 0 : 6, backgroundImage = [], @@ -24,7 +24,7 @@ export default function Line({ points, pointRadius, pointStyle, lineSize, isArea } points.forEach((point, index) => { - var pointY = convertRange(point, yMin, yMax, 0, chartMax) + layerPaddingY; + var pointY = convertRange(point, yMin, yMax, 0, chartHeight) + layerPaddingY; if (showPoint) { var doubleIndex = index * 2; diff --git a/src/Chart/series.js b/src/Chart/series.js index 0dd8b3b..706635b 100644 --- a/src/Chart/series.js +++ b/src/Chart/series.js @@ -1,12 +1,14 @@ import Line from './line'; import Bar from './bar'; import Area from './area'; +import Bubble from './bubble'; import { convertObjToStyles } from './../Base/util'; const series = { line: Line, bar: Bar, - area: Area + area: Area, + bubble: Bubble } // barSize - this value directly used in bar, so this can be ignored diff --git a/src/Chart/styles/bubble-chart.css b/src/Chart/styles/bubble-chart.css new file mode 100644 index 0000000..219f2d1 --- /dev/null +++ b/src/Chart/styles/bubble-chart.css @@ -0,0 +1,29 @@ +.sd-bubble::before { + display: flex; + content: ""; + + height: 100%; + width: 100%; + + top: 0; + left: 0; + + background-image: var(--background-image); + background-size: var(--background-size); + background-position: var(--background-position); + background-repeat: no-repeat; +} + +.sd-bubble { + --bubble-color: #6d81f0; + --bubble-border-color: #4a5fd4; + --bubble-border-width: 2px; + + --bubble: radial-gradient( + circle, + var(--bubble-color) 62%, + var(--bubble-border-color) 62%, + var(--bubble-border-color) calc(62% + var(--bubble-border-width)), + transparent calc(62% + var(--bubble-border-width)) + ); +} diff --git a/src/Chart/styles/index.css b/src/Chart/styles/index.css index ae6f466..95f212b 100644 --- a/src/Chart/styles/index.css +++ b/src/Chart/styles/index.css @@ -2,3 +2,4 @@ @import url(./graph.css); @import url(./line-chart.css); @import url(./bar-chart.css); +@import url(./bubble-chart.css); diff --git a/src/Chart/styles/variables.css b/src/Chart/styles/variables.css index 5fc89ab..9fcbb6d 100644 --- a/src/Chart/styles/variables.css +++ b/src/Chart/styles/variables.css @@ -24,4 +24,10 @@ /* Area chart related styles */ --area-color: #6d81f04d; --area-top-color: transparent; + + /* Bubble chart related styles */ + --bubble-color: #6d81f0; + --bubble-border-color: #6d81f0; + --bubble-border-width: 2px; + --bubble-opacity: 0.7; } From 12b383d2aff1a1959b90e2163c004987495b40e7 Mon Sep 17 00:00:00 2001 From: Soundar Date: Tue, 26 May 2026 01:16:23 +0530 Subject: [PATCH 2/8] bubble.js - code cleanup --- src/Chart/bubble.js | 80 ++++++--------------------------------------- 1 file changed, 10 insertions(+), 70 deletions(-) diff --git a/src/Chart/bubble.js b/src/Chart/bubble.js index ab608f0..70469d6 100644 --- a/src/Chart/bubble.js +++ b/src/Chart/bubble.js @@ -3,22 +3,7 @@ import { convertRange, unitValue } from '../Base/util'; const BACKGROUND = '--background-'; const defaultBubbleRadius = 10; -export default function Bubble( - { - points, - bubbleColor, - bubbleBorderColor, - bubbleBorderWidth, - bubbleOpacity - }, - { - yMin, - yMax, - chartHeight, - chartWidth, - startPosition - } -) { +export default function Bubble({ points, bubbleOpacity }, { yMin, yMax, chartHeight, chartWidth, startPosition }) { var backgroundImage = [], backgroundSize = [], backgroundPosition = [], @@ -29,9 +14,6 @@ export default function Bubble( var xMin = 0; var xMax = 4; - // usable graph width - // var chartWidth = chartHeight; - points.forEach(function(point, index) { var xValue, yValue, radius; @@ -49,63 +31,21 @@ export default function Bubble( radius = defaultBubbleRadius; } - // convert x coordinate - var bubbleX = convertRange( - xValue, - xMin, - xMax, - 0, - chartWidth - ); - - // convert y coordinate - var bubbleY = convertRange( - yValue, - yMin, - yMax, - 0, - chartHeight - ); - - if (!(bubbleX >= 0)) { - bubbleX = 0; - } - - if (!(bubbleY >= 0)) { - bubbleY = 0; - } - var diameter = radius * 2; + // convert x, y coordinate + var bubbleX = convertRange(xValue, xMin, xMax, 0, chartWidth); + var bubbleY = convertRange(yValue, yMin, yMax, 0, chartHeight); + + if (!(bubbleX >= 0)) bubbleX = 0; + if (!(bubbleY >= 0)) bubbleY = 0; // final render positions var posX = startPosition + bubbleX - radius; - var posY = chartHeight - bubbleY - radius; - // bubble style - var getBubbleImage = function() { - // return ` - // radial-gradient( - // circle, - // ${bubbleColor} 62%, - // ${bubbleBorderColor} 62%, - // ${bubbleBorderColor} calc(62% + ${bubbleBorderWidth}), - // transparent calc(62% + ${bubbleBorderWidth}) - // ) - // `; - - return 'var(--bubble)'; - }; - - backgroundImage.push(getBubbleImage()); - - backgroundSize.push( - unitValue(diameter) + ' ' + unitValue(diameter) - ); - - backgroundPosition.push( - unitValue(posX) + ' ' + unitValue(posY) - ); + backgroundImage.push('var(--bubble)'); + backgroundSize.push(unitValue(diameter) + ' ' + unitValue(diameter)); + backgroundPosition.push(unitValue(posX) + ' ' + unitValue(posY)); }); styles[BACKGROUND + 'image'] = backgroundImage.join(', '); From 6fe3d1b5698c0d03061359d698668450bd741a5d Mon Sep 17 00:00:00 2001 From: Soundar Date: Tue, 26 May 2026 17:36:54 +0530 Subject: [PATCH 3/8] bubble chart - code optimization --- src/Chart/bubble.js | 46 ++++++++++------------------------ src/Chart/chart.js | 2 +- src/Chart/graph.js | 30 +++++++++++++++++----- src/Chart/styles/variables.css | 1 - 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/Chart/bubble.js b/src/Chart/bubble.js index 70469d6..c0da7b0 100644 --- a/src/Chart/bubble.js +++ b/src/Chart/bubble.js @@ -1,43 +1,24 @@ import { convertRange, unitValue } from '../Base/util'; -const BACKGROUND = '--background-'; const defaultBubbleRadius = 10; -export default function Bubble({ points, bubbleOpacity }, { yMin, yMax, chartHeight, chartWidth, startPosition }) { +export default function Bubble({ points }, { xMin, xMax, yMin, yMax, chartHeight, chartWidth, startPosition }) { var backgroundImage = [], backgroundSize = [], backgroundPosition = [], styles = {}; - // TEMPORARY - // later this should come from graph.js - var xMin = 0; - var xMax = 4; - - points.forEach(function(point, index) { - var xValue, yValue, radius; - - if (point !== null && typeof point === 'object') { - xValue = point.x; - yValue = point.y; - - radius = parseFloat(point.r) > 0 - ? parseFloat(point.r) - : defaultBubbleRadius; - } - else { - xValue = index; - yValue = point; - radius = defaultBubbleRadius; + points.forEach(function(point) { + if (typeof point !== 'object') { + return; } - var diameter = radius * 2; - // convert x, y coordinate - var bubbleX = convertRange(xValue, xMin, xMax, 0, chartWidth); - var bubbleY = convertRange(yValue, yMin, yMax, 0, chartHeight); + // convert the point x, y coordinate to the bubble position in the chart + var bubbleX = convertRange(point.x, xMin, xMax, 0, chartWidth); + var bubbleY = convertRange(point.y, yMin, yMax, 0, chartHeight); - if (!(bubbleX >= 0)) bubbleX = 0; - if (!(bubbleY >= 0)) bubbleY = 0; + var radius = point.r || defaultBubbleRadius; + var diameter = radius * 2; // final render positions var posX = startPosition + bubbleX - radius; @@ -48,10 +29,9 @@ export default function Bubble({ points, bubbleOpacity }, { yMin, yMax, chartHei backgroundPosition.push(unitValue(posX) + ' ' + unitValue(posY)); }); - styles[BACKGROUND + 'image'] = backgroundImage.join(', '); - styles[BACKGROUND + 'size'] = backgroundSize.join(', '); - styles[BACKGROUND + 'position'] = backgroundPosition.join(', '); - styles['--bubble-opacity'] = bubbleOpacity || 1; + styles['--background-image'] = backgroundImage.join(', '); + styles['--background-size'] = backgroundSize.join(', '); + styles['--background-position'] = backgroundPosition.join(', '); return styles; -} \ No newline at end of file +} diff --git a/src/Chart/chart.js b/src/Chart/chart.js index 7d516a2..434b4d9 100644 --- a/src/Chart/chart.js +++ b/src/Chart/chart.js @@ -158,7 +158,7 @@ Chart.prototype = { var needExtraColumn = (type === 'bar'); // render the Graph - var graph = new Graph(chartHeight, chartWidth, xAxisData, yAxisData, graphSettings, needExtraColumn); + var graph = new Graph(chartHeight, chartWidth, xAxisData, yAxisData, graphSettings, needExtraColumn, type); // render the Series var series = new Series(seriesObj, graph); diff --git a/src/Chart/graph.js b/src/Chart/graph.js index c4fae8a..a2b6f27 100644 --- a/src/Chart/graph.js +++ b/src/Chart/graph.js @@ -6,7 +6,7 @@ const math = Math; const isNumber = (val) => !isNaN(parseFloat(val)); const WHITESPACE_CHAR = ' '; -export default function Graph(height, width, xData, yData, graphSettings, extraColumn) { +export default function Graph(height, width, xData, yData, graphSettings, extraColumn, type) { var { xAxis = {}, yAxis = {} } = graphSettings; var xAxisSetting = Object.assign({}, graphSettings, xAxis); var yAxisSetting = Object.assign({}, graphSettings, yAxis); @@ -16,20 +16,37 @@ export default function Graph(height, width, xData, yData, graphSettings, extraC var pLeft = paddingX[0] || 0, pRight = paddingX[1] || 0; if (extraColumn) pLeft += 1; + var xMin = 0, xMax = xData.length - 1, scaleXData = xData; + + // bubble chart uses scale based x-axis + if (type === 'bubble') { + var { min, max, scale } = generateScaleY(xData, xAxisSetting); + + xMin = min; + xMax = max; + scaleXData = scale.reverse(); + } + // generate scale-y (based on the scale only we can calculate the row and rowSize) - var { min: yMin, max: yMax, scale: scaleY } = generateScaleY(yData, yAxisSetting); + var { min: yMin, max: yMax, scale: scaleY } = generateScaleY(yData, yAxisSetting, true); var row = scaleY.length - 1, rowSize = height / row; - var col = (xData.length - 1) + (pLeft + pRight), columnSize = width / col; + var col = (xMax - xMin) + (pLeft + pRight), columnSize = width / col; + + if (type === 'bubble') { + col = scaleXData.length - 1 + (pLeft + pRight); + columnSize = width / col; + } + // to round the nearby value of 0.5 // this is crucial part, since round-off the columnSize might lead the gap inbetween area columnSize = Math.floor(columnSize / 0.5) * 0.5; // format the X and Y labels, if the formatter is available scaleY = formatData(scaleY, yAxisSetting.labelFormatter); - xData = formatData(xData, xAxisSetting.labelFormatter); + scaleXData = formatData(scaleXData, xAxisSetting.labelFormatter); // generate scale-x - var scaleX = generateScaleX(xData, columnSize, xAxisSetting); + var scaleX = generateScaleX(scaleXData, columnSize, xAxisSetting); var startPosition = columnSize * pLeft; var yLabelWidth = getMaxLabelWidth(scaleY, yAxisSetting); @@ -59,6 +76,7 @@ export default function Graph(height, width, xData, yData, graphSettings, extraC return { row, col, rowSize, columnSize, + xMin, xMax, yMin, yMax, chartHeight: height, chartWidth: width, @@ -161,4 +179,4 @@ function convertPropsToStyles(xAxisSetting, yAxisSetting) { // merge the xAxis, yAxis and Common styles return Object.assign({}, commonStyles, xAxisStyles, yAxisStyles); -} +} \ No newline at end of file diff --git a/src/Chart/styles/variables.css b/src/Chart/styles/variables.css index 9fcbb6d..90f2e1f 100644 --- a/src/Chart/styles/variables.css +++ b/src/Chart/styles/variables.css @@ -29,5 +29,4 @@ --bubble-color: #6d81f0; --bubble-border-color: #6d81f0; --bubble-border-width: 2px; - --bubble-opacity: 0.7; } From a0f6d4a0195c7297322594c20d13a7b1aa5bb62e Mon Sep 17 00:00:00 2001 From: Soundar Date: Tue, 26 May 2026 18:06:58 +0530 Subject: [PATCH 4/8] graph.js - code optimization --- src/Chart/graph.js | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Chart/graph.js b/src/Chart/graph.js index a2b6f27..e29d8f3 100644 --- a/src/Chart/graph.js +++ b/src/Chart/graph.js @@ -16,31 +16,28 @@ export default function Graph(height, width, xData, yData, graphSettings, extraC var pLeft = paddingX[0] || 0, pRight = paddingX[1] || 0; if (extraColumn) pLeft += 1; - var xMin = 0, xMax = xData.length - 1, scaleXData = xData; - - // bubble chart uses scale based x-axis - if (type === 'bubble') { - var { min, max, scale } = generateScaleY(xData, xAxisSetting); - - xMin = min; - xMax = max; - scaleXData = scale.reverse(); - } - - // generate scale-y (based on the scale only we can calculate the row and rowSize) - var { min: yMin, max: yMax, scale: scaleY } = generateScaleY(yData, yAxisSetting, true); - var row = scaleY.length - 1, rowSize = height / row; - var col = (xMax - xMin) + (pLeft + pRight), columnSize = width / col; - + var col, xMin, xMax, scaleXData; if (type === 'bubble') { + // bubble chart uses scale based x-axis + ({ min: xMin, max: xMax, scale: scaleXData } = generateScaleY(xData, xAxisSetting)); col = scaleXData.length - 1 + (pLeft + pRight); - columnSize = width / col; + scaleXData.reverse(); + } + else { + xMin = 0, xMax = xData.length - 1, scaleXData = xData; + col = (xMax - xMin) + (pLeft + pRight); } + var columnSize = width / col; // to round the nearby value of 0.5 // this is crucial part, since round-off the columnSize might lead the gap inbetween area columnSize = Math.floor(columnSize / 0.5) * 0.5; + // generate scale-y (based on the scale only we can calculate the row and rowSize) + var { min: yMin, max: yMax, scale: scaleY } = generateScaleY(yData, yAxisSetting, true); + var row = scaleY.length - 1; + var rowSize = height / row; + // format the X and Y labels, if the formatter is available scaleY = formatData(scaleY, yAxisSetting.labelFormatter); scaleXData = formatData(scaleXData, xAxisSetting.labelFormatter); From 9391cdc3fcb869d99a1ecd983bc37a954bb0d139 Mon Sep 17 00:00:00 2001 From: Soundar Date: Tue, 26 May 2026 18:41:24 +0530 Subject: [PATCH 5/8] bubble related code cleanup --- src/Chart/chart.js | 14 +++----------- src/Chart/graph.js | 30 +++++++++++++++++------------- src/Chart/linear-scale.js | 5 +++-- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Chart/chart.js b/src/Chart/chart.js index 434b4d9..3225e1f 100644 --- a/src/Chart/chart.js +++ b/src/Chart/chart.js @@ -145,20 +145,12 @@ Chart.prototype = { // bubble chart uses true XY coordinates if (type === 'bubble') { - xAxisData = seriesObj.points.map(function(p) { - return (p !== null && typeof p === 'object') ? p.x : p; - }); - - yAxisData = seriesObj.points.map(function(p) { - return (p !== null && typeof p === 'object') ? p.y : p; - }); + xAxisData = seriesObj.points.map((p) => p.x); + yAxisData = seriesObj.points.map((p) => p.y); } - // bar chart needs an additional column, since each bar renders in-between the column - var needExtraColumn = (type === 'bar'); - // render the Graph - var graph = new Graph(chartHeight, chartWidth, xAxisData, yAxisData, graphSettings, needExtraColumn, type); + var graph = new Graph(chartHeight, chartWidth, xAxisData, yAxisData, graphSettings, type); // render the Series var series = new Series(seriesObj, graph); diff --git a/src/Chart/graph.js b/src/Chart/graph.js index e29d8f3..d0c693e 100644 --- a/src/Chart/graph.js +++ b/src/Chart/graph.js @@ -3,30 +3,34 @@ import { convertObjToStyles, unitValue } from './../Base/util'; import { calculateTextWidth } from './../Base/dom-utill'; const math = Math; -const isNumber = (val) => !isNaN(parseFloat(val)); +const isNumber = (val) => Number.isFinite(Number(val)); const WHITESPACE_CHAR = ' '; -export default function Graph(height, width, xData, yData, graphSettings, extraColumn, type) { +export default function Graph(height, width, xData, yData, graphSettings, type) { var { xAxis = {}, yAxis = {} } = graphSettings; var xAxisSetting = Object.assign({}, graphSettings, xAxis); var yAxisSetting = Object.assign({}, graphSettings, yAxis); + var isCategoricalXAxis = (type !== 'bubble'); + // bar chart needs an additional column, since each bar renders in-between the column + var needExtraColumn = (type === 'bar'); + var paddingX = xAxisSetting.padding; - paddingX = (paddingX instanceof Array) ? paddingX : [0, 0]; + paddingX = Array.isArray(paddingX) ? paddingX : [0, 0]; var pLeft = paddingX[0] || 0, pRight = paddingX[1] || 0; - if (extraColumn) pLeft += 1; + if (needExtraColumn) pLeft += 1; var col, xMin, xMax, scaleXData; - if (type === 'bubble') { - // bubble chart uses scale based x-axis - ({ min: xMin, max: xMax, scale: scaleXData } = generateScaleY(xData, xAxisSetting)); - col = scaleXData.length - 1 + (pLeft + pRight); - scaleXData.reverse(); - } - else { + if (isCategoricalXAxis) { + // label/index based logic for x-axis xMin = 0, xMax = xData.length - 1, scaleXData = xData; col = (xMax - xMin) + (pLeft + pRight); } + else { + // bubble chart uses scale based x-axis + ({ min: xMin, max: xMax, scale: scaleXData } = generateScale(xData, xAxisSetting)); + col = scaleXData.length - 1 + (pLeft + pRight); + } var columnSize = width / col; // to round the nearby value of 0.5 @@ -34,7 +38,7 @@ export default function Graph(height, width, xData, yData, graphSettings, extraC columnSize = Math.floor(columnSize / 0.5) * 0.5; // generate scale-y (based on the scale only we can calculate the row and rowSize) - var { min: yMin, max: yMax, scale: scaleY } = generateScaleY(yData, yAxisSetting, true); + var { min: yMin, max: yMax, reverseScale: scaleY } = generateScale(yData, yAxisSetting); var row = scaleY.length - 1; var rowSize = height / row; @@ -142,7 +146,7 @@ function generateScaleX(xData, columnSize, { labelFontSize, labelFontFamily, ver return xLabel; } -function generateScaleY(data, { maxTicks, startFromZero, customScale }) { +function generateScale(data, { maxTicks, startFromZero, customScale }) { var minValue, maxValue, step; var { min, max, interval } = customScale; if (isNumber(min)) minValue = parseFloat(min); diff --git a/src/Chart/linear-scale.js b/src/Chart/linear-scale.js index c3f4c60..505e98a 100644 --- a/src/Chart/linear-scale.js +++ b/src/Chart/linear-scale.js @@ -20,12 +20,13 @@ export default function LinearScale(minPoint, maxPoint, maxTicks, stepSize) { for(let i=0; i<=count; i++) { result.push(lBound + (i * stepSize)); } - result.reverse(); + var reverseScale = result.slice().reverse(); return { min: lBound, - max: result[0], + max: reverseScale[0], scale: result, + reverseScale, step: stepSize }; } From b303aebf7d91282a22070bc6e54e1ebf9ad3087c Mon Sep 17 00:00:00 2001 From: Soundar Date: Wed, 27 May 2026 00:28:08 +0530 Subject: [PATCH 6/8] bubble circle size issue fixed --- src/Chart/styles/bubble-chart.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Chart/styles/bubble-chart.css b/src/Chart/styles/bubble-chart.css index 219f2d1..2af9b69 100644 --- a/src/Chart/styles/bubble-chart.css +++ b/src/Chart/styles/bubble-chart.css @@ -19,11 +19,12 @@ --bubble-border-color: #4a5fd4; --bubble-border-width: 2px; + --_bubble-size: 70%; --bubble: radial-gradient( circle, - var(--bubble-color) 62%, - var(--bubble-border-color) 62%, - var(--bubble-border-color) calc(62% + var(--bubble-border-width)), - transparent calc(62% + var(--bubble-border-width)) + var(--bubble-color) calc(var(--_bubble-size) - var(--bubble-border-width)), + var(--bubble-border-color) calc(var(--_bubble-size) - var(--bubble-border-width)), + var(--bubble-border-color) var(--_bubble-size), + transparent calc(var(--_bubble-size)) ); } From af332aad94fc0256ae5e53dd6d3abe6f317ca8da Mon Sep 17 00:00:00 2001 From: Soundar Date: Wed, 27 May 2026 00:33:40 +0530 Subject: [PATCH 7/8] bubble default values updated --- demo/bubble-chart.html | 105 ++++++++++++++++++++++++------ src/Chart/styles/bubble-chart.css | 4 +- 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/demo/bubble-chart.html b/demo/bubble-chart.html index 7e663ab..bd41c6c 100644 --- a/demo/bubble-chart.html +++ b/demo/bubble-chart.html @@ -20,6 +20,10 @@

Bubble Chart

+ + diff --git a/src/Chart/chart.js b/src/Chart/chart.js index 3225e1f..32197a5 100644 --- a/src/Chart/chart.js +++ b/src/Chart/chart.js @@ -51,7 +51,12 @@ Chart.prototype = { barColor: null, // ------ for area-chart related customizations ------ - areaColor: null + areaColor: null, + + // ------ for bubble-chart related customizations ------ + bubbleColor: null, + bubbleBorderColor: null, + bubbleBorderWidth: null, }, }, diff --git a/src/Chart/styles/bubble-chart.css b/src/Chart/styles/bubble-chart.css index 656b771..5e88f26 100644 --- a/src/Chart/styles/bubble-chart.css +++ b/src/Chart/styles/bubble-chart.css @@ -15,10 +15,6 @@ } .sd-bubble { - --bubble-color: #6d81f0ab; - --bubble-border-color: #4a5fd4; - --bubble-border-width: 1px; - --_bubble-size: 70%; --bubble: radial-gradient( circle, diff --git a/src/Chart/styles/variables.css b/src/Chart/styles/variables.css index 90f2e1f..6a1891a 100644 --- a/src/Chart/styles/variables.css +++ b/src/Chart/styles/variables.css @@ -26,7 +26,7 @@ --area-top-color: transparent; /* Bubble chart related styles */ - --bubble-color: #6d81f0; - --bubble-border-color: #6d81f0; - --bubble-border-width: 2px; + --bubble-color: #6d81f091; + --bubble-border-color: #4a5fd4; + --bubble-border-width: 1px; }