From b64c3693fe932cab4cd0d6e3a6054483a98512ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arno=C5=A1t=20Pleskot?= Date: Wed, 2 Aug 2023 00:54:44 +0200 Subject: [PATCH] feat: render backgrounds with rounded corners --- src/appState.ts | 2 +- src/renderer/renderScene.ts | 89 +++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/appState.ts b/src/appState.ts index b297b35c5..c835f7a5b 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -208,7 +208,7 @@ const APP_STATE_STORAGE_CONF = (< pendingImageElementId: { browser: false, export: false, server: false }, showHyperlinkPopup: { browser: false, export: false, server: false }, selectedLinearElement: { browser: true, export: false, server: false }, - exportBackgroundImage: { browser: true, export: false, server: false }, + exportBackgroundImage: { browser: false, export: false, server: false }, }); const _clearAppStateForStorage = < diff --git a/src/renderer/renderScene.ts b/src/renderer/renderScene.ts index 2ec7d8e08..58f45f7b1 100644 --- a/src/renderer/renderScene.ts +++ b/src/renderer/renderScene.ts @@ -392,6 +392,9 @@ const addExportBackground = ( svgUrl: string, rectangleColor: string, ): void => { + const MARGIN = 24; + const BORDER_RADIUS = 12; + const ctx = canvas.getContext("2d") as CanvasRenderingContext2D; // Create a new image object @@ -399,8 +402,37 @@ const addExportBackground = ( // When the image has loaded img.onload = (): void => { - // Draw the image onto the canvas - ctx.drawImage(img, 0, 0, normalizedCanvasWidth, canvas.height); + // Scale image to fill canvas and draw it onto the canvas + ctx.save(); + ctx.beginPath(); + if (ctx.roundRect) { + ctx.roundRect( + 0, + 0, + normalizedCanvasWidth, + normalizedCanvasHeight, + BORDER_RADIUS, + ); + } else { + roundRect( + ctx, + 0, + 0, + normalizedCanvasWidth, + normalizedCanvasHeight, + BORDER_RADIUS, + ); + } + const scale = Math.max( + normalizedCanvasWidth / img.width, + normalizedCanvasHeight / img.height, + ); + const x = (normalizedCanvasWidth - img.width * scale) / 2; + const y = (normalizedCanvasHeight - img.height * scale) / 2; + ctx.clip(); + ctx.drawImage(img, x, y, img.width * scale, img.height * scale); + ctx.closePath(); + ctx.restore(); // Create shadow similar to the CSS box-shadow const shadows = [ @@ -426,46 +458,38 @@ const addExportBackground = ( ]; shadows.forEach((shadow, index): void => { - const MARGIN = 24; - const BORDER_RADIUS = 12; - + ctx.save(); + ctx.beginPath(); ctx.shadowColor = `rgba(0, 0, 0, ${shadow.alpha})`; ctx.shadowBlur = shadow.blur; ctx.shadowOffsetX = shadow.offsetX; ctx.shadowOffsetY = shadow.offsetY; - // Define path for rectangle - ctx.beginPath(); - ctx.moveTo(MARGIN, MARGIN); - ctx.lineTo(normalizedCanvasWidth - MARGIN, MARGIN); - ctx.quadraticCurveTo( - normalizedCanvasWidth, - MARGIN, - normalizedCanvasWidth, - MARGIN + BORDER_RADIUS, - ); - ctx.lineTo(normalizedCanvasWidth, normalizedCanvasHeight - MARGIN); - ctx.quadraticCurveTo( - normalizedCanvasWidth, - normalizedCanvasHeight, - normalizedCanvasWidth - MARGIN, - normalizedCanvasHeight, - ); - ctx.lineTo(MARGIN, normalizedCanvasHeight); - ctx.quadraticCurveTo( - 0, - normalizedCanvasHeight, - 0, - normalizedCanvasHeight - MARGIN, - ); - ctx.lineTo(0, MARGIN + BORDER_RADIUS); - ctx.quadraticCurveTo(0, MARGIN, MARGIN, MARGIN); - ctx.closePath(); + if (ctx.roundRect) { + ctx.roundRect( + MARGIN, + MARGIN, + normalizedCanvasWidth - MARGIN * 2, + normalizedCanvasHeight - MARGIN * 2, + BORDER_RADIUS, + ); + } else { + roundRect( + ctx, + MARGIN, + MARGIN, + normalizedCanvasWidth - MARGIN * 2, + normalizedCanvasHeight - MARGIN * 2, + BORDER_RADIUS, + ); + } if (index === shadows.length - 1) { ctx.fillStyle = rectangleColor; ctx.fill(); } + ctx.closePath(); + ctx.restore(); }); // Reset shadow properties for future drawings @@ -534,7 +558,6 @@ export const _renderScene = ({ } context.save(); if (isExporting && exportBackgroundImage) { - context.save(); addExportBackground( canvas, normalizedCanvasWidth,