Overview
The JavaScript Scheduler supports export of complex event/task objects to image (PNG, JPEG, SVG) using active areas:
Use active areas to insert rectangle objects at a specified position (pixel position or date/time position)
Active areas can display images supported by the browser (PNG, JPEG, SVG format)
The Scheduler can display and export font icons (e.g Font Awesome)
Active areas support vertical and horizontal text alignment, custom background color and font color
Export the Scheduler view to PNG, JPEG or SVG using exportAs() method
Includes a trial version of DayPilot Pro for JavaScript (see also License below)
License
Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.
Live Demo
Scheduler Image Export
The JavaScript/HTML5 Scheduler component includes built-in support for client-side image export. It exports the Scheduler view to common formats:
JPEG - bitmap format with lossy compression (can be used for PDF export)
PNG - bitmap format with lossless compression
SVG - vector format (ideal for printing)
However, the export feature does't simply copy the screen - each element has to be rendered individually using basic elements like lines, rectangles, and text strings. That means the image export has limited support for HTML and CSS:
The Scheduler tries to read the styles of individual elements (e.g. event background) and use them for export.
The inner HTML is interpreted as text. The <br> elements are converted to line breaks.
The CSS detection works on element level and it doesn't read styles that you use inside the element.
To overcome these limitations the Scheduler offers two tools:
onBeforeEventExport event handler lets you provide plain text instead of custom HTML and override the detected styles (similar event handlers are also available for other Scheduler elements, like grid cells and row headers)
event active areas let you insert custom objects at specified positions inside an event
This tutorial shows how to use the active areas to build the event content and make it exportable.
Rich Content with Active Areas
The active areas can be used to create complex event layouts. If you specify the active area content and appearance using the built-in properties it will be automatically used during export.
SVG Image
dp.events.list = [
{
"id": 1,
"text": "SVG Image",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barColor": "#f1c232",
"areas": [
{
"right": 3,
"top": 8,
"width": 26,
"height": 26,
"image": "icon.svg"
}
]
}
];
PNG Image
dp.events.list = [
{
"id": 2,
"text": "PNG Image",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barColor": "#f1c232",
"areas": [
{
"right": 3,
"top": 8,
"width": 26,
"height": 26,
"image": "icon.png"
}
]
}
];
Font Icon
dp.events.list = [
{
"id": 3,
"text": "Font icon",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barColor": "#f1c232",
"areas": [
{
"right": 8,
"top": 8,
"width": 16,
"height": 14,
"icon": "icon-edit"
}
]
}
];
Centered Text
dp.events.list = [
{
"id": 21,
"text": "",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barHidden": true,
"areas": [
{
"right": 10,
"top": 5,
"left": 10,
"bottom": 5,
"text": "center/center",
"backColor": "#6aa84f",
"fontColor": "#ffffff",
"horizontalAlignment": "center",
"verticalAlignment": "center"
}
]
}
];
Left-Aligned Text
dp.events.list = [
{
"id": 22,
"text": "",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barHidden": true,
"areas": [
{
"right": 10,
"top": 5,
"left": 10,
"bottom": 5,
"text": "left/top",
"backColor": "#6aa84f",
"fontColor": "#ffffff",
"horizontalAlignment": "left",
"verticalAlignment": "top"
}
]
}
];
Right-Aligned Text
dp.events.list = [
{
"id": 23,
"text": "",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barHidden": true,
"areas": [
{
"right": 10,
"top": 5,
"left": 10,
"bottom": 5,
"text": "right/bottom",
"backColor": "#6aa84f",
"fontColor": "#ffffff",
"horizontalAlignment": "right",
"verticalAlignment": "bottom"
}
]
}
];
Text Padding
dp.events.list = [
{
"id": 24,
"text": "",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barHidden": true,
"areas": [
{
"right": 10,
"top": 5,
"left": 10,
"bottom": 5,
"text": "2px padding",
"backColor": "#6aa84f",
"fontColor": "#ffffff",
"horizontalAlignment": "left",
"verticalAlignment": "top",
"padding": 2
}
]
}
];
Background Color
dp.events.list = [
{
"id": 33,
"text": "",
"start": "2019-11-08T00:00:00",
"end": "2019-11-12T00:00:00",
"resource": "R2",
"barHidden": true,
"areas": [
{
"right": 10,
"top": 5,
"left": 10,
"bottom": 5,
"text": "#1155cc",
"backColor": "#1155cc",
"fontColor": "#ffffff",
"horizontalAlignment": "center",
"verticalAlignment": "center"
}
]
}
];
Exported Image
Scheduler with a sample event set:
Exported image:
Source Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>JavaScript Scheduler: How to Export HTML to Image</title>
<style type="text/css">
<!-- ... -->
</style>
<link rel="stylesheet" href="icons/style.css">
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/61152/javascript-scheduler-how-to-export-html-to-image'>JavaScript Scheduler: How to Export HTML to Image</a></h1>
<div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React/Vue</div>
</div>
<div class="main">
<div id="dp"></div>
<div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
<div class="space">
<button id="export">Export</button>
</div>
<div class="space">
<img id="target" >
</div>
</div>
<script>
var dp = new DayPilot.Scheduler("dp", {
timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
scale: "Day",
days: 30,
startDate: "2019-11-01",
timeRangeSelectedHandling: "Enabled",
onTimeRangeSelected: function (args) {
var dp = this;
DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function(modal) {
dp.clearSelection();
if (!modal.result) { return; }
dp.events.add(new DayPilot.Event({
start: args.start,
end: args.end,
id: DayPilot.guid(),
resource: args.resource,
text: modal.result
}));
});
},
treeEnabled: true,
});
dp.resources = [
{name: "Icons", id: "R1"},
{name: "Text", id: "R2"},
{name: "Background color", id: "R3"},
{name: "Resource 4", id: "R4"},
{name: "Resource 5", id: "R5"},
{name: "Resource 6", id: "R6"},
{name: "Resource 7", id: "R7"},
{name: "Resource 8", id: "R8"},
{name: "Resource 9", id: "R9"},
];
dp.onBeforeEventRender = function(args) {
/*args.data.areas = [
{
right: 3,
top: 5,
width: 26,
height: 26,
image: "diamond.svg"
},
];*/
};
dp.eventVersionsEnabled = true;
dp.events.list = [
{
id: 1,
text: "SVG Image",
start: "2019-11-02T00:00:00",
end: "2019-11-06T00:00:00",
resource: "R1",
barColor: "#f1c232",
areas: [
{
right: 3,
top: 8,
width: 26,
height: 26,
image: "icon.svg"
},
]
},
{
id: 2,
text: "PNG Image",
start: "2019-11-07T00:00:00",
end: "2019-11-11T00:00:00",
resource: "R1",
barColor: "#f1c232",
areas: [
{
right: 3,
top: 8,
width: 26,
height: 26,
image: "icon.png"
},
]
},
{
id: 3,
text: "Font icon",
start: "2019-11-12T00:00:00",
end: "2019-11-16T00:00:00",
resource: "R1",
barColor: "#f1c232",
areas: [
{
right: 8,
top: 8,
width: 16,
height: 14,
icon: "icon-edit"
},
]
},
{
id: 21,
text: "",
start: "2019-11-02T00:00:00",
end: "2019-11-06T00:00:00",
resource: "R2",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "center/center",
backColor: "#6aa84f",
fontColor: "#ffffff",
horizontalAlignment: "center",
verticalAlignment: "center"
},
]
},
{
id: 22,
text: "",
start: "2019-11-07T00:00:00",
end: "2019-11-11T00:00:00",
resource: "R2",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "left/top",
backColor: "#6aa84f",
fontColor: "#ffffff",
horizontalAlignment: "left",
verticalAlignment: "top"
},
]
},
{
id: 23,
text: "",
start: "2019-11-12T00:00:00",
end: "2019-11-16T00:00:00",
resource: "R2",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "right/bottom",
backColor: "#6aa84f",
fontColor: "#ffffff",
horizontalAlignment: "right",
verticalAlignment: "bottom"
},
]
},
{
id: 24,
text: "",
start: "2019-11-17T00:00:00",
end: "2019-11-21T00:00:00",
resource: "R2",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "2px padding",
backColor: "#6aa84f",
fontColor: "#ffffff",
horizontalAlignment: "left",
verticalAlignment: "top",
padding: 2
},
]
},
{
id: 31,
text: "",
start: "2019-11-02T00:00:00",
end: "2019-11-06T00:00:00",
resource: "R3",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "#6d9eeb",
backColor: "#6d9eeb",
fontColor: "#ffffff",
horizontalAlignment: "center",
verticalAlignment: "center"
},
]
},
{
id: 32,
text: "",
start: "2019-11-07T00:00:00",
end: "2019-11-11T00:00:00",
resource: "R3",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "#3c78d8",
backColor: "#3c78d8",
fontColor: "#ffffff",
horizontalAlignment: "center",
verticalAlignment: "center"
},
]
},
{
id: 33,
text: "",
start: "2019-11-12T00:00:00",
end: "2019-11-16T00:00:00",
resource: "R3",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "#1155cc",
backColor: "#1155cc",
fontColor: "#ffffff",
horizontalAlignment: "center",
verticalAlignment: "center"
},
]
},
{
id: 34,
text: "",
start: "2019-11-17T00:00:00",
end: "2019-11-21T00:00:00",
resource: "R3",
barHidden: true,
areas: [
{
right: 10,
top: 5,
left: 10,
bottom: 5,
text: "transparent",
backColor: "transparent",
horizontalAlignment: "center",
verticalAlignment: "center"
},
]
},
];
dp.init();
</script>
<script>
var elements = {
export: document.getElementById("export"),
target: document.getElementById("target")
};
elements.export.addEventListener("click", function(ev) {
elements.target.src = dp.exportAs("png").toDataUri();
});
</script>
</body>
</html>