Export a D3 chart

It is possible to export D3-based visualizations with FusionExport. To demonstrate, we will export this chord diagram .

Let’s create a template file named template.html and load the d3.js library. Write the necessary code to render the chord diagram. Now, use the --asyncCapture CLI option to hook into D3’s rendering life-cycle and export the chart after D3 completes the rendering.
template.html

    <!DOCTYPE html>
        <meta charset="utf-8">
        <style>
          body {
            font: 10px sans-serif;
          }

          .chord {
            fill-opacity: .67;
          }
        </style>

        <body>
          <script src=" https://d3js.org/d3.v3.min.js"></script >
          <script>
            var outerRadius = 1366 / 2,
              innerRadius = outerRadius - 130;

            var fill = d3.scale.category20c();

            var chord = d3.layout.chord()
              .padding(.04)
              .sortSubgroups(d3.descending)
              .sortChords(d3.descending);

            var arc = d3.svg.arc()
              .innerRadius(innerRadius)
              .outerRadius(innerRadius + 20);

            var svg = d3.select("body").append("svg")
              .attr("width", outerRadius  2)
              .attr("height", outerRadius  2)
              .append("g")
              .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");

            d3.json(
              " https://gist.githubusercontent.com/sandeep1995/141a2045ab9e4c8f450c970682b89b00/raw/7aacb8a793c2d9e0ed60ad0251e1b754b2c430f2/filename.json" ,
              function(error, imports) {
                if (error) throw error;

                var indexByName = d3.map(),
                  nameByIndex = d3.map(),
                  matrix = [],
                  n = 0;

                // Returns the Flare package name for the given class name.
                function name(name) {
                  return name.substring(0, name.lastIndexOf(".")).substring(6);
                }

                // Compute a unique index for each package name.
                imports.forEach(function(d) {
                  if (!indexByName.has(d = name(d.name))) {
                    nameByIndex.set(n, d);
                    indexByName.set(d, n++);
                  }
                });

                // Construct a square matrix counting package imports.
                imports.forEach(function(d) {
                  var source = indexByName.get(name(d.name)),
                    row = matrix[source];
                  if (!row) {
                    row = matrix[source] = [];
                    for (var i = -1; ++i < n;) row[i] = 0;
                  }
                  d.imports.forEach(function(d) {
                    row[indexByName.get(name(d))]++;
                  });
                });

                chord.matrix(matrix);

                var g = svg.selectAll(".group")
                  .data(chord.groups)
                  .enter().append("g")
                  .attr("class", "group");

                g.append("path")
                  .style("fill", function(d) {
                    return fill(d.index);
                  })
                  .style("stroke", function(d) {
                    return fill(d.index);
                  })
                  .attr("d", arc);

                g.append("text")
                  .each(function(d) {
                    d.angle = (d.startAngle + d.endAngle) / 2;
                  })
                  .attr("dy", ".35em")
                  .attr("transform", function(d) {
                    return "rotate(" + (d.angle  180 / Math.PI - 90) + ")" +
                      "translate(" + (innerRadius + 26) + ")" +
                      (d.angle > Math.PI ? "rotate(180)" : "");
                  })
                  .style("text-anchor", function(d) {
                    return d.angle > Math.PI ? "end" : null;
                  })
                  .text(function(d) {
                    return nameByIndex.get(d.index);
                  });

                svg.selectAll(".chord")
                  .data(chord.chords)
                  .enter().append("path")
                  .attr("class", "chord")
                  .style("stroke", function(d) {
                    return d3.rgb(fill(d.source.index)).darker();
                  })
                  .style("fill", function(d) {
                    return fill(d.source.index);
                  })
                  .attr("d", d3.svg.chord().radius(innerRadius));

                // Emitting CAPTURE_EXIT event after d3 chart render complete
                FusionExport.emit('CAPTURE_EXIT');

              });

            d3.select(self.frameElement).style("height", outerRadius  2 + "px");
          </script>
        </body>
    </html>
Pay special attention to FusionExport.emit('CAPTURE_EXIT'). You need to emit the CAPTURE_EXIT event when the render is complete.
The fusioncharts_config.json looks like as follows:


    {
      "template": "path/to/d3_exp/template.html",
      "output-file": "./",
      "type": "pdf",
      "async-capture": true
    }

