Skip to content

Commit 33fbb15

Browse files
authored
Downloads chart : highlight areas on hover in stacked and percentage display mode (#8612)
1 parent 8192b6b commit 33fbb15

File tree

2 files changed

+52
-27
lines changed

2 files changed

+52
-27
lines changed

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

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ void drawChart(
198198
{DisplayMode displayMode = DisplayMode.unstacked}) {
199199
final ranges = displayLists.ranges;
200200
final values = displayLists.weekLists;
201+
final displayAreas = displayMode != DisplayMode.unstacked;
201202

202203
if (values.isEmpty) return;
203204

@@ -375,30 +376,25 @@ void drawChart(
375376
lines.add(lineCoordinates);
376377
}
377378

378-
StringBuffer computeLinePath(List<(double, double)> coordinates) {
379-
final path = StringBuffer();
380-
var command = 'M';
381-
coordinates.forEach((c) {
382-
path.write(' $command${c.$1} ${c.$2}');
383-
command = 'L';
384-
});
385-
return path;
379+
final areas = <List<(double, double)>>[];
380+
if (displayAreas) {
381+
for (int i = 0; i < ranges.length; i++) {
382+
final prevLine = i == 0 ? [(xZero, yZero), (xMax, yZero)] : lines[i - 1];
383+
final areaLine = [...lines[i], ...prevLine.reversed, lines[i].first];
384+
areas.add(areaLine);
385+
}
386386
}
387387

388-
StringBuffer computeAreaPath(List<(double, double)> topCoordinates,
389-
List<(double, double)> bottomCoordinates) {
388+
final linePaths = <SVGPathElement>[];
389+
final areaPaths = <SVGPathElement>[];
390+
391+
StringBuffer computeLinePath(List<(double, double)> coordinates) {
390392
final path = StringBuffer();
391393
var command = 'M';
392-
topCoordinates.forEach((c) {
393-
path.write(' $command${c.$1} ${c.$2}');
394-
command = 'L';
395-
});
396-
397-
bottomCoordinates.reversed.forEach((c) {
394+
coordinates.forEach((c) {
398395
path.write(' $command${c.$1} ${c.$2}');
399396
command = 'L';
400397
});
401-
path.write('Z');
402398
return path;
403399
}
404400

@@ -408,28 +404,24 @@ void drawChart(
408404
final legendWidth = 20;
409405
final legendHeight = 8;
410406

411-
final linePaths = <SVGPathElement>[];
412407
for (int i = 0; i < lines.length; i++) {
413-
// We add the lines in reverse order so that the newest versions get the
414-
// main colors.
415-
final line = computeLinePath(lines[lines.length - 1 - i]);
408+
// We add the lines and areas in reverse order so that the newest versions
409+
// get the main colors.
410+
final line = computeLinePath(lines[ranges.length - 1 - i]);
416411
final path = SVGPathElement();
417412
path.setAttribute('class', '${strokeColorClass(i)} downloads-chart-line ');
418413
path.setAttribute('d', '$line');
419414
path.setAttribute('clip-path', 'url(#clipRect)');
420415
linePaths.add(path);
421416
chart.append(path);
422417

423-
if (displayMode == DisplayMode.stacked ||
424-
displayMode == DisplayMode.percentage) {
425-
final prevLine = i == lines.length - 1
426-
? [(xZero, yZero), (xMax, yZero)]
427-
: lines[lines.length - 1 - i - 1];
428-
final areaPath = computeAreaPath(lines[lines.length - 1 - i], prevLine);
418+
if (displayAreas) {
419+
final areaPath = computeLinePath(areas[ranges.length - 1 - i]);
429420
final area = SVGPathElement();
430421
area.setAttribute('class', '${fillColorClass(i)} downloads-chart-area ');
431422
area.setAttribute('d', '$areaPath');
432423
area.setAttribute('clip-path', 'url(#clipRect)');
424+
areaPaths.add(area);
433425
chart.append(area);
434426
}
435427

@@ -487,6 +479,12 @@ void drawChart(
487479
final l = linePaths[i];
488480
l.removeAttribute('class');
489481
l.setAttribute('class', '${strokeColorClass(i)} downloads-chart-line');
482+
483+
if (displayAreas) {
484+
areaPaths[i].removeAttribute('class');
485+
areaPaths[i]
486+
.setAttribute('class', '${fillColorClass(i)} downloads-chart-area');
487+
}
490488
}
491489
}
492490

@@ -527,6 +525,14 @@ void drawChart(
527525
highlightRangeIndices.add(i);
528526
}
529527
}
528+
if (displayAreas) {
529+
for (int i = 0; i < areas.length; i++) {
530+
final a = areas[i];
531+
if (isPointInPolygon(a, (xPosition, yPosition))) {
532+
highlightRangeIndices.add(i);
533+
}
534+
}
535+
}
530536

531537
final coords = computeCoordinates(selectedDay, 0);
532538
cursor.setAttribute('transform', 'translate(${coords.$1}, 0)');
@@ -557,19 +563,34 @@ void drawChart(
557563
..text = text;
558564

559565
linePaths[i].removeAttribute('class');
566+
if (displayAreas) {
567+
areaPaths[i].removeAttribute('class');
568+
}
560569

561570
if (highlightRangeIndices.contains(rangeIndex)) {
562571
rangeText.setAttribute('class', 'downloads-chart-tooltip-highlight');
563572
downloadsText.setAttribute(
564573
'class', 'downloads-chart-tooltip-highlight');
565574
linePaths[i].setAttribute(
566575
'class', '${strokeColorClass(i)} downloads-chart-line');
576+
if (displayAreas) {
577+
areaPaths[i].setAttribute(
578+
'class', '${fillColorClass(i)} downloads-chart-area');
579+
}
567580
} else if (highlightRangeIndices.isNotEmpty) {
568581
linePaths[i].setAttribute(
569582
'class', '${strokeColorClass(i)} downloads-chart-line-faded');
583+
if (displayAreas) {
584+
areaPaths[i].setAttribute(
585+
'class', '${fillColorClass(i)} downloads-chart-area-faded');
586+
}
570587
} else {
571588
linePaths[i].setAttribute(
572589
'class', '${strokeColorClass(i)} downloads-chart-line');
590+
if (displayAreas) {
591+
areaPaths[i].setAttribute(
592+
'class', '${fillColorClass(i)} downloads-chart-area ');
593+
}
573594
}
574595
final tooltipRange = HTMLDivElement()
575596
..setAttribute('class', 'downloads-chart-tooltip-row')

pkg/web_css/lib/src/_pkg.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@
466466
opacity: 0.3;
467467
}
468468

469+
.downloads-chart-area-faded {
470+
opacity: 0.1;
471+
}
472+
469473
.downloads-chart-stroke-blue {
470474
stroke: var(--pub-downloads-chart-color-0);
471475
}

0 commit comments

Comments
 (0)