【问题标题】:how can i store floor plan dynamically?如何动态存储平面图?
【发布时间】:2014-10-08 10:48:55
【问题描述】:

我有一个大学项目来创建平面图设计软件。为此,我正在尝试在 HTML Canvas 和网格的帮助下创建平面图。我想将创建的交互式平面图保存到数据库中,但不能像将平面图保存在数据库中时一样,将其转换为图像文件。我想知道如何在创建地图后将交互式地图保存在数据库中,以及拿来做改动。

简单的canvas map代码如下..

 <!doctype>
 <html>
 <head>
 </head>
 <body style=" background: lightblue;">
 <canvas id="canvas" width="500px" height="500px"style="background: #fff; magrin:20px;"> 
 Browser does not support canvas </canvas>
 <img id="canvasImg" alt="Right click to save me!">
 <script type="text/javascript" language="javascript">                                                                                  
 var bw = 400;
 var bh = 400;
 var p = 10;
 var cw = bw + (p*2) + 1;
 var ch = bh + (p*2) + 1;

 var grid = 50;

 var canvas = document.getElementById("canvas");
 var context = canvas.getContext("2d");

 function drawBoard(){

 context.beginPath();
 for (var x = 0; x <= bw; x += grid){
 context.moveTo(0.5 + x + p, p);
 context.lineTo(0.5 + x + p, bh + p);
 }
 for (var x = 0; x <= bh; x += grid) {
 context.moveTo(p, 0.5 + x + p);
 context.lineTo(bw + p, 0.5 + x + p);
 }
 context.lineWidth = 1;
 context.strokeStyle = "black";
 context.stroke();

 }
 drawBoard();

 function drawRect() {

 context.beginPath();
 context.rect(0.5+p+5*grid, 0.5+p+3*grid, 2*grid, 3*grid);
 context.rect(0.0+p+0*grid, 0.0+p+0*grid, 0*grid, 0*grid);
 context.rect(0.5+p+3*grid, 0.5+p+3*grid, 2*grid, 3*grid);
 context.rect(0.5+p+0*grid, 0.5+p+0*grid, 2*grid, 3*grid);
 context.fillStyle = 'yellow';
 context.fill();
 context.lineWidth = 2;
 context.strokeStyle = 'blue';
 context.stroke();
 }
 drawRect();

  ////new 

 var el = document.getElementById('canvas');
 var ctx = el.getContext('2d');
 var isDrawing;

 el.onmousedown = function(e) {
 isDrawing = true;
 ctx.moveTo(e.clientX, e.clientY);
 };
 el.onmousemove = function(e) {
 if (isDrawing) {
 ctx.lineTo(e.clientX, e.clientY);
 ctx.stroke();
 }
 };
 el.onmouseup = function() {
 isDrawing = false;
 };

 }

 // save canvas image as data url (png format by default)
 var dataURL = canvas.toDataURL();

 // set canvasImg image src to dataURL
 // so it can be saved as an image
  document.getElementById('canvasImg').src = dataURL;

 </script>
 </body>
 </html>

这是输出::

这是静态计划,

我想动态创建并将完整的计划存储在我的数据库(MySQL)上,这可能吗?给出充分的答案。

【问题讨论】:

  • 我将采用的方法是创建一个单独的逻辑地图对象,您可以在其中保存有关坐标和尺寸的信息,并基于您在画布上绘制的对象。您也可以轻松地将这个对象保存到数据库中,因为它只是数据。

标签: javascript canvas html5-canvas


【解决方案1】:

您在此处遇到的问题表明您的应用程序中缺少一些抽象层。

首先你需要定义一个合适的板子对象。它将具有诸如大小、以某种方式组织的计划部分集合之类的属性,并且很可能您需要一些我无法猜测的其他属性。

您还需要一个计划部分对象,-我猜不出什么是好名字-在您的示例中似乎只是矩形。

一旦你有了这两个对象,将它们“序列化”到数据库非常简单,一个 sql 表有一个板列表,另一个表有一个“地板部件”列表,通过链接到它们自己的板一个标识符。

