ngx-charts line chart, how to show the line chart with dot for the data point all the time
Asked Answered
M

3

7

for ngx-charts line chart, it show the line chart, but there is no dot for the data point. enter image description here

If you hover the data point, it show a dot for the data pint and also with a label tooltip.

enter image description here

I like to have the line chart to show all the data point with a dot all the time like this.

enter image description here

I need your help on how to show a dot at the data point in ngx-charts line chart

Here is the sample for ngx-chart https://github.com/kedmenecr/cinnamon-angular5-with-ngx-charts

Here is the source code for ngx-chart libary . https://github.com/swimlane/ngx-charts

thanks.

Meanwhile answered 8/5, 2019 at 23:29 Comment(2)
github.com/swimlane/ngx-charts/issues/467 refer this issue. Its not possible with ngx-charts.Inexpensive
did you find any workaround for same?Inexpensive
A
5

if anyone still needs this feature I workaround this feature with a non-super clean solution but it works with no side effect so far :

enter image description here

custom service to draw the points over liner chart:

import { Injectable } from '@angular/core';
@Injectable()
export class CustomLinerChartService {
    /**
     * custom: override SVG to have the dots display all the time over the liner chart
     * since it's not supported anymore from ngx chart
     */

    showDots(chart) {
        let index = 0;
        const paths = chart.chartElement.nativeElement.getElementsByClassName(
            'line-series'
        );
        const color = chart.chartElement.nativeElement.getElementsByClassName(
            'line-highlight'
        );

        for (let path of paths) {
            const chrtColor = color[index].getAttribute('ng-reflect-fill');
            const pathElement = path.getElementsByTagName('path')[0];
            const pathAttributes = {
                'marker-start': `url(#dot${index})`,
                'marker-mid': `url(#dot${index})`,
                'marker-end': `url(#dot${index})`
            };
            this.createMarker(chart, chrtColor, index);
            this.setAttributes(pathElement, pathAttributes);
            index += 1;
        }
    }

    /**
     * create marker
     *
     */

    createMarker(chart, color, index) {
        const svg = chart.chartElement.nativeElement.getElementsByTagName('svg');
        var marker = document.createElementNS(
            'http://www.w3.org/2000/svg',
            'marker'
        );
        var circle = document.createElementNS(
            'http://www.w3.org/2000/svg',
            'circle'
        );
        svg[0].getElementsByTagName('defs')[0].append(marker);
        marker.append(circle);
        const m = svg[0].getElementsByTagName('marker')[0];
        const c = svg[0].getElementsByTagName('circle')[0];

        const markerAttributes = {
            id: `dot${index}`,
            viewBox: '0 0 10 10',
            refX: 5,
            refY: 5,
            markerWidth: 5,
            markerHeight: 5
        };

        const circleAttributes = {
            cx: 5,
            cy: 5,
            r: 5,
            fill: color
        };
        m.append(circle);

        this.setAttributes(m, markerAttributes);
        this.setAttributes(c, circleAttributes);
    }

    /**
     * set multiple attributes
     */
    setAttributes(element, attributes) {
        for (const key in attributes) {
            element.setAttribute(key, attributes[key]);
        }
    }
}

and after your view init and the data is set to the chart call :

@ViewChild('chart') chart: any;

ngAfterViewInit() {
    this.customLinerChartService.showDots(this.chart);
}

make sure to have the reference on your chart :

<ngx-charts-line-chart #chart>

UPDATE

you can't rely on ng-reflect-fill class since it just added in development mood so insted provide your colors as array and chose it based on index for example

Award answered 19/6, 2020 at 10:9 Comment(6)
this worked great, except one issue is that with multiple charts it only draws the dots on one chart. I fixed it by adding the index in the marker and circle get elements: "const m = svg[0].getElementsByTagName('marker')[index]; const c = svg[0].getElementsByTagName('circle')[index];"Alyciaalyda
Is there any way to redraw the dots once the dataset of the chart changes?Embody
I actually just found a way, calling 'service.showDots()' manually after changing the dataset doesn't work. However doing 'setTimeout(() => { this.service.showDots(this.chart); }, 0);' works. Is there a way of doing this without using 'setTimeout()'?Embody
@Alyciaalyda in my project I'm considering each chart as a stand-alone component in this case you are goodAward
@Embody just call this guy each time you update the data : this.customLinerChartService.showDots(this.chart);Award
Is there a way to show these dots with different colors based on some custom calculation like if the value is > 80 show in red and if less than 80 then show the dot in green color?Bernt
B
1

This simpler approach first posted here also works well:

https://github.com/swimlane/ngx-charts/issues/462#issuecomment-783237600

I suggest first getting a reference to the chart, and looping through the series:

@ViewChild("numberChart", {read: ElementRef, static: false})
numberChartRef: ElementRef;
...
chartRef.nativeElement.querySelectorAll("g.line-series path").forEach((el) => {
     el.setAttribute("stroke-width", "10");
     el.setAttribute("stroke-linecap", "round");
});

I test the length of the series, and only apply these changes if the length is 1. Also make sure to return the attributes to the defaults though if you don't want extra thick lines for all your charts-

Braden answered 15/9, 2021 at 12:28 Comment(3)
what approach is better if we want to show few dots in different color?Atwood
@Braden Could You please show / describe more preciseluy Your solution ? Your code make all lines bigger,Ligni
@MateuszKaleta sorry, unless you have a codesandbox link, I can't help, I'm not using this library anymore-Braden
C
-1

I have a way simpler solution to this, just adding a single field will do the trick for you:

In your component class, set the "dot" property of the series to true:

this.data = [
  {
    name: 'Series 1',
    series: [
      {
        name: 'Point 1',
        value: 9,
      },
      {
        name: 'Point 2',
        value: 7,
      },
      {
        name: 'Point 3',
        value: 5,
      }
    ],
    dot: true
  },
  {
    name: 'Series 2',
    series: [
      {
        name: 'Point 1',
        value: 8,
      },
      {
        name: 'Point 2',
        value: 6,
      },
      {
        name: 'Point 3',
        value: 4,
      }
    ],
    dot: true
  }
];

This will show dots on the line chart on the respective data points as shown below:

Data points Highlight Single Point

Chippy answered 16/1, 2023 at 7:34 Comment(1)
this soultion does not work , could You please provide some more precise example?Ligni

© 2022 - 2024 — McMap. All rights reserved.