Zip files using jszip

Scenario

We just finish exporting SVG, PNG, and PDF. How can we zip files in client’s browser when the files we export? I tried jszip and it is easy to use.

2016-06-04_181840

DEMO SOURCE

Export SVG as PDF using canvg.js, Canvas, and jspdf

Scenario

Why I have to export as PDF is that the laser printer is used by the factory doesn’t support PNG and SVG. For how, we just need to import  jspdf  after we’ve done exporting SVG as PNG.

2016-06-03_114927

DEMO SOURCE

Export SVG as PNG using canvg.js and Canvas

Scenario

Instead of the post which shows how it exports SVG using XMLSerializer, this time we are going to export Raster Graphics(PNG, JPEG, etc.) using canvg.js and also HTML5 Canvas.

2016-06-02_104328

DEMO SOURCE

Solution

That’s quite easy to do it. You can imagine that a painter paints a view. Canvas is the painter, the view is SVG, and the picture which is made by the painter is Raster Graphic.

pexels-photo-47482
Canvas paints SVG as a PNG.

The above photo was added three words by me. And the souce and license are as following links: SOURCE LICENSE.

Preparation

At first, import libraries and dependencies.

<html>
  <head>
    ...
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/rgbcolor.js"></script>
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/StackBlur.js"></script>
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/canvg.js"></script>
    ...
  </head>
  <body>
    ...
  </body>
</html>

The next step, add a download button and SVG in body.

<html>
  <head>
    ...
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/rgbcolor.js"></script>
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/StackBlur.js"></script>
    <script type="text/javascript" src="http://gabelerner.github.io/canvg/canvg.js"></script>
    ...
  </head>
  <body>
    <div>
      <input id='downloadBtn' type='button' value='Download'/>
    </div>
    <svg xmlns="http://www.w3.org/2000/svg" class="item" id="svg-01" width="600" height="250">
      <rect fill="none" stroke="#000" stroke-width="1" x="0" y="0" width="600" height="250" />
      <text class="item-title" style="font-family:monospace; font-size: 20px;" lengthAdjust="spacing" textLength="580" transform="translate(300,40)" text-anchor="middle">Export SVG as PNG using canvg.js and Canvas</text>
    </svg>
</body>
</html>

You will see like this:

2016-06-02_104328

Render SVG as PNG

We create a function named SVG2PNG with 2 parameters: svg and callback. callback means callback function and it will be executed at last of SVG2PNG; however, you must understand what callback function is.

function SVG2PNG(svg, callback) {
  var canvas = document.createElement('canvas'); // Create a Canvas element.
  var ctx = canvas.getContext('2d'); // For Canvas returns 2D graphic.
  var data = svg.outerHTML; // Get SVG element as HTML code.
  canvg(canvas, data); // Render SVG on Canvas.
  callback(canvas); // Execute callback function.
}

Link Generator

We use a element for downloading.

function generateLink(fileName, data) {
  var link = document.createElement('a');
  link.download = fileName;
  link.href = data;
  return link;
}

Bind Click Event & Download

document.getElementById('downloadBtn').onclick = function() { // Bind click event on download button.
  var element = document.getElementById('svg-01'); // Get SVG element.
  SVG2PNG(element, function(canvas) { // Arguments: SVG element, callback function.
    var base64 = canvas.toDataURL("image/png"); // toDataURL return DataURI as Base64 format.
    generateLink('SVG2PNG-01.png', base64).click(); // Trigger the Link is made by Link Generator and download.
  });
}

Export SVG file using XMLSerializer

Scenario

I was considering how I can export SVG as a file using client JavaScript. The way I found on the Internet uses XMLSerializer and create a element for download. Let’s see how it goes.

2016-06-01_104845

DEMO SOURCE

Solution

About

We are going to use native JavaScript only; hence, you don’t need any library but the browser compatibility of XMLSerializer must be confirmed.

2016-06-01_095625

It seems work on most modern browsers. :p

Create SVG Sample Element

  <svg xmlns="http://www.w3.org/2000/svg" id="svg-01" width="600" height="250">
    <rect fill="none" stroke="#000" stroke-width="1" x="0" y="0" width="600" height="250" />
    <text class="item-title" style="font-size: 30px; font-weight: 900;" lengthAdjust="spacing" textLength="480" x="60" y="40">Export SVG using XMLSerializer</text>
  </svg>

Download Function

