Implementing PNG Export of Schedule in Open Event Webapp

Fortunately for us, we don’t have to implement it from scratch (which would have been extremely difficult and time-consuming). Enter html2canvas library. It renders an element onto the canvas after which we can convert it into an image. I will now explain how we implemented png export in the calendar mode. You can view the whole schedule template file here

Here is a screenshot of calendar or grid view of the schedule. Currently selected date is 18th Mar, Saturday. The PNG Export button is on the top-right corner beside the ‘Calendar View’ button.

32fa6d15-59da-4521-b348-6c01f6af7825.png

Here is a little excerpt of the basic structure of the calendar mode of the sessions. I have given an overview of it in the comments.

<div class="{{slug}} calendar">
 <!-- slug represents the currently selected date -->
 <!-- This div contains all the sessions scheduled on the selected date -->
 <div class="col-md-12 paddingzero">
   <!-- Contain content related to current date and time -->
 </div>
 <div class="calendar-content">
   <div class="times">
     <!-- This div contains the list of all the session times on the current day -->
     <!-- It is the left most column of the grid view which contains all the times →
     <div class="time">
       <!-- This div contains information about the particular time -->
     </div>
   </div>
   <div class="rooms">
     <!-- This div contains all the rooms of an event -->
     <!-- Each particular room has a set of sessions associated with it on that particular date -->
     <div class="room">
       <!-- This div contains the list of session happening in a particular room -->
       <!-- Session Details -->
     </div>
   </div>
 </div>
</div>

Now, let us see how we will actually capture an image of the HTML element shown above. Here is the code related to it:

$(".export-png").click(function() {
 if (isCalendarView === true) {

   $('.calendar').each(function() {
     if ($(this).attr('class').split(' ').indexOf('hide') <= 0) {

       $timeline = $(this);
       initialWidth = $timeline.width();
       numberOfChildElements = $timeline.find('.rooms')[0].childElementCount;
       numberOfChildElements = numberOfChildElements - 1;
       widthOfChild = $timeline.find('.room').width();
       canvasWidth = numberOfChildElements * widthOfChild + 50;
       $timeline.width(canvasWidth);
     }
   });
 }

 html2canvas($timeline, {
   onrendered: function(canvas) {
     canvas.id = "generated-canvas";
     canvas.toBlob(function(blob) {
       saveAs(blob, '' + $timeline.attr('class') + '.png');
     });
   },
 });
 $timeline.width(initialWidth);
});

Note that this initial width calculated is the width which is visible to us on the screen. In reality, the element might be scrollable and its actual width might be different. If we render the element using the initial width, we would not be able to see the full contents of that element. It will not show the whole view. Hence we need to calculate the actual width.Let us see what is going on in this code. When the user clicks on the export PNG button, we check whether we are in the calendar mode or not. If yes, then we proceed further. We then see which date is currently selected and accordingly select that div. After selecting it, we then get the initial width of that element.

So, we check all the child elements inside it, get their count and width and then calculate the actual width of the parent element based on it. Temporarily, we set this actual width as the width of the session element and pass it to the html2canvas function. That in turn, renders the whole element onto a canvas. After it has been successfully rendered onto the canvas, we save it to as an image and present a download box to the user for downloading that image.

Here is the download pop-up box

bfbd12c2-f6ed-4dae-8485-bfd1638faf74.png

And this is the downloaded PNG Image. Click on it for a higher resolution!

Screenshot from 2017-07-03 00-31-56.png

Resources