Skip to content

Commit f3eb388

Browse files
authored
kb(Diagram): Update PNG export KB for dataviz components (#3218)
* kb(Diagram): Update PNG export KB for dataviz components * Update knowledge-base/qrcode-barcode-chart-export-to-image.md * Update knowledge-base/qrcode-barcode-chart-export-to-image.md
1 parent 2b8bf41 commit f3eb388

File tree

1 file changed

+137
-11
lines changed

1 file changed

+137
-11
lines changed

knowledge-base/qrcode-barcode-chart-export-to-image.md

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
2-
title: Export QRCode, Barcode, or Chart to Image
3-
description: Learn how to convert and export a Telerik Blazor QRCode, Barcode, or Chart to an image and send it to the .NET runtime.
2+
title: Export QRCode, Barcode, Chart or Diagram to Image
3+
description: Learn how to convert and export a Telerik Blazor QRCode, Barcode, Chart, or Diagram to an image and send it to the .NET runtime.
44
type: how-to
5-
page_title: How to Export Telerik QRCode, Barcode, or Chart to Image
5+
page_title: How to Export Telerik QRCode, Barcode, Chart, or Diagram to Image
66
slug: qrcode-barcode-chart-kb-export-to-image
7-
tags: telerik, blazor, qrcode, barcode, chart
8-
ticketid: 1572189, 1588186, 1667798
7+
tags: telerik, blazor, qrcode, barcode, chart, diagram
8+
ticketid: 1572189, 1588186, 1667798, 1697494, 1697884
99
res_type: kb
1010
---
1111

@@ -32,6 +32,7 @@ This KB answers the following questions:
3232
* How to create an image from the Telerik QRCode for Blazor?
3333
* How to convert a Barcode, Chart, or QRCode from SVG to an image?
3434
* How to save a Barcode or QRCode as an image?
35+
* How to export a Diagram to a PNG file?
3536

3637
## Solution
3738

@@ -48,7 +49,11 @@ When using the `SVG` rendering mode:
4849

4950
> When using a Blazor app with **Server** render mode, make sure to [increase the SignalR max message size](slug:common-kb-increase-signalr-max-message-size), otherwise the Base64 data URI may not reach the .NET runtime.
5051
51-
>caption Export QRCode, BarCode, or Chart to Image
52+
> The following examples demonstrates JavaScript APIs, which are not subject to Telerik technical support.
53+
54+
### Export BarCode, Chart and QRCode
55+
56+
>caption Export QRCode, BarCode, or Chart to PNG Image
5257
5358
````RAZOR
5459
@inject IJSRuntime js
@@ -65,7 +70,7 @@ When using the `SVG` rendering mode:
6570
</TelerikButtonGroup>
6671
6772
<TelerikButton ThemeColor="@ThemeConstants.Button.ThemeColor.Success"
68-
OnClick="@OnQrCodeExportButtonClick">Export to PNG</TelerikButton>
73+
OnClick="@OnExportButtonClick">Export to PNG</TelerikButton>
6974
7075
<div style="display: flex; gap: 2em;">
7176
<div style="flex: 1 33%;">
@@ -186,8 +191,6 @@ When using the `SVG` rendering mode:
186191
</script>
187192
188193
@code {
189-
#nullable enable
190-
191194
private RenderingMode RenderingMode { get; set; } = RenderingMode.SVG;
192195
193196
private string QrImageDataUrl { get; set; } = string.Empty;
@@ -196,7 +199,7 @@ When using the `SVG` rendering mode:
196199
private List<ChartModel> SeriesData1 { get; set; } = new();
197200
private List<ChartModel> SeriesData2 { get; set; } = new();
198201
199-
private async Task OnQrCodeExportButtonClick()
202+
private async Task OnExportButtonClick()
200203
{
201204
string jsFunctionName = RenderingMode == RenderingMode.SVG ? "getImageFromSvg" : "getImageFromCanvas";
202205
@@ -254,10 +257,133 @@ When using the `SVG` rendering mode:
254257
}
255258
````
256259

257-
> The example in this KB article demonstrates JavaScript APIs, which are not subject to Telerik technical support.
260+
### Export Diagram
261+
262+
The required approach with a Telerik Blazor Diagram is the same as described above, with one exception. The `getBlobImage` JavaScript function must receive the exact Diagram width and height, instead of `svgBox.width` and `svgBox.height`. This is because the Diagram supports panning and the `svgBox` is larger than the visible component dimensions. Using `svgBox.width` and `svgBox.height` may result in a clipped PNG image.
263+
264+
>caption Export Diagram to PNG Image
265+
266+
````RAZOR
267+
@inject IJSRuntime js
268+
269+
<TelerikButton ThemeColor="@ThemeConstants.Button.ThemeColor.Success"
270+
OnClick="@OnDiagramExportButtonClick">Export Diagram to PNG</TelerikButton>
271+
272+
<TelerikDiagram Width="@( $"{DiagramWidth}px" )" Height="@( $"{DiagramHeight}px" )" Zoom="0.8" Class="exportable-diagram">
273+
<DiagramConnectionDefaults Type="@DiagramConnectionType.Cascading" />
274+
<DiagramLayout Type="@DiagramLayoutType.Tree" />
275+
<DiagramShapeDefaults Type="@DiagramShapeType.Rectangle" />
276+
277+
<DiagramShapes>
278+
<DiagramShape Id="shape1">
279+
<DiagramShapeContent Text="Shape 1" />
280+
</DiagramShape>
281+
<DiagramShape Id="shape2">
282+
<DiagramShapeContent Text="Shape 2" />
283+
</DiagramShape>
284+
<DiagramShape Id="shape3">
285+
<DiagramShapeContent Text="Shape 3" />
286+
</DiagramShape>
287+
<DiagramShape Id="shape4">
288+
<DiagramShapeContent Text="Shape 4" />
289+
</DiagramShape>
290+
<DiagramShape Id="shape5">
291+
<DiagramShapeContent Text="Shape 5" />
292+
</DiagramShape>
293+
<DiagramShape Id="shape6">
294+
<DiagramShapeContent Text="Shape 6" />
295+
</DiagramShape>
296+
</DiagramShapes>
297+
298+
<DiagramConnections>
299+
<DiagramConnection FromId="shape1" ToId="shape2" />
300+
<DiagramConnection FromId="shape1" ToId="shape3" />
301+
<DiagramConnection FromId="shape2" ToId="shape4" />
302+
<DiagramConnection FromId="shape2" ToId="shape5" />
303+
<DiagramConnection FromId="shape3" ToId="shape6" />
304+
</DiagramConnections>
305+
</TelerikDiagram>
306+
307+
@if (!string.IsNullOrEmpty(DiagramImageDataUrl))
308+
{
309+
<h3>Diagram PNG</h3>
310+
<img src="@DiagramImageDataUrl" style="width: @(DiagramWidth)px; height: @(DiagramHeight)px;" alt="PNG from Diagram" />
311+
}
312+
313+
@* Move JavaScript code to a separate JS file *@
314+
<script suppress-error="BL9992">
315+
function getDiagramFromSvg(selector, diagramWidth, diagramHeight) {
316+
const dpr = window.devicePixelRatio;
317+
318+
const svg = document.querySelector(`${selector} svg`);
319+
if (!svg) {
320+
return;
321+
}
322+
323+
const svgBox = svg.getBBox();
324+
const svgW = diagramWidth; // svgBox.width
325+
const svgH = diagramHeight; // svgBox.height
326+
// Using svgBox.width and svgBox.height may result in a clipped image,
327+
// because the Diagram shapes can overflow their container.
328+
329+
const svgData = (new XMLSerializer()).serializeToString(svg);
330+
const svgBlob = new Blob([svgData], {
331+
type: "image/svg+xml;charset=utf-8"
332+
});
333+
const blobUrl = URL.createObjectURL(svgBlob);
334+
335+
return getBlobImage(blobUrl, svgW, svgH).then((img) => {
336+
const canvas = document.createElement("canvas");
337+
canvas.width = svgW * dpr;
338+
canvas.height = svgH * dpr;
339+
340+
const context = canvas.getContext("2d");
341+
context.imageSmoothingEnabled = false;
342+
context.drawImage(img, 0, 0, svgW * dpr, svgH * dpr);
343+
344+
URL.revokeObjectURL(blobUrl);
345+
img.parentElement.removeChild(img);
346+
347+
return canvas.toDataURL("image/png");
348+
});
349+
}
350+
351+
function getBlobImage(blobUrl, imageWidth, imageHeight) {
352+
return new Promise(function(resolve) {
353+
const img = new Image();
354+
355+
img.addEventListener("load", () => {
356+
setTimeout( () => resolve(img) );
357+
});
358+
359+
img.style.cssText = "visibility:hidden;position:absolute;top:0;left:0;";
360+
img.width = imageWidth;
361+
img.height = imageHeight;
362+
document.body.appendChild(img);
363+
364+
img.src = blobUrl;
365+
});
366+
}
367+
</script>
368+
369+
@code {
370+
private string DiagramImageDataUrl { get; set; } = string.Empty;
371+
372+
private const int DiagramWidth = 480;
373+
private const int DiagramHeight = 400;
374+
375+
private async Task OnDiagramExportButtonClick()
376+
{
377+
string jsFunctionName = "getDiagramFromSvg";
378+
379+
DiagramImageDataUrl = await js.InvokeAsync<string>(jsFunctionName, ".exportable-diagram", DiagramWidth, DiagramHeight);
380+
}
381+
}
382+
````
258383

259384
## See Also
260385

261386
* [Barcode Overview](slug:barcode-overview)
262387
* [Chart Overview](slug:components/chart/overview)
388+
* [Diagram Overview](slug:diagram-overview)
263389
* [QRCore Overview](slug:qrcode-overview)

0 commit comments

Comments
 (0)