We are going to create a element for download method. The element within attributes:

  • download: This is the name of download file.
  • href: This is the content of download file.
    function generateLink(fileName, data) {
      var link = document.createElement('a'); // Create a element.
      link.download = fileName; // Set value as the file name of download file.
      link.href = data; // Set value as the file content of download file.
      return link;
    }

Begin To Export!

New a XMLSerializer object and serial our SVG element to a string. Then, we have to prepend ‘data:image/svg+xml;utf8,’ for Data URIs. .click() will fire as user click.

    function exportSVG(element, fileName) {
      var svg = element;
      var svgString;
      if (window.ActiveXObject) {
        svgString = svg.xml;
      } else {
        var oSerializer = new XMLSerializer();
        svgString = oSerializer.serializeToString(svg);
      }
      generateLink(fileName + '.svg', 'data:image/svg+xml;utf8,' + svgString).click();
    }

Click & Download

.onclick binds the function on the element.

    document.getElementById('downloadBtn').onclick = function() {
      var element = document.getElementById('svg-01');
      exportSVG(element, 'SVG-01');
    }

Quality Map using D3.js

Scenario

Draw a heat-map-like graphic using D3.js and bind click-event on radios using jQuery. This followings are the features.

  • A dropdown list to switch in several years (2014, 2015, 2016).
  • Each year will be a single layer and the layers will be switched by the dropdown list.
  • Each square of each layer will display a color in several RGBs.
  • Each square size is 5 x 5 pixels.
  • Around 100 x 100 squares.
  • A series of radios to display/hide min, max, average, etc..

2016-05-31_164017

DEMO SOURCE

Solution

Before We Begin

We have to import the libraries: D3.js & jQuery. And create a script block for our own program.

<!DOCTYPE>
<html>
  <head>
    <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
    <script type="text/javascript">
      // Our own program.
    </script>
    ...
  </head>
  <body>
    ...
  </body>
</html>

New Config Object

This Config includes some properties as below:

  • width[Number]: width of SVG
  • height[Number]: height of SVG
  • grid[Object]: Each grid(square) size: width and height.
  • diff[Number]: The gap of the sequence(array) of the data
  • colors[Array]: It arrayed from deep to light and uses HEX colors.

    var config = {
      width: 500, // SVG width.
      height: 500, // SVG height.
      grid: {
        width: 50, // Can divide SVG width,
        height: 50 // Can divide SVG height
      },
      diff: 200, // The difference(gap) between each color.
      // It arrayed from deep to light and uses HEX colors.
      colors: ['#993404', '#d95f0e', '#fe9929', '#fed98e', '#ffffd4']
    };

Create Functions

We need a function to get a position(x-axis, y-axis) from the index of data array.

    function getPosition(dataIndex) { // index is from 0.
      if(!dataIndex) return {x: 0, y: 0};

      var nthColumn = dataIndex % (config.height / config.grid.height), // x-axis: 0 - 99
          nthRow = Math.floor(dataIndex / (config.width / config.grid.width)); // y-axis: 0 - 99

      var columnWidth = config.grid.width,
          rowHeight = config.grid.height;
      return {
        x: columnWidth * nthColumn, // Translate columnWidth pixel nthColumn times
horizontally.
        y: rowHeight * nthRow // Translate rowHeight pixel nthRow times vertically.
      };
    }

And we have to create a function to get the grid background by the data value and config.diff.

    function getColor(dataValue) {
      return config.colors[Math.floor(dataValue / config.diff)];
    }

Let’s Draw!

First of all, color your border on SVG using CSS. Append the style to head tag.

<!DOCTYPE>
<html>
  <head>
    ...
<style>
      svg {
        border: 3px solid;
      }
    </style>

  </head>
  <body>
    ...
  </body>
</html>

And then, create SVG element as following:

    function renderSVG(data) {
      var svg = d3.select('body')
                  .append('svg')
                  .attr({
                    width: config.width,
                    height: config.height
                  });
    }

Now, append the grids to the SVG:

    function renderSVG(data) {
      var svg = d3.select('body')
                  .append('svg')
                  .attr({
                    width: config.width,
                    height: config.height
                  });
      svg.selectAll('rect') // Create virtual rect elements.
         .data(data).enter() // Deal with on each data, or put data in to the rect elemetns.
         .append('rect').attr({ // Assign every attribute we need.
           width: config.grid.width, // The width of each rect element.
           height: config.grid.height, // The height of each rect element.
           x: function(d, i) { return getPosition(i).x; }, // Assign the x-axis position to x attribute.
           y: function(d, i) { return getPosition(i).y; }, // Assign the y-axis position to y attribute.
           'fill': function(d) { return getColor(d); } // Set the fill value as the return value of getColor(d).
         }
      );
    }