Once done, run the following command:

    $ fe -e fusioncharts_config.json

    // D3 export
    const path = require('path');

    // Require FusionExport
    const {
        ExportManager,
        ExportConfig
    } = require('../');

    // Instantiate ExportManager
    const exportManager = new ExportManager();

    // Instantiate ExportConfig and add the required configurations
    const exportConfig = new ExportConfig();

    exportConfig.set('templateFilePath', path.join(dirname, 'resources', 'template_d3.html'));
    exportConfig.set('type', 'jpg');
    exportConfig.set('asyncCapture', true);

    // provide the export config
    exportManager.export(exportConfig);

    // Called when export is done
    exportManager.on('exportDone', (outputFileBag) => {
        outputFileBag.forEach((op) => {
            console.log(DONE: ${op.realName});
        });

        ExportManager.saveExportedFiles(outputFileBag);
    });

    // Called on each export state change
    exportManager.on('exportStateChange', (state) => {
        console.log([${state.reporter}] ${state.customMsg});
    });

    // Called on erroe
    exportManager.on('error', (err) => {
        console.error(err);
    });

    import com.fusioncharts.fusionexport.client.*;

    public class d3_exp {
        public static void main(String[] args) throws Exception {

            String rootPath = System.getProperty("user.dir") + java.io.File.separator;
            String templateRelativePath = "src\test\resources\static2\resources\template_d3.html".replace("\", java.io.File.separator);
            String templateAbsolutePath = rootPath + templateRelativePath;
            ExportConfig config = new ExportConfig();

            config.set("templateFilePath", templateAbsolutePath);
            config.set("type", "pdf");
            config.set("asyncCapture", true);

            ExportManager manager = new ExportManager(config);
            manager.export(new ExportDoneListener() {
                    @Override
                    public void exportDone(ExportDoneData result, ExportException error) {
                        if (error != null) {
                            System.out.println(error.getMessage());
                        } else {
                            ExportManager.saveExportedFiles(rootPath + "bin" + java.io.File.separator + "static2" + java.io.File.separator + "resources", result);
                        }
                    }
                },
                new ExportStateChangedListener() {
                    @Override
                    public void exportStateChanged(ExportState state) {
                        System.out.println("STATE: " + state.customMsg);
                    }
                });

        }
    }

    using System;
    using System.IO;
    using System.Linq;
    using FusionCharts.FusionExport.Client; // Import sdk

    namespace FusionExportTest {
        public static class D3_Exp {
            public static void Run(string host = Constants.DEFAULT_HOST, int port = Constants.DEFAULT_PORT) {
                // Instantiate the ExportConfig class and add the required configurations
                ExportConfig exportConfig = new ExportConfig();
                exportConfig.Set("templateFilePath", "./resources/template_d3.html");
                exportConfig.Set("type", "jpg");
                exportConfig.Set("asyncCapture", true);
                // Instantiate the ExportManager class
                ExportManager em = new ExportManager(host: host, port: port);
                // Call the Export() method with the export config and the respective callbacks
                em.Export(exportConfig, OnExportDone, OnExportStateChanged);
                Console.Read();
            }
            // Called when export is done
            static void OnExportDone(ExportEvent ev, ExportException error) {
                if (error != null) {
                    Console.WriteLine("Error: " + error);
                } else {
                    var fileNames = ExportManager.GetExportedFileNames(ev.exportedFiles);
                    Console.WriteLine("Done: " + String.Join(", ", fileNames)); // export result
                }
            }

            // Called on each export state change
            static void OnExportStateChanged(ExportEvent ev) {
                Console.WriteLine("State: " + ev.state.customMsg);
            }
        }
    }

    <?php
    // D3 export
    require DIR__ . '/../vendor/autoload.php';
    // Use the sdk
    use FusionExport\ExportManager;
    use FusionExport\ExportConfig;
    // Instantiate the ExportConfig class and add the required configurations
    $exportConfig = new ExportConfig();
    $exportConfig->set('templateFilePath', realpath('resources/template_d3.html'));
    $exportConfig->set('type', 'jpg');
    $exportConfig->set('asyncCapture', 'true');
    // Called on each export state change
    $onStateChange = function ($event) {
        $state = $event->state;
        echo('STATE: [' . $state->reporter . '] ' . $state->customMsg . "\n");
    };
    // Called when export is done
    $onDone = function ($event, $e) {
        $export = $event->export;
        if ($e) {
            echo('ERROR: ' . $e->getMessage());
        } else {
            foreach ($export as $file) {
                echo('DONE: ' . $file->realName. "\n");
            }
            ExportManager::saveExportedFiles($export);
        }
    };
    // Instantiate the ExportManager class
    $exportManager = new ExportManager();
    // Call the export() method with the export config and the respective callbacks
    $exportManager->export($exportConfig, $onDone, $onStateChange);

    #!/usr/bin/env python

    from fusionexport import ExportManager, ExportConfig  # Import sdk

    def read_file(file_path):
        try:
            with open(file_path, "r") as f:
                return f.read()
        except Exception as e:
            print(e)


    # Called when export is done
    def on_export_done(event, error):
        if error:
            print(error)
        else:
            ExportManager.save_exported_files("exported_images", event["result"])


    # Called on each export state change
    def on_export_state_changed(event):
        print(event["state"])


    # Instantiate the ExportConfig class and add the required configurations
    export_config = ExportConfig()
    export_config["templateFilePath"] = "template_d3.html"
    export_config["type"] = "pdf"
    export_config["asyncCapture"] = "true"

    # Provide port and host of FusionExport Service
    export_server_host = "127.0.0.1"
    export_server_port = 1337

    # Instantiate the ExportManager class
    em = ExportManager(export_server_host, export_server_port)
    # Call the export() method with the export config and the respective callbacks
    em.export(export_config, on_export_done, on_export_state_changed)

    // D3 export

    package main

    import (
        "fmt"

        "github.com/fusioncharts/fusionexport-go-client"
    )

    // Called when export is done
    func onDone(outFileBag []FusionExport.OutFileBag, err error) {
        check(err)
        FusionExport.SaveExportedFiles(outFileBag)
    }

    // Called on each export state change
    func onStateChange(event FusionExport.ExportEvent) {
        fmt.Println("[" + event.Reporter + "] " + event.CustomMsg)
    }

    func main() {
        // Instantiate ExportConfig and add the required configurations
        exportConfig := FusionExport.NewExportConfig()

        exportConfig.Set("templateFilePath", "example/resources/template_d3.html")
        exportConfig.Set("type", "pdf")
        exportConfig.Set("asyncCapture", true)

        // Instantiate ExportManager
        exportManager := FusionExport.NewExportManager()
        // Call the Export() method with the export config and the respective callbacks
        exportManager.Export(exportConfig, onDone, onStateChange)
    }

    func check(e error) {
        if e != nil {
            panic(e)
        }
    }
Was this article helpful to you ?