Fix drill-down navigation and unknown subcategory colors
Bug A: Center click to go back now works after switching months while drilled down. Fixed by saving root state BEFORE drilled state in selectMonth, so historyIndex=0 always points to root. Bug B: Unknown subcategories (not in December data) now get distinct colors. Fixed by tracking unknownCount separately and using (predefinedCount + unknownIndex) % 10 to assign colors starting after the predefined palette positions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d934b5465b
commit
d93c7c6051
43
app.js
43
app.js
@ -726,10 +726,13 @@ function renderChart(data) {
|
||||
if (params.data.children && params.data.children.length > 0) {
|
||||
// Case 1: Node has children (category or subcategory)
|
||||
const sortedChildren = sortBySubcategoryOrder(params.data.children, params.name);
|
||||
const predefinedOrder = subcategoryOrder[params.name] || [];
|
||||
|
||||
// Process each child
|
||||
// Process each child, tracking unknown item count for color assignment
|
||||
let unknownCount = 0;
|
||||
sortedChildren.forEach((child, i) => {
|
||||
const color = getSubcategoryColor(params.name, child.name, i);
|
||||
const isUnknown = !predefinedOrder.includes(child.name);
|
||||
const color = getSubcategoryColor(params.name, child.name, i, isUnknown ? unknownCount++ : null);
|
||||
const newCategory = {
|
||||
name: child.name,
|
||||
value: child.value,
|
||||
@ -1078,11 +1081,16 @@ for (const category in subcategoryColors) {
|
||||
}
|
||||
|
||||
// Get color for a subcategory, using fixed mapping or fallback to index-based
|
||||
function getSubcategoryColor(category, subcategory, index) {
|
||||
// unknownIndex: for unknown subcategories, pass the count of unknown items before this one
|
||||
function getSubcategoryColor(category, subcategory, index, unknownIndex = null) {
|
||||
if (subcategoryColors[category] && subcategoryColors[category][subcategory]) {
|
||||
return subcategoryColors[category][subcategory];
|
||||
}
|
||||
return defaultColorPalette[index % defaultColorPalette.length];
|
||||
// For unknown subcategories, use colors starting after the predefined ones
|
||||
const predefinedCount = subcategoryOrder[category] ? subcategoryOrder[category].length : 0;
|
||||
// Use unknownIndex if provided, otherwise calculate from index minus predefined items that might be before
|
||||
const colorIndex = unknownIndex !== null ? unknownIndex : index;
|
||||
return defaultColorPalette[(predefinedCount + colorIndex) % defaultColorPalette.length];
|
||||
}
|
||||
|
||||
// Sort items by fixed subcategory order, with unknown items at the end sorted by value
|
||||
@ -1273,14 +1281,20 @@ function generateDrilledDownGradient(monthData, path) {
|
||||
|
||||
const gradientStops = [];
|
||||
let currentAngle = 0;
|
||||
const predefinedOrder = parentCategory ? (subcategoryOrder[parentCategory] || []) : [];
|
||||
|
||||
let unknownCount = 0;
|
||||
sortedKeys.forEach((key, index) => {
|
||||
const percentage = totals[key] / total;
|
||||
const angle = percentage * 360;
|
||||
// Use fixed subcategory colors for first level, fallback to palette for deeper levels
|
||||
const color = (level === 'subcategory' && parentCategory)
|
||||
? getSubcategoryColor(parentCategory, key, index)
|
||||
: defaultColorPalette[index % defaultColorPalette.length];
|
||||
let color;
|
||||
if (level === 'subcategory' && parentCategory) {
|
||||
const isUnknown = !predefinedOrder.includes(key);
|
||||
color = getSubcategoryColor(parentCategory, key, index, isUnknown ? unknownCount++ : null);
|
||||
} else {
|
||||
color = defaultColorPalette[index % defaultColorPalette.length];
|
||||
}
|
||||
|
||||
gradientStops.push(`${color} ${currentAngle}deg ${currentAngle + angle}deg`);
|
||||
currentAngle += angle;
|
||||
@ -1395,9 +1409,12 @@ async function loadAvailableMonths() {
|
||||
function transformDrillDownData(parentNode, parentCategoryName) {
|
||||
const newData = [];
|
||||
const sortedChildren = sortBySubcategoryOrder(parentNode.children, parentCategoryName);
|
||||
const predefinedOrder = subcategoryOrder[parentCategoryName] || [];
|
||||
|
||||
let unknownCount = 0;
|
||||
sortedChildren.forEach((child, i) => {
|
||||
const color = getSubcategoryColor(parentCategoryName, child.name, i);
|
||||
const isUnknown = !predefinedOrder.includes(child.name);
|
||||
const color = getSubcategoryColor(parentCategoryName, child.name, i, isUnknown ? unknownCount++ : null);
|
||||
const newCategory = {
|
||||
name: child.name,
|
||||
value: child.value,
|
||||
@ -1618,20 +1635,26 @@ async function selectMonth(index) {
|
||||
|
||||
if (navigatedState) {
|
||||
// Successfully navigated to (part of) the path
|
||||
// First save the root state so we can go back to it
|
||||
saveToHistory(sunburstData.data, sunburstData.total, null, true, []);
|
||||
|
||||
targetData = navigatedState.data;
|
||||
targetTotal = navigatedState.total;
|
||||
targetName = navigatedState.contextName;
|
||||
targetPath = navigatedState.path;
|
||||
|
||||
// Save the drilled-down state
|
||||
saveToHistory(targetData, targetTotal, targetName, false, targetPath);
|
||||
} else {
|
||||
// Stay at root level
|
||||
targetData = sunburstData.data;
|
||||
targetTotal = sunburstData.total;
|
||||
targetName = null;
|
||||
targetPath = [];
|
||||
}
|
||||
|
||||
// Save initial state with the path
|
||||
// Save initial state
|
||||
saveToHistory(targetData, targetTotal, targetName, true, targetPath);
|
||||
}
|
||||
|
||||
// Update the data
|
||||
option.series.data = targetData;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user