diff --git a/config.default.yml b/config.default.yml index 56ef07c..ea8ef46 100644 --- a/config.default.yml +++ b/config.default.yml @@ -28,6 +28,9 @@ frontend: # Image download format, can be "png", "jpeg" (or "webp" -> only working on chrome) -- string imageDownloadFormat: "png" + # draw the background grid to images on download ? (If True, even PNGs are also not transparent anymore) -- boolean + drawBackgroundGrid: false + # Frontend performance tweaks performance: # Refresh frequency of the debug / info div (in Hz i.e. /s) -- number diff --git a/scripts/config/config-schema.json b/scripts/config/config-schema.json index 2f33968..e42fca3 100644 --- a/scripts/config/config-schema.json +++ b/scripts/config/config-schema.json @@ -51,6 +51,9 @@ "imageDownloadFormat": { "type": "string" }, + "drawBackgroundGrid": { + "type": "boolean" + }, "performance": { "type": "object", "additionalProperties": false, diff --git a/src/js/main.js b/src/js/main.js index ee49860..f8c280f 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -285,21 +285,27 @@ function initWhiteboard() { // save image as imgae $("#saveAsImageBtn").click(function () { - whiteboard.getImageDataBase64(ConfigService.imageDownloadFormat, function (imgData) { - var w = window.open("about:blank"); //Firefox will not allow downloads without extra window - setTimeout(function () { - //FireFox seems to require a setTimeout for this to work. - var a = document.createElement("a"); - a.href = imgData; - a.download = "whiteboard." + ConfigService.imageDownloadFormat; - w.document.body.appendChild(a); - a.click(); - w.document.body.removeChild(a); + whiteboard.getImageDataBase64( + { + imageFormat: ConfigService.imageDownloadFormat, + drawBackgroundGrid: ConfigService.drawBackgroundGrid, + }, + function (imgData) { + var w = window.open("about:blank"); //Firefox will not allow downloads without extra window setTimeout(function () { - w.close(); - }, 100); - }, 0); - }); + //FireFox seems to require a setTimeout for this to work. + var a = document.createElement("a"); + a.href = imgData; + a.download = "whiteboard." + ConfigService.imageDownloadFormat; + w.document.body.appendChild(a); + a.click(); + w.document.body.removeChild(a); + setTimeout(function () { + w.close(); + }, 100); + }, 0); + } + ); }); // save image to json containing steps @@ -380,26 +386,30 @@ function initWhiteboard() { localStorage.setItem("webdavusername", webdavusername); var webdavpassword = webDavHtml.find(".webdavpassword").val(); localStorage.setItem("webdavpassword", webdavpassword); - whiteboard.getImageDataBase64(ConfigService.imageDownloadFormat, function ( - base64data - ) { - var webdavaccess = { - webdavserver: webdavserver, - webdavpath: webdavpath, - webdavusername: webdavusername, - webdavpassword: webdavpassword, - }; - webDavHtml.find(".loadingWebdavText").show(); - webDavHtml.find(".webdavUploadBtn").hide(); - saveWhiteboardToWebdav(base64data, webdavaccess, function (err) { - if (err) { - webDavHtml.find(".loadingWebdavText").hide(); - webDavHtml.find(".webdavUploadBtn").show(); - } else { - webDavHtml.parents(".basicalert").remove(); - } - }); - }); + whiteboard.getImageDataBase64( + { + imageFormat: ConfigService.imageDownloadFormat, + drawBackgroundGrid: ConfigService.drawBackgroundGrid, + }, + function (base64data) { + var webdavaccess = { + webdavserver: webdavserver, + webdavpath: webdavpath, + webdavusername: webdavusername, + webdavpassword: webdavpassword, + }; + webDavHtml.find(".loadingWebdavText").show(); + webDavHtml.find(".webdavUploadBtn").hide(); + saveWhiteboardToWebdav(base64data, webdavaccess, function (err) { + if (err) { + webDavHtml.find(".loadingWebdavText").hide(); + webDavHtml.find(".webdavUploadBtn").show(); + } else { + webDavHtml.parents(".basicalert").remove(); + } + }); + } + ); }); showBasicAlert(webDavHtml, { header: "Save to Webdav", diff --git a/src/js/services/ConfigService.js b/src/js/services/ConfigService.js index 40ccea4..cc34026 100644 --- a/src/js/services/ConfigService.js +++ b/src/js/services/ConfigService.js @@ -40,6 +40,14 @@ class ConfigService { return this.#imageDownloadFormat; } + /** + * @type {boolean} + */ + #drawBackgroundGrid = false; + get drawBackgroundGrid() { + return this.#drawBackgroundGrid; + } + /** * @type {{minDistDelta: number, minTimeDelta: number}} */ @@ -69,12 +77,14 @@ class ConfigService { onWhiteboardLoad, showSmallestScreenIndicator, imageDownloadFormat, + drawBackgroundGrid, performance, } = common; this.#onWhiteboardLoad = onWhiteboardLoad; this.#showSmallestScreenIndicator = showSmallestScreenIndicator; this.#imageDownloadFormat = imageDownloadFormat; + this.#drawBackgroundGrid = drawBackgroundGrid; this.#refreshInfoInterval = 1000 / performance.refreshInfoFreq; console.log("Whiteboard config from server:", configFromServer, "parsed:", this); diff --git a/src/js/whiteboard.js b/src/js/whiteboard.js index 512700f..e990726 100644 --- a/src/js/whiteboard.js +++ b/src/js/whiteboard.js @@ -1173,62 +1173,78 @@ const whiteboard = { refreshUserBadges() { this.cursorContainer.find(".userbadge").remove(); }, - getImageDataBase64(format, callback) { + getImageDataBase64(options, callback) { var _this = this; var width = this.mouseOverlay.width(); var height = this.mouseOverlay.height(); var copyCanvas = document.createElement("canvas"); copyCanvas.width = width; copyCanvas.height = height; - var ctx = copyCanvas.getContext("2d"); + var imageFormat = options.imageFormat || "png"; + var drawBackgroundGrid = options.drawBackgroundGrid || false; - $.each(_this.imgContainer.find("img"), function () { - //Draw Backgroundimages to the export canvas - var width = $(this).width(); - var height = $(this).height(); - var p = $(this).position(); - var left = Math.round(p.left * 100) / 100; - var top = Math.round(p.top * 100) / 100; - ctx.drawImage(this, left, top, width, height); - }); + var brackGroundImg = new Image(); + brackGroundImg.src = _this.settings.backgroundGridUrl; - var destCtx = copyCanvas.getContext("2d"); //Draw the maincanvas to the exportcanvas - if (format === "jpeg") { - //Set white background for jpeg images - destCtx.fillStyle = "#FFFFFF"; - destCtx.fillRect(0, 0, width, height); - } - destCtx.drawImage(this.canvas, 0, 0); + brackGroundImg.onload = function () { + var destCtx = copyCanvas.getContext("2d"); //Draw the maincanvas to the exportcanvas - var textBoxCnt = 0; - $.each($(".textBox"), function () { - //Draw the text on top - textBoxCnt++; + if (imageFormat === "jpeg") { + //Set white background for jpeg images + destCtx.fillStyle = "#FFFFFF"; + destCtx.fillRect(0, 0, width, height); + } - var textContainer = $(this); - var p = textContainer.position(); + if (drawBackgroundGrid) { + var ptrn = destCtx.createPattern(brackGroundImg, "repeat"); // Create a pattern with this image, and set it to "repeat". + destCtx.fillStyle = ptrn; + destCtx.fillRect(0, 0, copyCanvas.width, copyCanvas.height); // context.fillRect(x, y, width, height); + } - var left = Math.round(p.left * 100) / 100; - var top = Math.round(p.top * 100) / 100; + $.each(_this.imgContainer.find("img"), function () { + //Draw Backgroundimages to the export canvas + var width = $(this).width(); + var height = $(this).height(); + var p = $(this).position(); + var left = Math.round(p.left * 100) / 100; + var top = Math.round(p.top * 100) / 100; + destCtx.drawImage(this, left, top, width, height); + }); - html2canvas(this, { backgroundColor: "rgba(0, 0, 0, 0)", removeContainer: true }).then( - function (canvas) { + //Copy drawings + destCtx.drawImage(_this.canvas, 0, 0); + + var textBoxCnt = 0; + $.each($(".textBox"), function () { + //Draw the text on top + textBoxCnt++; + + var textContainer = $(this); + var p = textContainer.position(); + + var left = Math.round(p.left * 100) / 100; + var top = Math.round(p.top * 100) / 100; + + html2canvas(this, { + backgroundColor: "rgba(0, 0, 0, 0)", + removeContainer: true, + }).then(function (canvas) { console.log("canvas", canvas); destCtx.drawImage(canvas, left, top); textBoxCnt--; checkForReturn(); - } - ); - }); + }); + }); - function checkForReturn() { - if (textBoxCnt == 0) { - var url = copyCanvas.toDataURL("image/" + format); - callback(url); + function checkForReturn() { + if (textBoxCnt == 0) { + var url = copyCanvas.toDataURL("image/" + imageFormat); + callback(url); + } } - } - checkForReturn(); + checkForReturn(); + }; }, getImageDataJson() { var sendObj = [];