From 5323eac0c9ae58ce6fa0f77ad818c5a918f12f00 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Fri, 12 Jul 2024 22:52:36 +0200 Subject: [PATCH] [mirotalksfu] - add whiteboard gridLine --- app/src/Server.js | 2 +- package.json | 2 +- public/css/Room.css | 10 ++-- public/js/Room.js | 102 ++++++++++++++++++++++++++++++---------- public/js/RoomClient.js | 2 +- public/views/Room.html | 1 + 6 files changed, 89 insertions(+), 30 deletions(-) diff --git a/app/src/Server.js b/app/src/Server.js index 29f1233a..a02986a1 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -44,7 +44,7 @@ dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.4.94 + * @version 1.4.95 * */ diff --git a/package.json b/package.json index 2aef3982..a538e416 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.4.94", + "version": "1.4.95", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { diff --git a/public/css/Room.css b/public/css/Room.css index b18d0e76..dfa25322 100644 --- a/public/css/Room.css +++ b/public/css/Room.css @@ -1176,8 +1176,8 @@ progress { position: absolute; margin: auto; padding: 10px; - width: calc(var(--wb-width) * 1px); - height: calc(var(--wb-height) * 1px); + width: var(--wb-width); + height: var(--wb-height); background: var(--wb-bg); border: var(--border); box-shadow: var(--box-shadow); @@ -1185,6 +1185,10 @@ progress { /* overflow: hidden; */ } +/* #wbCanvas { + border: var(--border); +} */ + .whiteboard-header { display: flex; background: rgba(0, 0, 0, 0.2); @@ -1225,7 +1229,7 @@ progress { } .whiteboard-header-options .dropdown-menu { - max-height: calc(var(--wb-height) * 1px); + max-height: var(--wb-height); } .whiteboard-header-options .dropdown-menu button { diff --git a/public/js/Room.js b/public/js/Room.js index a708462c..f9e98ea2 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.4.94 + * @version 1.4.95 * */ @@ -67,10 +67,15 @@ const thisInfo = getInfo(); const Base64Prefix = 'data:application/pdf;base64,'; +// Whiteboard const wbImageInput = 'image/*'; const wbPdfInput = 'application/pdf'; -const wbWidth = 1280; +const wbWidth = 1366; const wbHeight = 768; +const wbGridSize = 20; +const wbStroke = '#cccccc63'; +let wbGridLines = []; +let wbGridVisible = false; const swalImageUrl = '../images/pricing-illustration.svg'; @@ -303,6 +308,7 @@ function initClient() { setTippy('refreshVideoFiles', 'Refresh', 'left'); setTippy('switchServerRecording', 'The recording will be stored on the server rather than locally', 'right'); setTippy('whiteboardGhostButton', 'Toggle transparent background', 'bottom'); + setTippy('whiteboardGridBtn', 'Toggle whiteboard grid', 'bottom'); setTippy('wbBackgroundColorEl', 'Background color', 'bottom'); setTippy('wbDrawingColorEl', 'Drawing color', 'bottom'); setTippy('whiteboardPencilBtn', 'Drawing mode', 'bottom'); @@ -1138,6 +1144,10 @@ async function shareRoom(useNavigator = false) { // ROOM UTILITY // #################################################### +function isDesktopDevice() { + return !DetectRTC.isMobileDevice && !isTabletDevice && !isIPadDevice; +} + function makeRoomQR() { let qr = new QRious({ element: document.getElementById('qrRoom'), @@ -1274,6 +1284,9 @@ function roomIsReady() { show(chatCleanTextButton); show(chatPasteButton); show(chatSendButton); + if (isDesktopDevice()) { + show(whiteboardGridBtn); + } if (DetectRTC.isMobileDevice) { hide(initVideoAudioRefreshButton); hide(refreshVideoDevices); @@ -2097,8 +2110,7 @@ async function toggleScreenSharing() { } function handleCameraMirror(video) { - const isDesktopDevice = !DetectRTC.isMobileDevice && !isTabletDevice && !isIPadDevice; - if (isDesktopDevice) { + if (isDesktopDevice()) { // Desktop devices... if (!video.classList.contains('mirror')) { video.classList.toggle('mirror'); @@ -2357,6 +2369,9 @@ function handleSelects() { wbIsBgTransparent = !wbIsBgTransparent; wbIsBgTransparent ? wbCanvasBackgroundColor('rgba(0, 0, 0, 0.100)') : setTheme(); }; + whiteboardGridBtn.onclick = (e) => { + toggleCanvasGrid(); + }; // room moderator rules switchEveryoneMute.onchange = (e) => { const audioStartMuted = e.currentTarget.checked; @@ -3079,25 +3094,19 @@ function setupWhiteboardCanvas() { } function setupWhiteboardCanvasSize() { - let optimalSize = [wbWidth, wbHeight]; - let scaleFactorX = window.innerWidth / optimalSize[0]; - let scaleFactorY = window.innerHeight / optimalSize[1]; - if (scaleFactorX < scaleFactorY && scaleFactorX < 1) { - wbCanvas.setWidth(optimalSize[0] * scaleFactorX); - wbCanvas.setHeight(optimalSize[1] * scaleFactorX); - wbCanvas.setZoom(scaleFactorX); - setWhiteboardSize(optimalSize[0] * scaleFactorX, optimalSize[1] * scaleFactorX); - } else if (scaleFactorX > scaleFactorY && scaleFactorY < 1) { - wbCanvas.setWidth(optimalSize[0] * scaleFactorY); - wbCanvas.setHeight(optimalSize[1] * scaleFactorY); - wbCanvas.setZoom(scaleFactorY); - setWhiteboardSize(optimalSize[0] * scaleFactorY, optimalSize[1] * scaleFactorY); - } else { - wbCanvas.setWidth(optimalSize[0]); - wbCanvas.setHeight(optimalSize[1]); - wbCanvas.setZoom(1); - setWhiteboardSize(optimalSize[0], optimalSize[1]); - } + const optimalSize = [wbWidth, wbHeight]; + const scaleFactorX = window.innerWidth / optimalSize[0]; + const scaleFactorY = window.innerHeight / optimalSize[1]; + const scaleFactor = Math.min(scaleFactorX, scaleFactorY, 1); + + const newWidth = optimalSize[0] * scaleFactor; + const newHeight = optimalSize[1] * scaleFactor; + + wbCanvas.setWidth(newWidth); + wbCanvas.setHeight(newHeight); + wbCanvas.setZoom(scaleFactor); + setWhiteboardSize(newWidth, newHeight); + wbCanvas.calcOffset(); wbCanvas.renderAll(); } @@ -3107,6 +3116,51 @@ function setWhiteboardSize(w, h) { document.documentElement.style.setProperty('--wb-height', h); } +function drawCanvasGrid() { + const width = wbCanvas.getWidth(); + const height = wbCanvas.getHeight(); + + removeCanvasGrid(); + + // Draw vertical lines + for (let i = 0; i <= width; i += wbGridSize) { + wbGridLines.push(createGridLine(i, 0, i, height)); + } + // Draw horizontal lines + for (let i = 0; i <= height; i += wbGridSize) { + wbGridLines.push(createGridLine(0, i, width, i)); + } + + // Create a group for grid lines and send it to the back + const gridGroup = new fabric.Group(wbGridLines, { selectable: false, evented: false }); + wbCanvas.add(gridGroup); + gridGroup.sendToBack(); + wbCanvas.renderAll(); +} + +function createGridLine(x1, y1, x2, y2) { + return new fabric.Line([x1, y1, x2, y2], { + stroke: wbStroke, + selectable: false, + evented: false, + }); +} + +function removeCanvasGrid() { + wbGridLines.forEach((line) => { + line.set({ stroke: wbGridVisible ? wbStroke : 'rgba(255, 255, 255, 0)' }); + wbCanvas.remove(line); + }); + wbGridLines = []; + wbCanvas.renderAll(); +} + +function toggleCanvasGrid() { + wbGridVisible = !wbGridVisible; + wbGridVisible ? drawCanvasGrid() : removeCanvasGrid(); + wbCanvasToJson(); +} + function setWhiteboardBgColor(color) { let data = { peer_name: peer_name, @@ -4171,7 +4225,7 @@ function showAbout() { imageUrl: image.about, customClass: { image: 'img-about' }, position: 'center', - title: 'WebRTC SFU v1.4.94', + title: 'WebRTC SFU v1.4.95', html: `
diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index cd1dbc6d..cfcbca1c 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -9,7 +9,7 @@ * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.4.94 + * @version 1.4.95 * */ diff --git a/public/views/Room.html b/public/views/Room.html index 5ed6632e..57ebb6be 100644 --- a/public/views/Room.html +++ b/public/views/Room.html @@ -1192,6 +1192,7 @@ access to use this app.
+