Articles in this section
Category / Section

How to export the JavaScript Circular Gauge with annotations?

6 mins read

The annotations set in the JavaScript Circular Gauge control will not be exported when exporting the control to an image. This is because the annotations are intended to render any items in the Circular Gauge control, such as text, images, or custom HTML elements. Since the Circular Gauge is an SVG-based control, the annotations can be rendered as foreignObject elements in the application level. It is important to note that the foreignObject element has compatibility constraints with some web browsers. This section will show you how to dynamically export the Circular Gauge with annotations using the foreignObject element.

To begin, we need to create a foreignObject element for each annotation and add it to the Circular Gauge control’s SVG element in the same positions as the control. Then, to allow image and PDF export, we must draw this SVG element in an HTML canvas element. Using the HTML image element, this canvas element can be transformed to an image. This image element is now converted to a PNG or JPEG image for export, or it can be inserted into a PDF document using Syncfusion’s ej2-pdf-export library.

In the following example, the processes described above are carried out using the “gaugeExport” method. The following example shows how to export the JavaScript Circular Gauge with annotations to PNG, JPEG, and PDF files.

[index.ts]

import { CircularGauge, Annotations, ImageExport, PdfExport } from '@syncfusion/ej2-circulargauge';
import { Export } from '@syncfusion/ej2-charts';
import { PdfDocument, PdfBitmap } from '@syncfusion/ej2-pdf-export';
CircularGauge.Inject(Annotations, Export, ImageExport, PdfExport);

let circulargauge: CircularGauge = new CircularGauge({
  allowImageExport: true,
  allowPdfExport: true,
  axes: [
    {
      lineStyle: { width: 10, color: 'transparent' },
      labelStyle: {
        position: 'Inside',
        useRangeColor: false,
        font: { size: '12px', fontFamily: 'Segoe UI', fontStyle: 'Regular' },
      },
      majorTicks: { height: 10, offset: 5 },
      minorTicks: { height: 0 },

      annotations: [
        {
          content:
            '<div><span style="font-size:14px; font-family:Segoe UI">Speedometer</span></div>',
          radius: '30%',
          angle: 0,
          zIndex: '1',
        },
        {
          content:
            '<div><span style="font-size:20px; font-family:Segoe UI">65 MPH</span></div>',
          radius: '40%',
          angle: 180,
          zIndex: '1',
        },
      ],
      startAngle: 210,
      endAngle: 150,
      minimum: 0,
      maximum: 120,
      radius: '80%',
      ranges: [
        { start: 0, end: 40, color: '#30B32D' },
        { start: 40, end: 80, color: '#FFDD00' },
        { start: 80, end: 120, color: '#F03E3E' },
      ],
      pointers: [
        {
          value: 65,
          radius: '60%',
          pointerWidth: 8,
          cap: { radius: 7 },
          needleTail: { length: '18%' },
        },
      ],
    },
  ],
});
circulargauge.appendTo('#gauge');

function gaugeExport(formatValue, fileName) {
  let svg: Element;
  let annotationEle: NodeListOf<Element> = document
    .getElementById('gauge')
    .querySelectorAll('[id*="gauge_Axis_0_Annotation_"]');
  for (let i: number = 0; i < annotationEle.length; i++) {
    let annotation: any = annotationEle[i];
    let foreign: SVGForeignObjectElement = document.createElementNS(
      'http://www.w3.org/2000/svg',
      'foreignObject'
    );
    foreign.setAttribute(
      'width',
      annotation.getBoundingClientRect().width.toString()
    );
    foreign.setAttribute(
      'height',
      annotation.getBoundingClientRect().height.toString()
    );
    foreign.setAttribute('x', annotation.style.left);
    foreign.setAttribute('y', annotation.style.top);
    foreign.innerHTML = annotation.innerHTML;
    annotation.style.display = 'none';
    svg = document.querySelector('#gauger_svg');
    svg.appendChild(foreign);
  }

  let svgData: string = new XMLSerializer().serializeToString(svg);
  let canvas: HTMLCanvasElement = document.createElement('canvas');
  document.body.appendChild(canvas);
  let svgSize: any = svg.getBoundingClientRect();
  canvas.width = svgSize.width;

  canvas.height = svgSize.height;

  let ctx: CanvasRenderingContext2D = canvas.getContext('2d');

  let img: HTMLImageElement = document.createElement('img');

  img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(svgData));

  img.onload = function () {
    ctx.drawImage(img, 0, 0);
    if (formatValue == 'PNG' || formatValue == 'JPEG') {
      let imagedata: string = canvas.toDataURL('image/png');
      let anchor: HTMLAnchorElement = document.createElement('a');
      anchor.download = fileName + '.' + formatValue;
      anchor.href = imagedata;
      document.body.appendChild(anchor);
      anchor.click();
    } else if (formatValue == 'PDF') {
      const document: PdfDocument = new PdfDocument();
      let imageString: string = canvas
        .toDataURL('image/jpeg')
        .replace('image/jpeg', 'image/octet-stream');
      imageString = imageString.slice(imageString.indexOf(',') + 1);
      document.pages
        .add()
        .graphics.drawImage(
          new PdfBitmap(imageString),
          0,
          0,
          canvas.width,
          canvas.height
        );
      if (circulargauge.allowPdfExport) {
        document.save(fileName + '.' + formatValue);
        document.destroy();
      }
    }
    canvas.remove();
  };
}

document.getElementById('export').onclick = () => {
  let formatValue: any = document.getElementById('format').value;
  let fileName : any = 'Gauge';
  gaugeExport(formatValue, fileName);
};

[index.html]

<html>  
  <body>    
    <div id="gauge"></div>
    <div>
    Export Type
       <select id="format">
          <option value="PNG">PNG</option>
          <option value="JPEG">JPEG</option>
          <option value="PDF">PDF</option>
       </select> <br /> <br />
       <button id="export">Export</button>
    </div>
  </body>
</html>

The following screenshot illustrates the output of the above code snippet.

Circular Gauge.png

View Sample in Stackblitz

Conclusion

I hope you enjoyed learning how to export the JavaScript Circular Gauge with annotations.

You can refer to our JavaScript Circular Gauge feature tour page to know about its other groundbreaking feature representations and documentation, and how to quickly get started for configuration specifications. You can also explore our JavaScript Circular Gauge example to understand how to create and manipulate data.

For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion, you can try our 30-day free trial to check out our other controls.

If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied