diff --git a/src/main/java/cn/airnan/dg/entity/Room.java b/src/main/java/cn/airnan/dg/entity/Room.java index f27402a..71dfee7 100644 --- a/src/main/java/cn/airnan/dg/entity/Room.java +++ b/src/main/java/cn/airnan/dg/entity/Room.java @@ -86,7 +86,7 @@ public class Room { * @param playerId 发送者的ID(用于排除发送者) */ public void sendMessage(String type, String playerId, String message) { - if (type.equals(Global.MSG_TYPE_ROOM_DRAW)) { + if (type.startsWith(Global.MSG_TYPE_ROOM_DRAW)) { log.info("【绘画房间消息】{}: {}", id, message); for (Player player : players) { // 向除自己之外的玩家发送消息 diff --git a/src/main/resources/static/css/game.css b/src/main/resources/static/css/game.css index 624f871..93b3978 100644 --- a/src/main/resources/static/css/game.css +++ b/src/main/resources/static/css/game.css @@ -1,90 +1,123 @@ #game-top-box { - width: 100%; - display: flex; - justify-content: space-between; + width: 100%; + display: flex; + justify-content: space-between; } #draw-box { - width: 350px; - margin: 0 auto; - min-height: 350px; - box-sizing: border-box; - border: #000000 solid 1px; - border-radius: 15px; - background-color: #daeefd; + width: 350px; + margin: 0 auto; + min-height: 350px; + box-sizing: border-box; + border: #000000 solid 1px; + border-radius: 15px; + background-color: #daeefd; } #topic-bar { - width: 350px; - height: 30px; - line-height: 30px; - display: flex; - justify-content: space-between; - font-size: 0.8em; + width: 350px; + height: 30px; + line-height: 30px; + display: flex; + justify-content: space-between; + font-size: 0.8em; } #topic-bar > div { - flex: 1; + flex: 1; } #board { - width: 300px; - height: 300px; - background-color: #ffffff; - box-shadow: #000000 0 0 1px; - border-radius: 10px; - touch-action: none; + width: 300px; + height: 300px; + background-color: #ffffff; + box-shadow: #000000 0 0 1px; + border-radius: 10px; + touch-action: none; +} + +.control-btn { + box-sizing: border-box; + width: 30px; + height: 30px; + font-size: 1.2em; + background-color: transparent; + border: none; + border-radius: 30px; +} + +.select-box { + display: flex; + align-items:center; + justify-content: space-around; + width: 100%; + height: 80px; + box-sizing: border-box; + padding: 15px; + text-align: left; } .color-btn { - width: 20px; - height: 20px; - padding: 0; - background-color: #ffffff; - border-radius: 20px; - border: 2px solid white; + width: 30px; + height: 30px; + padding: 0; + background-color: #ffffff; + border-radius: 30px; + border: 4px solid transparent; + box-shadow: #00000033 0 0 10px; } +.width-btn,.eraser-btn { + box-sizing: content-box; + width: 12px; + height: 12px; + padding: 0; + border-radius: 24px; + background-color: #444444; + border: 4px solid #444444; + box-shadow: #00000033 0 0 10px; +} #player-box { - display: flex; - justify-content: center; - width: 100%; + display: flex; + justify-content: center; + width: 100%; } .player-item { - box-sizing: border-box; - width: 30px; - height: 30px; - line-height: 30px; - border-radius: 4px; - font-size: 1.4em; - color: coral; - background-color: #ffffff; - box-shadow: #00000022 0 0 5px; - margin: 5px 10px; + box-sizing: border-box; + width: 30px; + height: 30px; + line-height: 30px; + border-radius: 4px; + font-size: 1.4em; + color: coral; + background-color: #ffffff; + box-shadow: #00000022 0 0 5px; + margin: 5px 10px; } #chat-box { - width: calc(100vw - 20px); - height: calc(100vh - 540px); - box-sizing: border-box; - padding: 10px; - margin: auto; - border-radius: 10px; - background-color: #00000022; - box-shadow: #000000 0 0 1px; - text-align: left; - font-size: 0.8em; - overflow-y: scroll; + width: calc(100vw - 20px); + height: calc(100vh - 540px); + box-sizing: border-box; + padding: 10px; + margin: auto; + border-radius: 10px; + background-color: #00000022; + box-shadow: #000000 0 0 1px; + text-align: left; + font-size: 0.8em; + overflow-y: scroll; } #chat-input-box { - width: 100vw; - height: 50px; - position: fixed; - bottom: 0; - background-color: #bbe1ec; + width: 100vw; + height: 50px; + position: fixed; + bottom: 0; + background-color: #bbe1ec; } + #chat-input { - width: calc(100vw - 100px); + width: calc(100vw - 100px); } diff --git a/src/main/resources/static/css/main.css b/src/main/resources/static/css/main.css index 691461a..16ff364 100644 --- a/src/main/resources/static/css/main.css +++ b/src/main/resources/static/css/main.css @@ -101,4 +101,19 @@ body { color: #000000; border-radius: 6px; pointer-events: none; +} + +@font-face { + font-family: 'iconfont'; + src: url('../icon/iconfont.woff2?t=1713086382342') format('woff2'), + url('../icon/iconfont.woff?t=1713086382342') format('woff'), + url('../icon/iconfont.ttf?t=1713086382342') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } \ No newline at end of file diff --git a/src/main/resources/static/icon/iconfont.ttf b/src/main/resources/static/icon/iconfont.ttf new file mode 100644 index 0000000..42d18fb Binary files /dev/null and b/src/main/resources/static/icon/iconfont.ttf differ diff --git a/src/main/resources/static/icon/iconfont.woff b/src/main/resources/static/icon/iconfont.woff new file mode 100644 index 0000000..2dd7ba6 Binary files /dev/null and b/src/main/resources/static/icon/iconfont.woff differ diff --git a/src/main/resources/static/icon/iconfont.woff2 b/src/main/resources/static/icon/iconfont.woff2 new file mode 100644 index 0000000..9a5e638 Binary files /dev/null and b/src/main/resources/static/icon/iconfont.woff2 differ diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index b63517d..b1c26c8 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -39,7 +39,7 @@
- +
@@ -48,31 +48,65 @@
提示:成语,四个字
+
+
+ + + + + + +
+
+ + +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
-
- - - - - -
-
- - - - - -
+
张
王
@@ -321,16 +355,17 @@ }; ws.onmessage = function (evt) { let result = JSON.parse(evt.data); - //接收到通知消息 + // 接收到通知消息 if (result.type === "room-msg") { showMsg(result.data); } + // 接收聊天消息 if (result.type === "room-chat") { $("#chat-box").append("

" + result.data + "

") } + // 接收绘画消息 if (result.type === "room-draw") { let brush = JSON.parse(result.data); - console.log("收到坐标: ", brush.x, brush.y); if (brush.isPoint) { brushPoint = {x: brush.x, y: brush.y} drawPoint(brush.x, brush.y, brush.width, brush.color); @@ -347,7 +382,10 @@ }, brush.width, brush.color); brushPoint = {x: brush.x, y: brush.y}; } - + } + // 接收清空画板消息 + if (result.type === "room-draw-clear") { + clearDraw(); } }; diff --git a/src/main/resources/static/js/draw.js b/src/main/resources/static/js/draw.js index 5fedca8..56ad79a 100644 --- a/src/main/resources/static/js/draw.js +++ b/src/main/resources/static/js/draw.js @@ -3,9 +3,12 @@ let canvas = document.getElementById("board"); let context = canvas.getContext("2d"); context.imageSmoothingEnabled = true; let brushColor = "#000000"; -let brushWidth = 2; +let brushWidth = 8; let brushPoint = {x: 0, y: 0}; let isDrawing = false; + +let eraserWidth = 8; +let useEraser = false; // PC端 ******************************* // 鼠标按下事件处理程序 canvas.addEventListener("mousedown", function (event) { @@ -13,7 +16,12 @@ canvas.addEventListener("mousedown", function (event) { brushPoint = getBrushPoint(event); // 广播绘画数据 sendDrawData(brushPoint.x, brushPoint.y, true); - drawPoint(brushPoint.x, brushPoint.y, brushWidth, brushColor); + // 判断是否是橡皮 + if (useEraser) { + drawPoint(brushPoint.x, brushPoint.y, eraserWidth, "#ffffff"); + } else { + drawPoint(brushPoint.x, brushPoint.y, brushWidth, brushColor); + } }); // 鼠标移动事件处理程序 @@ -22,7 +30,12 @@ canvas.addEventListener("mousemove", function (event) { let newPoint = getBrushPoint(event); // 广播绘画数据 sendDrawData(newPoint.x, newPoint.y, false); - drawLine(brushPoint, newPoint, brushWidth, brushColor); + // 判断是否是橡皮 + if (useEraser) { + drawLine(brushPoint, newPoint, eraserWidth, "#ffffff"); + } else { + drawLine(brushPoint, newPoint, brushWidth, brushColor); + } brushPoint = newPoint; } }); @@ -39,7 +52,12 @@ canvas.addEventListener("touchstart", function (event) { brushPoint = getTouchPoint(event); // 广播绘画数据 sendDrawData(brushPoint.x, brushPoint.y, true); - drawPoint(brushPoint.x, brushPoint.y, brushWidth, brushColor); + // 判断是否是橡皮 + if (useEraser) { + drawPoint(brushPoint.x, brushPoint.y, eraserWidth, "#ffffff"); + } else { + drawPoint(brushPoint.x, brushPoint.y, brushWidth, brushColor); + } }); // 触摸移动事件处理程序 @@ -49,7 +67,12 @@ canvas.addEventListener("touchmove", function (event) { let newPoint = getTouchPoint(event.touches[0]); // 使用第一个触摸点 // 广播绘画数据 sendDrawData(newPoint.x, newPoint.y, false); - drawLine(brushPoint, newPoint, brushWidth, brushColor); + // 判断是否是橡皮 + if (useEraser) { + drawLine(brushPoint, newPoint, eraserWidth, "#ffffff"); + } else { + drawLine(brushPoint, newPoint, brushWidth, brushColor); + } brushPoint = newPoint; } }); @@ -67,6 +90,7 @@ function getBrushPoint(event) { y: (event.clientY - rect.top) * 2 }; } + // 计算画笔在画布上的触摸坐标 function getTouchPoint(touch) { let rect = canvas.getBoundingClientRect(); @@ -75,6 +99,7 @@ function getTouchPoint(touch) { y: (touch.clientY - rect.top) * (canvas.height / rect.height) }; } + // 绘制单个点 function drawPoint(x, y, width, color) { context.beginPath(); @@ -102,8 +127,8 @@ function sendDrawData(x, y, isPoint) { const drawData = { x, y, - color: brushColor, - width: brushWidth, + color: useEraser ? "#ffffff" : brushColor, + width: useEraser ? eraserWidth : brushWidth, isPoint }; @@ -118,10 +143,105 @@ function changeBrushColor(color) { brushColor = color; } + /** * 切换画笔宽度 * @param width 整数 */ function changeBrushWidth(width) { brushWidth = width; -} \ No newline at end of file +} + +/** + * 切换橡皮宽度 + * @param width 整数 + */ +function changeEraserWidth(width) { + eraserWidth = width; +} + +/** + * 发送清空画板命令 + */ +function sendClearDraw() { + sendMessage("room-draw-clear", true); + clearDraw(); +} + +/** + * 清空画板 + */ +function clearDraw() { + context.clearRect(0, 0, 600, 600); + context.beginPath(); + canvas.width = canvas.width; + showMsg("画板已清空"); +} + +/** + * 打开或关闭颜色选择框 + */ +function toggleColorBox() { + $("#width-select-box").hide(); + $("#eraser-select-box").hide(); + $("#color-select-box").show(); +} + +/** + * 打开或关闭画笔粗细选择框 + */ +function toggleWidthBox() { + $("#color-select-box").hide(); + $("#eraser-select-box").hide(); + $("#width-select-box").show(); +} + +/** + * 打开或关闭橡皮粗细选择框 + */ +function toggleEraserBox() { + $("#width-select-box").hide(); + $("#color-select-box").hide(); + $("#eraser-select-box").show(); +} + +// 默认隐藏所有工具框 +$(".select-box").hide(); +/** + * 颜色按钮事件 + */ +$(".color-btn").click(function () { + changeBrushColor($(this).attr("data-color")); + $(".color-btn").css("border-color", "transparent"); + $(this).css("border-color", "#ffffff"); +}) + +/** + * 画笔宽度按钮事件 + */ +$(".width-btn").click(function () { + changeBrushWidth($(this).attr("data-width")); + $(".width-btn").css("border-color", "#444444"); + $(this).css("border-color", "#ffffff"); +}) + +/** + * 画笔宽度按钮事件 + */ +$(".eraser-btn").click(function () { + changeEraserWidth($(this).attr("data-width")); + $(".eraser-btn").css("border-color", "#444444"); + $(this).css("border-color", "#ffffff"); +}) + +/** + * 橡皮状态切换 + */ +$("#eraser-select-btn").click(function () { + useEraser = !useEraser; + if(useEraser){ + $(this).css("background-color", "#ffffff"); + }else { + $(this).css("background-color", "transparent"); + } +})