diff --git a/frontend/src/lib/components/CampaignTrendChart.svelte b/frontend/src/lib/components/CampaignTrendChart.svelte index 9a483ae..d7a9ff8 100644 --- a/frontend/src/lib/components/CampaignTrendChart.svelte +++ b/frontend/src/lib/components/CampaignTrendChart.svelte @@ -131,6 +131,7 @@ let chartData = []; let xScale, yScale; + let useLogScale = false; // Time range filter for campaigns const timeRanges = [ @@ -277,7 +278,9 @@ const yExtent = [0, 100]; xScale = createLinearScale(xExtent, [margin.left, width - margin.right]); - yScale = createLinearScale(yExtent, [height - margin.bottom, margin.top]); + yScale = useLogScale + ? createLogScale(yExtent, [height - margin.bottom, margin.top]) + : createLinearScale(yExtent, [height - margin.bottom, margin.top]); createGridLines(svg); createAxes(svg); @@ -382,6 +385,20 @@ return (value) => r0 + k * (value - d0); } + // log scale for y axis (clamps to min > 0) + function createLogScale(domain, range) { + const [d0, d1] = domain; + const [r0, r1] = range; + const min = Math.max(d0, 0.1); + const logd0 = Math.log10(min); + const logd1 = Math.log10(d1); + const k = (r1 - r0) / (logd1 - logd0 || 1); + return (value) => { + const v = Math.max(value, 0.1); + return r0 + k * (Math.log10(v) - logd0); + }; + } + function createGridLines(svg) { // Create subtle gradient for grid lines const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'); @@ -488,7 +505,7 @@ text.setAttribute('x', (margin.left - 10).toString()); text.setAttribute('y', (y - 2).toString()); text.setAttribute('text-anchor', 'end'); - text.setAttribute('font-size', '11'); + text.setAttribute('font-size', useLogScale ? '8' : '11'); text.setAttribute( 'fill', document.documentElement.classList.contains('dark') ? '#e5e7eb' : '#6B7280' @@ -1025,7 +1042,10 @@ }); // Only create chart when width is set and chartData is ready - $: if (containerReady && chartContainer && width > 0 && chartData.length > 1 && movingAvgN) { + $: if ( + (containerReady && chartContainer && width > 0 && chartData.length > 1 && movingAvgN) || + useLogScale + ) { createChart(); } @@ -1159,6 +1179,12 @@ style="height: 1.5rem;" /> +