Skip to content

Commit bb13f34

Browse files
authored
Downloads chart: refactor color assignment + minor cleanups (#8618)
1 parent e372213 commit bb13f34

File tree

2 files changed

+71
-54
lines changed

2 files changed

+71
-54
lines changed

pkg/web_app/lib/src/widget/downloads_chart/widget.dart

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ void drawChart(
395395
return path;
396396
}
397397

398+
int colorIndex(int i) {
399+
// We assign colors in reverse order so that the newest versions
400+
// get the main colors.
401+
return ranges.length - i - 1;
402+
}
403+
398404
double legendX = xZero;
399405
double legendY =
400406
tickLabelYCoordinate + firstTickLabel.getBBox().height + labelPadding;
@@ -403,22 +409,22 @@ void drawChart(
403409

404410
final linePaths = <SVGPathElement>[];
405411
final areaPaths = <SVGPathElement>[];
412+
final legends = <(SVGRectElement, SVGTextElement)>[];
406413
for (int i = 0; i < ranges.length; i++) {
407-
// We add the lines and areas in reverse order so that the newest versions
408-
// get the main colors.
409-
final rangeIndex = ranges.length - 1 - i;
410-
final line = computeLinePath(lines[rangeIndex]);
414+
final line = computeLinePath(lines[i]);
411415
final path = SVGPathElement();
412-
path.setAttribute('class', '${strokeColorClass(i)} downloads-chart-line ');
416+
path.setAttribute(
417+
'class', '${strokeColorClass(colorIndex(i))} downloads-chart-line');
413418
path.setAttribute('d', '$line');
414419
path.setAttribute('clip-path', 'url(#clipRect)');
415420
linePaths.add(path);
416421
chart.append(path);
417422

418423
if (displayAreas) {
419-
final areaPath = computeLinePath(areas[rangeIndex]);
424+
final areaPath = computeLinePath(areas[i]);
420425
final area = SVGPathElement();
421-
area.setAttribute('class', '${fillColorClass(i)} downloads-chart-area ');
426+
area.setAttribute(
427+
'class', '${fillColorClass(colorIndex(i))} downloads-chart-area');
422428
area.setAttribute('d', '$areaPath');
423429
area.setAttribute('clip-path', 'url(#clipRect)');
424430
areaPaths.add(area);
@@ -428,20 +434,26 @@ void drawChart(
428434
final legend = SVGRectElement();
429435
chart.append(legend);
430436
legend.setAttribute('class',
431-
'downloads-chart-legend ${fillColorClass(i)} ${strokeColorClass(i)}');
437+
'downloads-chart-legend ${fillColorClass(colorIndex(i))} ${strokeColorClass(colorIndex(i))}');
432438
legend.setAttribute('height', '$legendHeight');
433439
legend.setAttribute('width', '$legendWidth');
434440

435441
final legendLabel = SVGTextElement();
436-
chart.append(legendLabel);
437442
legendLabel.setAttribute('class', 'downloads-chart-tick-label');
438-
legendLabel.text = ranges[ranges.length - 1 - i];
443+
legendLabel.text = ranges[i];
444+
chart.append(legendLabel);
445+
legends.add((legend, legendLabel));
446+
}
447+
448+
for (var i = legends.length - 1; i >= 0; i--) {
449+
// We traverse the legends in reverse order so that the legend of the newest
450+
// version is placed first.
451+
final (legend, legendLabel) = legends[i];
439452

440453
if (legendX + marginPadding + legendWidth + legendLabel.getBBox().width >
441454
xMax) {
442455
// There is no room for the legend and label.
443-
// Make a new line and update legendXCoor and legendYCoor accordingly.
444-
456+
// Make a new line and update legendX and legendY accordingly.
445457
legendX = xZero;
446458
legendY += 2 * marginPadding + legendHeight;
447459
}
@@ -476,67 +488,72 @@ void drawChart(
476488

477489
hideCursor(1);
478490

491+
void resetHighlights() {
492+
for (int i = 0; i < linePaths.length; i++) {
493+
final l = linePaths[i];
494+
l.removeAttribute('class');
495+
l.setAttribute(
496+
'class', '${strokeColorClass(colorIndex(i))} downloads-chart-line');
497+
498+
if (displayAreas) {
499+
areaPaths[i].removeAttribute('class');
500+
areaPaths[i].setAttribute(
501+
'class', '${fillColorClass(colorIndex(i))} downloads-chart-area');
502+
}
503+
}
504+
}
505+
479506
void setHighlights(Set<int> highlightRangeIndices) {
507+
if (highlightRangeIndices.isEmpty) {
508+
resetHighlights();
509+
}
510+
480511
for (int i = 0; i < ranges.length; i++) {
481-
final rangeIndex = ranges.length - 1 - i;
482512
linePaths[i].removeAttribute('class');
483513
if (displayAreas) {
484514
areaPaths[i].removeAttribute('class');
485515
}
486516

487-
if (highlightRangeIndices.contains(rangeIndex)) {
517+
if (highlightRangeIndices.contains(i)) {
488518
linePaths[i].setAttribute(
489-
'class', '${strokeColorClass(i)} downloads-chart-line');
519+
'class', '${strokeColorClass(colorIndex(i))} downloads-chart-line');
490520
if (displayAreas) {
491521
areaPaths[i].setAttribute(
492-
'class', '${fillColorClass(i)} downloads-chart-area');
522+
'class', '${fillColorClass(colorIndex(i))} downloads-chart-area');
493523
}
494524
} else if (highlightRangeIndices.isNotEmpty) {
495-
linePaths[i].setAttribute(
496-
'class', '${strokeColorClass(i)} downloads-chart-line-faded');
525+
linePaths[i].setAttribute('class',
526+
'${strokeColorClass(colorIndex(i))} downloads-chart-line-faded');
497527
if (displayAreas) {
498-
areaPaths[i].setAttribute(
499-
'class', '${fillColorClass(i)} downloads-chart-area-faded');
528+
areaPaths[i].setAttribute('class',
529+
'${fillColorClass(colorIndex(i))} downloads-chart-area-faded');
500530
}
501531
} else {
502532
linePaths[i].setAttribute(
503-
'class', '${strokeColorClass(i)} downloads-chart-line');
533+
'class', '${strokeColorClass(colorIndex(i))} downloads-chart-line');
504534
if (displayAreas) {
505-
areaPaths[i].setAttribute(
506-
'class', '${fillColorClass(i)} downloads-chart-area ');
535+
areaPaths[i].setAttribute('class',
536+
'${fillColorClass(colorIndex(i))} downloads-chart-area ');
507537
}
508538
}
509539
}
510540
}
511541

512-
void resetHighlights() {
513-
for (int i = 0; i < linePaths.length; i++) {
514-
final l = linePaths[i];
515-
l.removeAttribute('class');
516-
l.setAttribute('class', '${strokeColorClass(i)} downloads-chart-line');
517-
518-
if (displayAreas) {
519-
areaPaths[i].removeAttribute('class');
520-
areaPaths[i]
521-
.setAttribute('class', '${fillColorClass(i)} downloads-chart-area');
522-
}
523-
}
524-
}
525-
526542
svg.onMouseMove.listen((e) {
527543
final boundingRect = svg.getBoundingClientRect();
528-
if (e.x < boundingRect.x + xZero ||
529-
e.x > boundingRect.x + xMax ||
530-
e.y < boundingRect.y + yMax ||
531-
e.y > boundingRect.y + yZero) {
544+
final yPosition = e.y - boundingRect.y;
545+
final xPosition = e.x - boundingRect.x;
546+
547+
if (xPosition < xZero ||
548+
xPosition > xMax ||
549+
yPosition < yMax ||
550+
yPosition > yZero) {
532551
// We are outside the actual chart area
533552
resetHighlights();
534553
hideCursor(1);
535554
return;
536555
}
537556

538-
final yPosition = e.y - boundingRect.y;
539-
final xPosition = e.x - boundingRect.x;
540557
final pointPercentage = (xPosition - xZero) / chartWidth;
541558
final nearestIndex = ((values.length - 1) * pointPercentage).round();
542559
final selectedDay =
@@ -584,19 +601,19 @@ void drawChart(
584601
'${formatAbbrMonthDay(startDay)} - ${formatAbbrMonthDay(selectedDay)}');
585602

586603
final downloads = values[nearestIndex];
587-
for (int i = 0; i < downloads.length; i++) {
588-
final rangeIndex = ranges.length - 1 - i;
589-
if (downloads[rangeIndex] > 0) {
604+
for (int i = ranges.length - 1; i >= 0; i--) {
605+
// We traverse in reverse order so that the downloads of the newest
606+
// version is placed highest up in the tooltip.
607+
if (downloads[i] > 0) {
590608
// We only show the exact download count in the tooltip if it is non-zero.
591609
final square = HTMLDivElement()
592-
..setAttribute(
593-
'class', 'downloads-chart-tooltip-square ${squareColorClass(i)}');
594-
final rangeText = HTMLSpanElement()..text = '${ranges[rangeIndex]}: ';
610+
..setAttribute('class',
611+
'downloads-chart-tooltip-square ${squareColorClass(colorIndex(i))}');
612+
final rangeText = HTMLSpanElement()..text = '${ranges[i]}: ';
595613
final suffix = (displayMode == DisplayMode.percentage)
596-
? ' (${(downloads[rangeIndex] * 100 / totals[nearestIndex]).toStringAsPrecision(2)}%)'
614+
? ' (${(downloads[i] * 100 / totals[nearestIndex]).toStringAsPrecision(2)}%)'
597615
: '';
598-
final text =
599-
'${formatWithThousandSeperators(downloads[rangeIndex])}$suffix';
616+
final text = '${formatWithThousandSeperators(downloads[i])}$suffix';
600617
final downloadsText = HTMLSpanElement()
601618
..setAttribute('class', 'downloads-chart-tooltip-downloads')
602619
..text = text;
@@ -611,7 +628,7 @@ void drawChart(
611628
..append(tooltipRange)
612629
..append(downloadsText);
613630

614-
if (highlightRangeIndices.contains(rangeIndex)) {
631+
if (highlightRangeIndices.contains(i)) {
615632
rangeText.setAttribute('class', 'downloads-chart-tooltip-highlight');
616633
downloadsText.setAttribute(
617634
'class', 'downloads-chart-tooltip-highlight');

pkg/web_css/lib/src/_pkg.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@
467467
}
468468

469469
.downloads-chart-area-faded {
470-
opacity: 0.1;
470+
opacity: 0.1;
471471
}
472472

473473
.downloads-chart-stroke-blue {

0 commit comments

Comments
 (0)