[mirotalksfu] - add whiteboard gridLine
هذا الالتزام موجود في:
@@ -44,7 +44,7 @@ dependencies: {
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.4.94
|
* @version 1.4.95
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mirotalksfu",
|
"name": "mirotalksfu",
|
||||||
"version": "1.4.94",
|
"version": "1.4.95",
|
||||||
"description": "WebRTC SFU browser-based video calls",
|
"description": "WebRTC SFU browser-based video calls",
|
||||||
"main": "Server.js",
|
"main": "Server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1176,8 +1176,8 @@ progress {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: calc(var(--wb-width) * 1px);
|
width: var(--wb-width);
|
||||||
height: calc(var(--wb-height) * 1px);
|
height: var(--wb-height);
|
||||||
background: var(--wb-bg);
|
background: var(--wb-bg);
|
||||||
border: var(--border);
|
border: var(--border);
|
||||||
box-shadow: var(--box-shadow);
|
box-shadow: var(--box-shadow);
|
||||||
@@ -1185,6 +1185,10 @@ progress {
|
|||||||
/* overflow: hidden; */
|
/* overflow: hidden; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #wbCanvas {
|
||||||
|
border: var(--border);
|
||||||
|
} */
|
||||||
|
|
||||||
.whiteboard-header {
|
.whiteboard-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
@@ -1225,7 +1229,7 @@ progress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.whiteboard-header-options .dropdown-menu {
|
.whiteboard-header-options .dropdown-menu {
|
||||||
max-height: calc(var(--wb-height) * 1px);
|
max-height: var(--wb-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
.whiteboard-header-options .dropdown-menu button {
|
.whiteboard-header-options .dropdown-menu button {
|
||||||
|
|||||||
@@ -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 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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @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,';
|
const Base64Prefix = 'data:application/pdf;base64,';
|
||||||
|
|
||||||
|
// Whiteboard
|
||||||
const wbImageInput = 'image/*';
|
const wbImageInput = 'image/*';
|
||||||
const wbPdfInput = 'application/pdf';
|
const wbPdfInput = 'application/pdf';
|
||||||
const wbWidth = 1280;
|
const wbWidth = 1366;
|
||||||
const wbHeight = 768;
|
const wbHeight = 768;
|
||||||
|
const wbGridSize = 20;
|
||||||
|
const wbStroke = '#cccccc63';
|
||||||
|
let wbGridLines = [];
|
||||||
|
let wbGridVisible = false;
|
||||||
|
|
||||||
const swalImageUrl = '../images/pricing-illustration.svg';
|
const swalImageUrl = '../images/pricing-illustration.svg';
|
||||||
|
|
||||||
@@ -303,6 +308,7 @@ function initClient() {
|
|||||||
setTippy('refreshVideoFiles', 'Refresh', 'left');
|
setTippy('refreshVideoFiles', 'Refresh', 'left');
|
||||||
setTippy('switchServerRecording', 'The recording will be stored on the server rather than locally', 'right');
|
setTippy('switchServerRecording', 'The recording will be stored on the server rather than locally', 'right');
|
||||||
setTippy('whiteboardGhostButton', 'Toggle transparent background', 'bottom');
|
setTippy('whiteboardGhostButton', 'Toggle transparent background', 'bottom');
|
||||||
|
setTippy('whiteboardGridBtn', 'Toggle whiteboard grid', 'bottom');
|
||||||
setTippy('wbBackgroundColorEl', 'Background color', 'bottom');
|
setTippy('wbBackgroundColorEl', 'Background color', 'bottom');
|
||||||
setTippy('wbDrawingColorEl', 'Drawing color', 'bottom');
|
setTippy('wbDrawingColorEl', 'Drawing color', 'bottom');
|
||||||
setTippy('whiteboardPencilBtn', 'Drawing mode', 'bottom');
|
setTippy('whiteboardPencilBtn', 'Drawing mode', 'bottom');
|
||||||
@@ -1138,6 +1144,10 @@ async function shareRoom(useNavigator = false) {
|
|||||||
// ROOM UTILITY
|
// ROOM UTILITY
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
|
function isDesktopDevice() {
|
||||||
|
return !DetectRTC.isMobileDevice && !isTabletDevice && !isIPadDevice;
|
||||||
|
}
|
||||||
|
|
||||||
function makeRoomQR() {
|
function makeRoomQR() {
|
||||||
let qr = new QRious({
|
let qr = new QRious({
|
||||||
element: document.getElementById('qrRoom'),
|
element: document.getElementById('qrRoom'),
|
||||||
@@ -1274,6 +1284,9 @@ function roomIsReady() {
|
|||||||
show(chatCleanTextButton);
|
show(chatCleanTextButton);
|
||||||
show(chatPasteButton);
|
show(chatPasteButton);
|
||||||
show(chatSendButton);
|
show(chatSendButton);
|
||||||
|
if (isDesktopDevice()) {
|
||||||
|
show(whiteboardGridBtn);
|
||||||
|
}
|
||||||
if (DetectRTC.isMobileDevice) {
|
if (DetectRTC.isMobileDevice) {
|
||||||
hide(initVideoAudioRefreshButton);
|
hide(initVideoAudioRefreshButton);
|
||||||
hide(refreshVideoDevices);
|
hide(refreshVideoDevices);
|
||||||
@@ -2097,8 +2110,7 @@ async function toggleScreenSharing() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleCameraMirror(video) {
|
function handleCameraMirror(video) {
|
||||||
const isDesktopDevice = !DetectRTC.isMobileDevice && !isTabletDevice && !isIPadDevice;
|
if (isDesktopDevice()) {
|
||||||
if (isDesktopDevice) {
|
|
||||||
// Desktop devices...
|
// Desktop devices...
|
||||||
if (!video.classList.contains('mirror')) {
|
if (!video.classList.contains('mirror')) {
|
||||||
video.classList.toggle('mirror');
|
video.classList.toggle('mirror');
|
||||||
@@ -2357,6 +2369,9 @@ function handleSelects() {
|
|||||||
wbIsBgTransparent = !wbIsBgTransparent;
|
wbIsBgTransparent = !wbIsBgTransparent;
|
||||||
wbIsBgTransparent ? wbCanvasBackgroundColor('rgba(0, 0, 0, 0.100)') : setTheme();
|
wbIsBgTransparent ? wbCanvasBackgroundColor('rgba(0, 0, 0, 0.100)') : setTheme();
|
||||||
};
|
};
|
||||||
|
whiteboardGridBtn.onclick = (e) => {
|
||||||
|
toggleCanvasGrid();
|
||||||
|
};
|
||||||
// room moderator rules
|
// room moderator rules
|
||||||
switchEveryoneMute.onchange = (e) => {
|
switchEveryoneMute.onchange = (e) => {
|
||||||
const audioStartMuted = e.currentTarget.checked;
|
const audioStartMuted = e.currentTarget.checked;
|
||||||
@@ -3079,25 +3094,19 @@ function setupWhiteboardCanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupWhiteboardCanvasSize() {
|
function setupWhiteboardCanvasSize() {
|
||||||
let optimalSize = [wbWidth, wbHeight];
|
const optimalSize = [wbWidth, wbHeight];
|
||||||
let scaleFactorX = window.innerWidth / optimalSize[0];
|
const scaleFactorX = window.innerWidth / optimalSize[0];
|
||||||
let scaleFactorY = window.innerHeight / optimalSize[1];
|
const scaleFactorY = window.innerHeight / optimalSize[1];
|
||||||
if (scaleFactorX < scaleFactorY && scaleFactorX < 1) {
|
const scaleFactor = Math.min(scaleFactorX, scaleFactorY, 1);
|
||||||
wbCanvas.setWidth(optimalSize[0] * scaleFactorX);
|
|
||||||
wbCanvas.setHeight(optimalSize[1] * scaleFactorX);
|
const newWidth = optimalSize[0] * scaleFactor;
|
||||||
wbCanvas.setZoom(scaleFactorX);
|
const newHeight = optimalSize[1] * scaleFactor;
|
||||||
setWhiteboardSize(optimalSize[0] * scaleFactorX, optimalSize[1] * scaleFactorX);
|
|
||||||
} else if (scaleFactorX > scaleFactorY && scaleFactorY < 1) {
|
wbCanvas.setWidth(newWidth);
|
||||||
wbCanvas.setWidth(optimalSize[0] * scaleFactorY);
|
wbCanvas.setHeight(newHeight);
|
||||||
wbCanvas.setHeight(optimalSize[1] * scaleFactorY);
|
wbCanvas.setZoom(scaleFactor);
|
||||||
wbCanvas.setZoom(scaleFactorY);
|
setWhiteboardSize(newWidth, newHeight);
|
||||||
setWhiteboardSize(optimalSize[0] * scaleFactorY, optimalSize[1] * scaleFactorY);
|
|
||||||
} else {
|
|
||||||
wbCanvas.setWidth(optimalSize[0]);
|
|
||||||
wbCanvas.setHeight(optimalSize[1]);
|
|
||||||
wbCanvas.setZoom(1);
|
|
||||||
setWhiteboardSize(optimalSize[0], optimalSize[1]);
|
|
||||||
}
|
|
||||||
wbCanvas.calcOffset();
|
wbCanvas.calcOffset();
|
||||||
wbCanvas.renderAll();
|
wbCanvas.renderAll();
|
||||||
}
|
}
|
||||||
@@ -3107,6 +3116,51 @@ function setWhiteboardSize(w, h) {
|
|||||||
document.documentElement.style.setProperty('--wb-height', 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) {
|
function setWhiteboardBgColor(color) {
|
||||||
let data = {
|
let data = {
|
||||||
peer_name: peer_name,
|
peer_name: peer_name,
|
||||||
@@ -4171,7 +4225,7 @@ function showAbout() {
|
|||||||
imageUrl: image.about,
|
imageUrl: image.about,
|
||||||
customClass: { image: 'img-about' },
|
customClass: { image: 'img-about' },
|
||||||
position: 'center',
|
position: 'center',
|
||||||
title: 'WebRTC SFU v1.4.94',
|
title: 'WebRTC SFU v1.4.95',
|
||||||
html: `
|
html: `
|
||||||
<br />
|
<br />
|
||||||
<div id="about">
|
<div id="about">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.4.94
|
* @version 1.4.95
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1192,6 +1192,7 @@ access to use this app.
|
|||||||
</div>
|
</div>
|
||||||
<div id="whiteboardOptions" class="whiteboard-header-options">
|
<div id="whiteboardOptions" class="whiteboard-header-options">
|
||||||
<button id="whiteboardGhostButton" class="fas fa-circle-half-stroke"></button>
|
<button id="whiteboardGhostButton" class="fas fa-circle-half-stroke"></button>
|
||||||
|
<button id="whiteboardGridBtn" class="fas fa-table-cells-large hidden"></button>
|
||||||
<input id="wbBackgroundColorEl" class="whiteboardColorPicker" type="color" value="#000000" />
|
<input id="wbBackgroundColorEl" class="whiteboardColorPicker" type="color" value="#000000" />
|
||||||
<input id="wbDrawingColorEl" class="whiteboardColorPicker" type="color" value="#FFFFFF" />
|
<input id="wbDrawingColorEl" class="whiteboardColorPicker" type="color" value="#FFFFFF" />
|
||||||
<button id="whiteboardPencilBtn" class="fas fa-pencil-alt"></button>
|
<button id="whiteboardPencilBtn" class="fas fa-pencil-alt"></button>
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم