0

I am trying to save a FLOT chart as an image. The chart is currently being displayed correctly in a div element as follows:

<div id="flotcontainer"></div>

The tool that I am using to save the image is canvas2image. This small library lets you easily save a HTML5 canvas element as an image file. This code is working on my page and I am able to annotate and then save the canvas element:

<canvas width="100" height="100" id="cvs"></canvas>

The problem that I am having is that the canvas2image code requires a canvas element, but my FLOT chart is displayed in a normal div element. What do I need to do to be able to pass the div containing my FLOT chart, instead of the canvas element to be saved? Thanks.

Here is the complete code that I am working on:

<style type="text/css">
#flotcontainer {
width: document.getElementById('flot_widget').offsetWidth;
height: 300px;
text-align: center;
margin: 0 auto;
}
canvas {
display: block;
border: 2px solid #888;
}
</style>

<div id="flotcontainer" style="display:none;" ></div>    

<div class="g12">
<canvas width="100" height="100" id="cvs"></canvas>

<div>
    <p>
        <button id="save">save</button> or <button id="convert">convert to</button> as: 
        <select id="sel">
            <option value="png">png</option>
            <option value="jpeg">jpeg</option>
            <option value="bmp">bmp</option>
        </select><br/>
        w : <input type="number" value="300" id="imgW" /> h : <input type="number" value="200" id="imgH" />
    </p>
</div>
<div id="imgs">        
</div>
</div>
<script>
var canvas, ctx, bMouseIsDown = false, iLastX, iLastY,
    $save, $imgs,
    $convert, $imgW, $imgH,
    $sel;
function init () {

    canvas = document.getElementById('cvs');
    ctx = canvas.getContext('2d');

    $save = document.getElementById('save');
    $convert = document.getElementById('convert');
    $sel = document.getElementById('sel');

    $imgs = document.getElementById('imgs');
    $imgW = document.getElementById('imgW');
    $imgH = document.getElementById('imgH');
    bind();
    draw();
}
function bind () {
    canvas.onmousedown = function(e) {
        bMouseIsDown = true;
        iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
        iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
    }
    canvas.onmouseup = function() {
        bMouseIsDown = false;
        iLastX = -1;
        iLastY = -1;
    }
    canvas.onmousemove = function(e) {
        if (bMouseIsDown) {
            var iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
            var iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
            ctx.moveTo(iLastX, iLastY);
            ctx.lineTo(iX, iY);
            ctx.stroke();
            iLastX = iX;
            iLastY = iY;
        }
    };      

    $save.onclick = function (e) {
        var type = $sel.value,
            w = $imgW.value,
            h = $imgH.value;
        Canvas2Image.saveAsImage(canvas, w, h, type);
    }

    $convert.onclick = function (e) {
        var type = $sel.value,
            w = $imgW.value,
            h = $imgH.value;
        $imgs.appendChild(Canvas2Image.convertToImage(canvas, w, h, type))
    }        
}

function draw () {
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, 600, 400);
    ctx.fillStyle = 'red';
    ctx.fillRect(10, 10, 50, 50);
}    

onload = init;
</script>
DanielAttard
  • 3,467
  • 9
  • 55
  • 104
  • Possible duplicate of [Save flot graph as image](http://stackoverflow.com/questions/15616925/save-flot-graph-as-image) – srussking Jun 09 '16 at 20:12

2 Answers2

1

To get the canvas of the Flot chart use

$canvas = $('#flotcontainer').find('canvas.base');

By the way:

  • You cannot use javascript inside your style element, you have to set the width by javascript after the page has loaded.
  • Why are you not using jQuery when you have to load it for the flot plugin?
    You could simplify $imgs = document.getElementById('imgs'); to $imgs = $('#imgs');.
    Additionally, beginning variable names with $ should be used for jQuery objects only to avoid confusion between jQuery objects and standard javascript / DOM objects.
Raidri
  • 17,258
  • 9
  • 62
  • 65
  • Thanks for the help @Raidra. You are correct that `$('#flotcontainer').find('canvas.base');` returns my FLOT chart, but I still don't know how to use that object, once I have retrieved it. When I try to assign it to the `canvas` variable, I get an error saying `Object [object Object] has no method 'getContext'`. I have implemented your other suggestions too, thanks. – DanielAttard Sep 30 '13 at 14:13
  • Use `canvas = $canvas.get(0)` to get the DOM object from the jQuery object and work from there. – Raidri Sep 30 '13 at 14:16
  • AWESOME! @Raidra - Your comments managed to get me on the right track. My problem was that I was trying to assign the canvas object before it was created. Once I moved the code from the init event to the AJAX event which created the chart, I was then able to assign the canvas to the variable (based on your advice), and now it is working fine. Now I can move on to the next issue, which is figuring out why I only have the chart overlay, and not the axis lines. – DanielAttard Sep 30 '13 at 14:48
  • There are multiple canvas element in a flot chart, use `$('#flotcontainer').find('canvas')` to get all of them and then look for what you need. – Raidri Sep 30 '13 at 15:47
1

You can also get the canvas from the flot plot object itself:

var somePlot = $.plot("#placeholder", [ [0,0],[10,10] ]);
somePlot.getCanvas()
Mark
  • 106,305
  • 20
  • 172
  • 230