最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - How can I draw the plan of one floor of the building using javascript - Stack Overflow

programmeradmin5浏览0评论

I want to draw 2D floor plan on html page.

I have a data set looks like below.

Dataset

{
  floor:{
    "id" : 2,
     rooms:[
       {
        "id" : 21,
        "x"  : 0.0,
        "y"  : 0.0,
        "height" : 15,
        "weight" : 20 
       }
       .
       .
       .
     ]
  }
}

I want to get a plan similar to the image below

And I want to add tooltip when hover on room.

Is there a library you can remend?

I want to draw 2D floor plan on html page.

I have a data set looks like below.

Dataset

{
  floor:{
    "id" : 2,
     rooms:[
       {
        "id" : 21,
        "x"  : 0.0,
        "y"  : 0.0,
        "height" : 15,
        "weight" : 20 
       }
       .
       .
       .
     ]
  }
}

I want to get a plan similar to the image below

And I want to add tooltip when hover on room.

Is there a library you can remend?

Share Improve this question edited May 11, 2020 at 10:01 Aytekin asked May 4, 2020 at 23:47 AytekinAytekin 1771 gold badge1 silver badge15 bronze badges 2
  • I don't think you need a library. You can quite easily draw SVG using coords. Another option is drawing on <canvas>, but in this case SVG is probably easier. – Robo Robok Commented May 4, 2020 at 23:50
  • I would also favor SVG instead of Canvas. It will be easier to create the mouse hovers/popups in the DOM instead of having to create them in canvas. – Albert Skibinski Commented May 14, 2020 at 14:22
Add a ment  | 

4 Answers 4

Reset to default 8 +25

No library needed, draw the SVG shapes yourself, it is worth the investment.

Your main SVG elements are:

  • RECTangles: https://developer.mozilla/en-US/docs/Web/SVG/Element/rect

  • Groups: https://developer.mozilla/en-US/docs/Web/SVG/Element/g

Door openings are white rectangles layered on top.

Alternative is use PATHs

  • https://developer.mozilla/en-US/docs/Web/SVG/Element/path

My advice: Draw 5 RECTangles first, after that learn PATH notation (drawing the same RECT shape)

Overlays are 'mouseover' EventListeners that show/hide (Group)SVG, just like you show/hide HTML Elements with JavaScript

Start with typing SVG in a JSFiddle or CodePen.
If you use VS-Code, add the SVG Preview extension: https://github./SimonSiefke/vscode-svg-preview

You will have a first draft within an hour.

Note: Your current dataset does not have/show coordinates, so drawing is all up to you.

You'll need more details in your data set. Here's code that produces the image you want... or something like it.

      const dataSet = {
        floor:{
          "id" : 2,
           rooms:[
             {
              "id" : 21,
              "x"  : 0.0,
              "y"  : 0.0,
              "height" : 15,
              "width" : 15,
              "weight": 0.4,
              "gap": 0.8,
              "roomSize": 5,
              "corridor": 2

             }
           ]
        }
      }
    
      const roomData = dataSet.floor.rooms[0]
      const { id
           , x
           , y
          , height
          , width
          , weight
          , gap
          , roomSize
          , corridor
          } = roomData

      const areaWidth = width - roomSize - 2 * weight
      const areaHeight = roomSize - weight
      const area = areaWidth * areaHeight
      const areas = {
        room1: area
      , room2: area
      , room3: area - weight * areaWidth
      , room4: (roomSize - 2* weight) * (roomSize - 2* weight)
      }
  
      let html = `<svg
        version="1.1"
        xmlns="http://www.w3/2000/svg"
        viewBox="0 0 ${width} ${height}"
        style={style}
      >
         <path
          d="M ${x},${y}
             h ${width - roomSize}
             v ${height - roomSize}
             h ${roomSize}
             v ${roomSize}

             h -${roomSize + 2 * weight}
             v -${weight}
             h ${weight}
             v -${weight}
             h ${weight}
             v ${weight}

             h ${roomSize - weight}
             v -${roomSize - 2 * weight}
             h -${roomSize - weight}
             v ${roomSize - 3 * weight - gap}
             h -${weight}

             v -${height - 3 * weight - gap}
             h -${width - roomSize - 2 * weight}
             
             v ${roomSize - weight}
             h ${width - roomSize - 2 * weight - corridor}
             v ${ weight}
             h -${width - roomSize - 2 * weight - corridor}

             v ${roomSize - weight}         
             h ${width - roomSize - 2 * weight - corridor}
             v ${ weight}
             h -${width - roomSize - 2 * weight - corridor}

             v ${roomSize - 2 * weight}
             h ${width - roomSize - 2 * weight - corridor}
             v ${weight}
             H 0
             z
            "
        />
        <rect
          id="room1"
          x="${weight}"
          y="${weight}"
          width="${width - roomSize - 2 * weight}"
          height="${roomSize - weight}"
          fill="#fee"
        />
        <rect
          id="room2"
          x="${weight}"
          y="${roomSize + weight}"
          width="${width - roomSize - 2 * weight}"
          height="${roomSize - weight}"
          fill="#efe"
        />
        <rect
          id="room3"
          x="${weight}"
          y="${roomSize * 2 + weight}"
          width="${width - roomSize - 2 * weight}"
          height="${roomSize - 2 * weight}"
          fill="#eef"
        />
        <rect
          id="room4"
          x="${width - roomSize}"
          y="${roomSize * 2 + weight}"
          width="${roomSize - weight}"
          height="${roomSize - 2 * weight}"
          fill="#fef"
        />
      </svg>
      `
     
      const svg = document.createElement("svg")
      svg.innerHTML = html

      document.body.appendChild(svg)

      const showArea = (event) => {
        const id = event.target.id
        const area = Math.round(areas[id])
        console.log("Area " + area + " square feet")
      }

      const rooms = [...document.querySelectorAll("rect")]
      rooms.forEach(room => {
        room.addEventListener("mouseenter", showArea, false)
      })

The room area is shown in the Console rather than as an overlay, so you'll have to modify the code to show it as a tooltip.

I think you would need an SVG based solution, because SVGs are efficient when there are user interactions like clicks & mouseovers involved. to ha there are a couple of libraries. I would remend Raphael.js

Its been around for a while, its simple to set up and easy to use. There are also a couple of good starter books that help you learn the whole library in a day. Raphael JS, Raphael JS Starter

I think you can use D3.js, although I don't know if it will be an overkill for your usecase. D3.js is an awesome library to create data-driven documents, i.e when you have some custom data, and you want to use that data to manipulate the HTML DOM elements. It also supports dynamic runtime behaviour and animation.

  • An easy quickstart for d3.js is https://www.dashingd3js./svg-basic-shapes-and-d3js.
  • Freecodecamp tutorial
  • Drawing Rectangle blocks using D3.js - https://bl.ocks/romsson/568e166d702b4a464347 (This example is a bit interactive).
  • This example shows how to show Tooltips while creating a document with d3.js https://bl.ocks/d3noob/a22c42db65eb00d4e369
发布评论

评论列表(0)

  1. 暂无评论