As you can see, function(d) { return something; } returns corresponding value of data list. For example, ‘fill’: function(d) { return getColor(d); } will assign getColor(d) to ‘fill’ property.

Make Transition

It’s quite easy to make transition on your SVG. Follow as below and you’ll get the result you want.

    function renderSVG(data) {
      var svg = d3.select('body')
                  .append('svg')
                  .attr({
                    width: config.width,
                    height: config.height
                  });
      svg.selectAll('rect')
         .data(data).enter()elemetns.
         .append('rect').attr({
           width: config.grid.width,
           height: config.grid.height,
           x: function(d, i) { return getPosition(i).x; },
           y: function(d, i) { return getPosition(i).y; },
           'fill': '#fff' // The initial background.
      }).transition().duration(1500).attr({ // The 1500 within duration() means millisecond.
        'fill': function(d) { return getColor(d); } // The color when transition has been finished.
      });

The transition will bring the color from #fff to getColor(d).
Let’s generate random data and render it!.

    // Just a template.
    var qualityData = {
      2014: {
        min: [],
        max: [],
        avg: []
      },
      2015: {
        min: [],
        max: [],
        avg: []
      },
      2016: {
        min: [],
        max: [],
        avg: []
      }
    };

    // This function is for DEMO.
    function dataRandom(dataLen, maxValue) {
      for(var i = 0; i < dataLen; dataLen; i++) {
        qualityData[2014].min.push(Math.floor(Math.random() * maxValue));
        qualityData[2014].max.push(Math.floor(Math.random() * maxValue));
        qualityData[2014].avg.push(Math.floor(Math.random() * maxValue));
        qualityData[2015].min.push(Math.floor(Math.random() * maxValue));
        qualityData[2015].max.push(Math.floor(Math.random() * maxValue));
        qualityData[2015].avg.push(Math.floor(Math.random() * maxValue));
        qualityData[2016].min.push(Math.floor(Math.random() * maxValue));
        qualityData[2016].max.push(Math.floor(Math.random() * maxValue));
        qualityData[2016].avg.push(Math.floor(Math.random() * maxValue));
      }
    }

    // Execute function with parameters.
    dataRandom(100, 1000);
    renderSVG(qualityData[2014][min]);

Bind Events

Create dorpdown list and radios.

  ...
  <body>
    <div style="margin-bottom: 10px">
      <select id="yearSelectorquot;>
        <option value=quot;2014quot;>2014</option><!--This will be the selected one.-->
        <option value=quot;2015quot;>2015</option>
        <option value=quot;2016quot;>2016</option>
      </select>
      <input type=quot;radioquot; name=quot;valueSelectorquot; value=quot;minquot; checked>Min. <!--This will be the selected one.-->
      <input type=quot;radioquot; name=quot;valueSelectorquot; value=quot;maxquot;>Max.
      <input type=quot;radioquot; name=quot;valueSelectorquot; value=quot;avgquot;>Avg.</div>
      ...
  </body>

Bind event using jQuery.

  renderSVG(qualityData[$('#yearSelector').val()][$('[name=valueSelector]:checked').val()]); // Initial, the first fire.

  $('#yearSelector, [name=valueSelector]').change(function() { // Actual binding.
      renderSVG(qualityData[$('#yearSelector').val()] [$('[name=valueSelector]:checked').val()]);
    });

Reference

SVG Text Horizontal Align- Centering

Scenario

You want to center horizontally without CSS.

2016-06-02_100303

DEMO SOURCE

Solution

Center Text element of SVG using transform and text-anchor attributes.

At first, add attribute transform with value ‘translate(half-svg-width, y-position)‘; for example, set value ‘translate(90, y-position)‘ if SVG width is ‘180‘.

Then, set attribute text-anchor with value ‘middle’.

<svg width="180" height="200"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

    <rect x="0" y=0 height=200 width=180
          style="stroke:#000; fill: #0086B2;"
          fill-opacity=0.2 stroke-opacity=0.2>
    </rect>

    <text transform="translate(90,30)" text-anchor="middle">A</text>

</svg>