我刚刚做了小班让你开始,小提琴就在这里:

http://jsfiddle.net/48gnjwae/1/

到目前为止,它与您的代码执行相同的操作,但从那时起保存/恢复内容会更容易。

// ----------------------------------------------------------

 function Board(gridWidth, gridHeight, graphicSize) {
     this.gridWidth = gridWidth;
     this.gridHeight = gridHeight;
     this.graphicSize = graphicSize;
     this.planParts = [];
     // no need to serialize this property 
     // but you have to rebuild it after loading from DB
     this.grid = new Array(gridWidth * gridHeight)
 }

 Board.prototype = {
     draw: function (ctx) {
         this.drawGrid(ctx);
         for (var i = 0; i < this.planParts.length; i++) {
             this.planParts[i].draw(ctx);
         }
     },
     canAdd: function (part) {
         // uses getGrid to check no cell is already covered
         // for (x) { for (y) { if this.getGrid(x,y) return false}}
         // return true;
     },
     addPart: function (part) {
         this.planParts.push(part);
         // + setGrid for all covered cells
         // for (x) { for (y) { this.setGrid(x,y,true)}}
     },
     getGrid: function (x, y) {
         return this.grid[x + y * this.gridWidth];
     },
     setGrid: function (x, y, val) {
         this.grid[x + y * this.gridWidth] = val;
     },
     drawGrid: function (ctx) {
         ctx.strokeStyle = "black";
         ctx.save();
         ctx.scale(this.graphicSize, this.graphicSize);
         ctx.lineWidth = 1 / this.graphicSize;
         for (var x = 0; x <= this.gridWidth; x++) {
             line(ctx, x, 0, x, this.gridHeight);
         }
         for (var y = 0; y <= this.gridHeight; y++) {
             line(ctx, 0, y, this.gridWidth, y);
         }
         ctx.restore();
     }
 }

现在是部分:

 // ----------------------------------------------------------

 function PlanPart(board, x, y, w, h) {
     this.board = board;
     this.x = x;
     this.y = y;
     this.w = w;
     this.h = h;
 }

 PlanPart.prototype = {
     draw: function (ctx) {
         ctx.save();
         ctx.fillStyle = 'yellow';
         ctx.strokeStyle = 'blue';
         ctx.scale(this.board.graphicSize, this.board.graphicSize);
         ctx.lineWidth = 2 / this.board.graphicSize;
         ctx.fillRect(this.x, this.y, this.w, this.h);
         ctx.strokeRect(this.x, this.y, this.w, this.h);
         ctx.restore();
     }
 }

使用中:

 // ----------------------------------------------------------

 var myBoard = new Board(8, 8, 50);

 var part;
 part = new PlanPart(myBoard, 0, 0, 2, 3);
 myBoard.addPart(part);
 part = new PlanPart(myBoard, 3, 3, 2, 3);
 myBoard.addPart(part);
 part = new PlanPart(myBoard, 5, 3, 2, 3);
 myBoard.addPart(part);

 myBoard.draw(context);

【讨论】:

    【解决方案2】:

    执行此操作的经典方法称为 MVC-Pattern (ModelViewController-Pattern),您可以在其中将绘画逻辑与模型分开,该模型保留描述应绘画内容的数据。 它还将控制逻辑与绘画逻辑分开。

    通过忽略平面图的绘制方式,尝试找到一种面向对象的方式来描述您的平面图。你可以通过——例如——创建一个 Floor-Object 和一个 Room-Object 来做到这一点。地板对象将包含房间对象。 每个 Room-Object 都会知道它在地板上的位置以及它是如何形成的或它的大小。

    该模型可以很容易地保存在数据库中。

    然后,您将编写绘画逻辑,使逻辑知道如何在画布上绘制模型。

    有关 MVC 的更多信息,请参见此处:http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

    【讨论】:

      猜你喜欢
      • 2021-01-25
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2019-01-04
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多