Skip to content

Commit 353f901

Browse files
authored
Merge pull request #5 from VisionKernel/dev
Patch fix
2 parents 48e58fd + ef6dbc4 commit 353f901

4 files changed

Lines changed: 393 additions & 63 deletions

File tree

examples/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ <h3>Dataset Manager</h3>
553553
</main>
554554

555555
<footer>
556-
<p>VisionCharts v0.2.0 | MIT License | &copy; 2025 VisionKernel Team</p>
556+
<p>VisionCharts v1.1.0 | MIT License | &copy; 2025 VisionKernel Team</p>
557557
</footer>
558558

559559
<script type="module">

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "visioncharts",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "A modern, high-performance JavaScript charting library optimized for financial and economic data visualization",
55
"type": "module",
66
"main": "dist/visioncharts.js",

src/charts/AreaChart.js

Lines changed: 146 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -466,17 +466,19 @@ export default class AreaChart extends LineChart {
466466

467467
console.log('Rendering', panelCount, 'panels');
468468

469-
// Calculate panel dimensions
470-
const panelHeight = innerHeight / panelCount;
471-
const panelMargin = 20;
472-
const effectivePanelHeight = panelHeight - panelMargin;
473-
474469
// Create panel for each dataset
475470
this.state.datasets.forEach((dataset, index) => {
471+
// Calculate panel dimensions
472+
const panelHeight = innerHeight / panelCount;
473+
const panelMargin = index === 0 ? 30 : 20; // Extra margin for first panel
474+
const effectivePanelHeight = panelHeight - panelMargin;
475+
476476
// Create panel group
477477
const panelGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
478478
panelGroup.setAttribute('class', `visioncharts-panel panel-${index}`);
479-
panelGroup.setAttribute('transform', `translate(0, ${index * panelHeight})`);
479+
// Add top margin of 10px for the first panel
480+
const yPos = index * panelHeight + (index === 0 ? 20 : 0);
481+
panelGroup.setAttribute('transform', `translate(0, ${yPos})`);
480482

481483
// Create panel background
482484
const panelBg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
@@ -489,10 +491,41 @@ export default class AreaChart extends LineChart {
489491
panelGroup.appendChild(panelBg);
490492

491493
// Create local scales for this panel
492-
const xScale = { ...this.state.scales.x };
493-
const yScale = this.options.isLogarithmic ?
494-
new LogScale([0.1, 1], [0, 1]) :
495-
new LinearScale([0, 1], [0, 1]);
494+
// Important: Create new scale instances instead of shallow copying
495+
let xScale;
496+
const { xField, xType, isLogarithmic } = this.options;
497+
498+
// Extract X values from this dataset only
499+
const xValues = dataset.data.map(d => d[xField]);
500+
501+
// Calculate domain based on dataset values
502+
let xMin, xMax;
503+
if (xType === 'time') {
504+
// For time type, handle date objects
505+
const dates = xValues.map(x => x instanceof Date ? x : new Date(x));
506+
xMin = new Date(Math.min(...dates.map(d => d.getTime())));
507+
xMax = new Date(Math.max(...dates.map(d => d.getTime())));
508+
} else {
509+
xMin = Math.min(...xValues);
510+
xMax = Math.max(...xValues);
511+
}
512+
513+
// Create appropriate scale type
514+
if (xType === 'time') {
515+
xScale = new TimeScale([xMin, xMax], [0, innerWidth]);
516+
} else if (isLogarithmic) {
517+
xScale = new LogScale([Math.max(0.01, xMin), xMax], [0, innerWidth]);
518+
} else {
519+
xScale = new LinearScale([xMin, xMax], [0, innerWidth]);
520+
}
521+
522+
// Create Y scale for this panel
523+
let yScale;
524+
if (this.options.isLogarithmic) {
525+
yScale = new LogScale([0.1, 1], [0, 1]);
526+
} else {
527+
yScale = new LinearScale([0, 1], [0, 1]);
528+
}
496529

497530
// Update Y scale range to panel height
498531
yScale.setRange([effectivePanelHeight, 0]);
@@ -543,7 +576,9 @@ export default class AreaChart extends LineChart {
543576
* @private
544577
*/
545578
renderPanelAxes(panel, xScale, yScale, width, height) {
546-
// X-axis (simplified, only draw line)
579+
const { xType, dateFormat, xField } = this.options;
580+
581+
// X-axis (draw line and labels)
547582
const xAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
548583
xAxis.setAttribute('x1', 0);
549584
xAxis.setAttribute('y1', height);
@@ -553,7 +588,84 @@ export default class AreaChart extends LineChart {
553588
xAxis.setAttribute('stroke-width', 1);
554589
panel.appendChild(xAxis);
555590

556-
// Y-axis (simplified, only show a few ticks)
591+
// Generate X ticks and labels for time axis
592+
if (xType === 'time') {
593+
// Generate 5 evenly spaced tick points
594+
const tickCount = 5;
595+
const xDomain = xScale.domain;
596+
const start = xDomain[0] instanceof Date ? xDomain[0] : new Date(xDomain[0]);
597+
const end = xDomain[1] instanceof Date ? xDomain[1] : new Date(xDomain[1]);
598+
const timeRange = end.getTime() - start.getTime();
599+
const timeStep = timeRange / (tickCount - 1);
600+
601+
// Draw ticks and labels
602+
for (let i = 0; i < tickCount; i++) {
603+
const tickTime = start.getTime() + (i * timeStep);
604+
const tickDate = new Date(tickTime);
605+
const x = xScale.scale(tickDate);
606+
607+
// Don't draw if out of bounds
608+
if (x < 0 || x > width) continue;
609+
610+
// Draw tick
611+
const tick = document.createElementNS('http://www.w3.org/2000/svg', 'line');
612+
tick.setAttribute('x1', x);
613+
tick.setAttribute('y1', height);
614+
tick.setAttribute('x2', x);
615+
tick.setAttribute('y2', height + 4);
616+
tick.setAttribute('stroke', '#ccc');
617+
tick.setAttribute('stroke-width', 1);
618+
panel.appendChild(tick);
619+
620+
// Format date for label
621+
const labelText = tickDate.toLocaleDateString(undefined,
622+
{year: 'numeric', month: 'short'});
623+
624+
// Add label
625+
const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
626+
label.textContent = labelText;
627+
label.setAttribute('x', x);
628+
label.setAttribute('y', height + 16);
629+
label.setAttribute('text-anchor', 'middle');
630+
label.setAttribute('font-size', '10px');
631+
label.setAttribute('fill', '#666');
632+
panel.appendChild(label);
633+
}
634+
} else {
635+
// For numeric axes, do similar tick generation
636+
const tickCount = 5;
637+
const xDomain = xScale.domain;
638+
const start = xDomain[0];
639+
const end = xDomain[1];
640+
const step = (end - start) / (tickCount - 1);
641+
642+
for (let i = 0; i < tickCount; i++) {
643+
const tickValue = start + (i * step);
644+
const x = xScale.scale(tickValue);
645+
646+
// Draw tick
647+
const tick = document.createElementNS('http://www.w3.org/2000/svg', 'line');
648+
tick.setAttribute('x1', x);
649+
tick.setAttribute('y1', height);
650+
tick.setAttribute('x2', x);
651+
tick.setAttribute('y2', height + 4);
652+
tick.setAttribute('stroke', '#ccc');
653+
tick.setAttribute('stroke-width', 1);
654+
panel.appendChild(tick);
655+
656+
// Add label
657+
const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
658+
label.textContent = tickValue.toFixed(1);
659+
label.setAttribute('x', x);
660+
label.setAttribute('y', height + 16);
661+
label.setAttribute('text-anchor', 'middle');
662+
label.setAttribute('font-size', '10px');
663+
label.setAttribute('fill', '#666');
664+
panel.appendChild(label);
665+
}
666+
}
667+
668+
// Y-axis (draw line and ticks)
557669
const yAxis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
558670
yAxis.setAttribute('x1', 0);
559671
yAxis.setAttribute('y1', 0);
@@ -563,16 +675,30 @@ export default class AreaChart extends LineChart {
563675
yAxis.setAttribute('stroke-width', 1);
564676
panel.appendChild(yAxis);
565677

566-
// Y-axis ticks (only show min and max)
567-
const domain = yScale.domain;
568-
const tickValues = [domain[0], (domain[0] + domain[1]) / 2, domain[1]];
678+
// Y-axis ticks (only show 3 evenly-spaced ticks)
679+
const yDomain = yScale.domain;
680+
const tickValues = [
681+
yDomain[0],
682+
yDomain[0] + (yDomain[1] - yDomain[0]) / 2,
683+
yDomain[1]
684+
];
569685

570686
tickValues.forEach(value => {
571687
const y = yScale.scale(value);
572688

573689
// Skip if out of range
574690
if (y < 0 || y > height) return;
575691

692+
// Draw tick
693+
const tick = document.createElementNS('http://www.w3.org/2000/svg', 'line');
694+
tick.setAttribute('x1', 0);
695+
tick.setAttribute('y1', y);
696+
tick.setAttribute('x2', -4); // Make tick go left instead of right
697+
tick.setAttribute('y2', y);
698+
tick.setAttribute('stroke', '#ccc');
699+
tick.setAttribute('stroke-width', 1);
700+
panel.appendChild(tick);
701+
576702
// Format label text
577703
let labelText;
578704
if (this.options.yType === 'percent') {
@@ -583,20 +709,21 @@ export default class AreaChart extends LineChart {
583709
labelText = value.toFixed(this.options.isLogarithmic ? 0 : 1);
584710
}
585711

586-
// Draw label
712+
// Draw label - POSITION CHANGED TO LEFT SIDE
587713
const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
588714
label.textContent = labelText;
589-
label.setAttribute('x', 5);
715+
label.setAttribute('x', -8); // Position to the left
590716
label.setAttribute('y', y);
591-
label.setAttribute('font-size', '10px');
717+
label.setAttribute('text-anchor', 'end'); // Right-align text
592718
label.setAttribute('dominant-baseline', 'middle');
719+
label.setAttribute('font-size', '10px');
593720
label.setAttribute('fill', '#666');
594721
panel.appendChild(label);
595722
});
596723
}
597724

598725
/**
599-
* Render data for a panel with area support
726+
* Render panel data with area support
600727
* @private
601728
*/
602729
renderPanelData(panel, dataset, xScale, yScale, panelHeight) {

0 commit comments

Comments
 (0)