You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Spring MVC的码头管理系统2D平面图实现技术咨询

解决方案

1. 定义码头数据模型

先创建一个封装码头属性的实体类,用于在Controller和视图间传递数据:

public class Dock {
    private int x; // 左上角x坐标(数学坐标系,从左下原点开始)
    private int y; // 左上角y坐标
    private int width; // 码头宽度
    private int height; // 码头高度
    private String name; // 码头名称(用于标注)

    // 构造函数、getter、setter按需实现
}

2. Controller层处理数据传递

Controller只负责准备数据并传递到JSP,不处理任何绘图逻辑,核心代码如下:

@Controller
@RequestMapping("/dock")
public class DockController {

    @GetMapping("/plan")
    public String showDockPlan(Model model) {
        // 替换为从数据库/服务层获取的真实数据
        List<Dock> docks = new ArrayList<>();
        docks.add(new Dock(50, 100, 150, 80, "码头A"));
        docks.add(new Dock(250, 150, 120, 100, "码头B"));
        docks.add(new Dock(100, 280, 200, 70, "码头C"));

        // 设置画布和坐标轴参数(根据实际场景调整)
        model.addAttribute("canvasWidth", 500);
        model.addAttribute("canvasHeight", 400);
        model.addAttribute("axisMaxX", 500);
        model.addAttribute("axisMaxY", 400);
        model.addAttribute("docks", docks);

        return "dock-plan"; // 返回对应的JSP视图名称
    }
}

3. JSP视图实现2D平面图

提供两种实用方案,根据需求选择:

方案A:HTML+CSS绘制(适合简单静态场景)

利用绝对定位的div模拟码头矩形,配合CSS实现坐标轴:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>码头平面图</title>
    <style>
        .canvas-container {
            position: relative;
            width: ${canvasWidth}px;
            height: ${canvasHeight}px;
            border: 2px solid #333;
            margin: 20px;
        }
        .axis-x {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 2px;
            background: #000;
        }
        .axis-y {
            position: absolute;
            top: 0;
            left: 0;
            width: 2px;
            height: 100%;
            background: #000;
        }
        .dock-rect {
            position: absolute;
            border: 2px solid #2196F3;
            background: rgba(33, 150, 243, 0.2);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            font-size: 14px;
        }
        .axis-label {
            position: absolute;
            font-size: 12px;
            color: #666;
        }
    </style>
</head>
<body>
    <h2>码头2D平面图</h2>
    <div class="canvas-container">
        <!-- 坐标轴 -->
        <div class="axis-x"></div>
        <div class="axis-y"></div>

        <!-- 渲染码头矩形 -->
        <c:forEach items="${docks}" var="dock">
            <div class="dock-rect" 
                 style="left: ${dock.x}px; bottom: ${dock.y}px; width: ${dock.width}px; height: ${dock.height}px;">
                ${dock.name}
            </div>
        </c:forEach>

        <!-- 坐标轴刻度标签 -->
        <c:forEach var="i" begin="0" end="${axisMaxX}" step="100">
            <div class="axis-label" style="left: ${i}px; bottom: -20px;">${i}</div>
        </c:forEach>
        <c:forEach var="i" begin="0" end="${axisMaxY}" step="100">
            <div class="axis-label" style="left: -20px; bottom: ${i}px;">${i}</div>
        </c:forEach>
    </div>
</body>
</html>

方案B:Canvas绘制(适合需要交互的场景)

如果需要缩放、拖拽等交互功能,用Canvas更灵活:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>码头平面图</title>
    <style>
        canvas {
            border: 2px solid #333;
            margin: 20px;
        }
    </style>
</head>
<body>
    <h2>码头2D平面图</h2>
    <canvas id="dockCanvas" width="${canvasWidth}" height="${canvasHeight}"></canvas>

    <script>
        const canvas = document.getElementById('dockCanvas');
        const ctx = canvas.getContext('2d');
        const axisMaxX = ${axisMaxX};
        const axisMaxY = ${axisMaxY};
        const docks = [
            <c:forEach items="${docks}" var="dock" varStatus="status">
                {x: ${dock.x}, y: ${dock.y}, width: ${dock.width}, height: ${dock.height}, name: "${dock.name}" }<c:if test="${!status.last}">,</c:if>
            </c:forEach>
        ];

        // 绘制坐标轴
        ctx.beginPath();
        ctx.moveTo(0, canvas.height);
        ctx.lineTo(canvas.width, canvas.height); // X轴
        ctx.moveTo(0, 0);
        ctx.lineTo(0, canvas.height); // Y轴
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.stroke();

        // 绘制坐标轴刻度和标签
        ctx.font = '12px Arial';
        ctx.fillStyle = '#666';
        // X轴刻度
        for (let i = 0; i <= axisMaxX; i += 100) {
            ctx.moveTo(i, canvas.height);
            ctx.lineTo(i, canvas.height - 5);
            ctx.stroke();
            ctx.fillText(i, i - 15, canvas.height + 20);
        }
        // Y轴刻度(转换Canvas坐标系)
        for (let i = 0; i <= axisMaxY; i += 100) {
            const yPos = canvas.height - i;
            ctx.moveTo(0, yPos);
            ctx.lineTo(5, yPos);
            ctx.stroke();
            ctx.fillText(i, -25, yPos + 5);
        }

        // 绘制码头矩形
        docks.forEach(dock => {
            // 转换Canvas Y轴坐标(Canvas原点在左上,需转成数学坐标系的左下原点)
            const yPos = canvas.height - dock.y - dock.height;
            ctx.beginPath();
            ctx.rect(dock.x, yPos, dock.width, dock.height);
            ctx.strokeStyle = '#2196F3';
            ctx.lineWidth = 2;
            ctx.stroke();
            ctx.fillStyle = 'rgba(33, 150, 243, 0.2)';
            ctx.fill();
            // 绘制码头名称
            ctx.fillStyle = '#333';
            ctx.font = 'bold 14px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(dock.name, dock.x + dock.width/2, yPos + dock.height/2);
        });
    </script>
</body>
</html>

关键注意事项

  • Controller职责边界:只负责数据准备,绘图逻辑完全交给前端,避免后端做可视化工作。
  • 坐标转换:HTML/CSS和Canvas的坐标系与常规数学坐标系不同,需要通过bottom属性或坐标计算对齐需求。
  • 数据替换:示例中的模拟数据,实际项目中替换为从数据库或业务服务获取的真实码头数据即可。

内容的提问来源于stack exchange,提问作者Réda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:41:58