如何使用CSS Grid制作一个大富翁游戏板?

40

我想创建一个像 enter image description here 这样的大富翁游戏版。这个版有如下特点:

  • 四个角是方形的,比其他格子要大;
  • 每行文字都倾斜一定角度。

我的基本html结构如下:

  • 版面
    • 第一行
      • 方块1
      • 方块2 ...

我成功地使用了grid-template-areas创建了基本结构。但是,我遇到的问题是无法根据需要旋转每行的方块。

我创建了一个只有每行3个方块的基本代码片段。第一行向右倾斜,所有其他行都倾斜得不对。第二行倾斜90deg,第三行倾斜180deg,第四行倾斜270deg

我试过使用writing-modetransform:rotate(),但它们似乎并没有起作用,或者我使用方法不对。请帮我找到正确的方法,我将不胜感激。

*{
  box-sizing: border-box;
}
#board {
   display: grid;
   /*first and last row and column are bigger than others*/
   grid-template-columns: 100px repeat(2, 70px) 100px;
   grid-template-rows: 100px repeat(2, 70px) 100px;
   
   /*a, b, c, d are 4 rows and o is center*/
   grid-template-areas:
      "c c c d"
      "b o o d"
      "b o o d"
      "b a a a";
}
#center {
   grid-area: o;
}
.row {
   display: flex;
}
.tile {
   display: flex;
   flex-direction: column;
   border: 1px solid;
   height: 100%;
   width: 100%;
}
.tile-color {
   flex: 3;
   background: red;
   border: 1px solid;
}
.tile-name {
   flex: 6;
}
.tile-price {
   flex: 3;
}

/*Flex directions are used to give the tiles correct order*/
#row-0 {
   grid-area: a;
   flex-direction: row-reverse;
}
#row-1 {
   grid-area: b;
   flex-direction: column-reverse;
}
#row-2 {
   grid-area: c;
   flex-direction: row;
}
#row-3 {
   grid-area: d;
   flex-direction: column;
}

/*To make the corner tiles bigger and square*/
.row > .tile:nth-child(1){
  flex: 0 0 100px;
}
<div id="board">
   <div id="center"></div>
   
   <!--Row 1-->
   <div class="row" id="row-0">
      <div class="tile">
         <div class="tile-name">Go</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 1</div>
         <div class="tile-price">Price 1</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 2</div>
         <div class="tile-price">Price 2</div>
      </div>
   </div>
   
   <!--Row 2-->
   <div class="row" id="row-1">
      <div class="tile">
         <div class="tile-name">Just visiting</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 3</div>
         <div class="tile-price">Price 3</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 4</div>
         <div class="tile-price">Price 4</div>
      </div>
   </div>
   
   <!--Row 3-->
   <div class="row" id="row-2">
      <div class="tile">
         <div class="tile-name">Free Parking</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 4</div>
         <div class="tile-price">Price 4</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 5</div>
         <div class="tile-price">Price 5</div>
      </div>
   </div>
   
   <!--Row 4-->
   <div class="row" id="row-3">
      <div class="tile">
         <div class="tile-name">Jail</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 6</div>
         <div class="tile-price">Price 6</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 7</div>
         <div class="tile-price">Price 7</div>
      </div>
   </div>
</div>


2
不要旋转“tile”,因为它是您网格布局(骨架)的一部分。在每个“tile”内部放置一个额外的div,其中包含标题和所有内容,并旋转该div。 - Jeremy Thille
@JeremyThille 我已经尝试过了,但是当我旋转附加的 div 时,它无法固定在主 div 内部。 - Maheer Ali
3个回答

18

以下是一种实现方式:

我已经更改了HTML标记,并且没有使用grid-template-areas属性。每个网格项目按照它们在HTML标记中出现的顺序自动放置在网格中。

这是一个4x4网格,其中第一列和最后一列的大小为120像素,中间的2列每个都是75像素。同样,第一行和最后一行的大小为120像素,中间的2行每个都是75像素。

为了旋转网格项,我创建了单独的类并将适当的旋转类应用于需要旋转的单个网格项。

* {
  box-sizing: border-box;
}

.board {
  display: grid;
  grid-template-columns: 120px repeat(2, 75px) 120px;
  grid-template-rows: 120px repeat(2, 75px) 120px;
  justify-content: center;
}

.lg-box {
  text-align: center;
  background: #999;
  border: 1px solid;
  overflow: hidden;
}

.sm-box {
  width: 100%;
  background: blue;
  background: red;
  height: 100%;
  position: relative;
  border: 1px solid;
  overflow: hidden;
}

.sm-box div {
  background: #fff;
  height: 85%;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-align: center;
  position: absolute;
  bottom: 0;
  padding: 5px;
}

.lg-box-centered {
  background: #fff;
  grid-row: 2 / span 2;
  grid-column: 2 / span 2;
}

.rot-180 {
  transform: rotate(180deg);
}

.lg-rot,
.lg-box-centered {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.rot-135 {
  transform: rotate(135deg);
}

.rot-45-reverse {
  transform: rotate(-45deg);
}

.rot-45 {
  transform: rotate(45deg);
}

.rot-135-reverse {
  transform: rotate(-135deg);
}

.rot-90 {
  transform: rotate(90deg);
}

.rot-90-reverse {
  transform: rotate(-90deg);
}

.sm-box .rot-90,
.sm-box .rot-90-reverse {
  position: absolute;
  left: 12px;
  top: -12px;
  width: 75px;
  height: 100px;
}

.sm-box .rot-90-reverse {
  left: initial;
  right: 12px;
}
<div class="board">
  <div class="lg-box">
    <div class="lg-rot rot-135">Just Visiting</div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 5</span>
      <span class="price">Price 5</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 6</span>
      <span class="price">Price 6</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-135-reverse">Jail</div>
  </div>



  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 4</span>
      <span class="price">Price 4</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 7</span>
      <span class="price">Price 7</span>
    </div>
  </div>
  <div class="lg-box-centered">center</div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 3</span>
      <span class="price">Price 3</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 8</span>
      <span class="price">Price 8</span>
    </div>
  </div>
  
  

  <div class="lg-box">
    <div class="lg-rot rot-45">Just Visiting</div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 2</span>
      <span class="price">Price 2</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 1</span>
      <span class="price">Price 1</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-45-reverse">Go</div>
  </div>
</div>

这是一种备选方案,使用 7 x 7 网格,并使用 writing-mode 属性。此方法与先前的方法唯一的不同之处在于它使用 writing-mode 属性来正确对齐第2行到第6行中小框内的文本。

* {
  box-sizing: border-box;
}

.board {
  display: grid;
  grid-template-columns: 120px repeat(5, 75px) 120px;
  grid-template-rows: 120px repeat(5, 75px) 120px;
  justify-content: center;
}

.lg-box {
  text-align: center;
  background: #999;
  border: 1px solid;
  overflow: hidden;
}

.sm-box {
  width: 100%;
  background: blue;
  background: red;
  height: 100%;
  position: relative;
  border: 1px solid;
  overflow: hidden;
}

.sm-box div {
  background: #fff;
  height: 85%;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-align: center;
  position: absolute;
  bottom: 0;
  padding: 5px;
}

.lg-box-centered {
  background: #fff;
  grid-row: 2 / span 5;
  grid-column: 2 / span 5;
}

.rot-180 {
  transform: rotate(180deg);
}

.lg-rot,
.lg-box-centered {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.rot-135 {
  transform: rotate(135deg);
}

.rot-45-reverse {
  transform: rotate(-45deg);
}

.rot-45 {
  transform: rotate(45deg);
}

.rot-135-reverse {
  transform: rotate(-135deg);
}

.sm-box .rot-90,
.sm-box .rot-90-reverse {
  height: 75px;
  width: 85%;
  writing-mode: vertical-rl;
  position: absolute;
  left: -10px;
}

.sm-box .rot-90-reverse {
  transform: rotate(180deg);
  right: 10px;
}
<div class="board">
  <div class="lg-box">
    <div class="lg-rot rot-135">Just Visiting</div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 11</span>
      <span class="price">Price 11</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 12</span>
      <span class="price">Price 12</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 13</span>
      <span class="price">Price 13</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 14</span>
      <span class="price">Price 14</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 15</span>
      <span class="price">Price 15</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-135-reverse">Jail</div>
  </div>



  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 10</span>
      <span class="price">Price 10</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 16</span>
      <span class="price">Price 16</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 9</span>
      <span class="price">Price 9</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 17</span>
      <span class="price">Price 17</span>
    </div>
  </div>
  <div class="lg-box-centered">center</div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 8</span>
      <span class="price">Price 8</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 18</span>
      <span class="price">Price 18</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 7</span>
      <span class="price">Price 7</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 19</span>
      <span class="price">Price 19</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 6</span>
      <span class="price">Price 6</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 20</span>
      <span class="price">Price 20</span>
    </div>
  </div>



  <div class="lg-box">
    <div class="lg-rot rot-45">Just Visiting</div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 5</span>
      <span class="price">Price 5</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 4</span>
      <span class="price">Price 4</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 3</span>
      <span class="price">Price 3</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 2</span>
      <span class="price">Price 2</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 1</span>
      <span class="price">Price 1</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-45-reverse">Go</div>
  </div>
</div>

这是一个使用第一种方法的 7 x 7 棋盘。

* {
  box-sizing: border-box;
}

.board {
  display: grid;
  grid-template-columns: 120px repeat(5, 75px) 120px;
  grid-template-rows: 120px repeat(5, 75px) 120px;
  justify-content: center;
}

.lg-box {
  text-align: center;
  background: #999;
  border: 1px solid;
  overflow: hidden;
}

.sm-box {
  width: 100%;
  background: blue;
  background: red;
  height: 100%;
  position: relative;
  border: 1px solid;
  overflow: hidden;
}

.sm-box div {
  background: #fff;
  height: 85%;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-align: center;
  position: absolute;
  bottom: 0;
  padding: 5px;
}

.lg-box-centered {
  background: #fff;
  grid-row: 2 / span 5;
  grid-column: 2 / span 5;
}

.rot-180 {
  transform: rotate(180deg);
}

.lg-rot,
.lg-box-centered {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.rot-135 {
  transform: rotate(135deg);
}

.rot-45-reverse {
  transform: rotate(-45deg);
}

.rot-45 {
  transform: rotate(45deg);
}

.rot-135-reverse {
  transform: rotate(-135deg);
}

.rot-90 {
  transform: rotate(90deg);
}

.rot-90-reverse {
  transform: rotate(-90deg);
}

.sm-box .rot-90,
.sm-box .rot-90-reverse {
  position: absolute;
  left: 12px;
  top: -12px;
  width: 75px;
  height: 100px;
}

.sm-box .rot-90-reverse {
  left: initial;
  right: 12px;
}
<div class="board">
  <div class="lg-box">
    <div class="lg-rot rot-135">Just Visiting</div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 11</span>
      <span class="price">Price 11</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 12</span>
      <span class="price">Price 12</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 13</span>
      <span class="price">Price 13</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 14</span>
      <span class="price">Price 14</span>
    </div>
  </div>
  <div class="sm-box rot-180">
    <div>
      <span class="title">Title 15</span>
      <span class="price">Price 15</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-135-reverse">Jail</div>
  </div>



  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 10</span>
      <span class="price">Price 10</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 16</span>
      <span class="price">Price 16</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 9</span>
      <span class="price">Price 9</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 17</span>
      <span class="price">Price 17</span>
    </div>
  </div>
  <div class="lg-box-centered">center</div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 8</span>
      <span class="price">Price 8</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 18</span>
      <span class="price">Price 18</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 7</span>
      <span class="price">Price 7</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 19</span>
      <span class="price">Price 19</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90">
      <span class="title">Title 6</span>
      <span class="price">Price 6</span>
    </div>
  </div>
  <div class="sm-box">
    <div class="rot-90-reverse">
      <span class="title">Title 20</span>
      <span class="price">Price 20</span>
    </div>
  </div>



  <div class="lg-box">
    <div class="lg-rot rot-45">Just Visiting</div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 5</span>
      <span class="price">Price 5</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 4</span>
      <span class="price">Price 4</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 3</span>
      <span class="price">Price 3</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 2</span>
      <span class="price">Price 2</span>
    </div>
  </div>
  <div class="sm-box">
    <div>
      <span class="title">Title 1</span>
      <span class="price">Price 1</span>
    </div>
  </div>
  <div class="lg-box">
    <div class="lg-rot rot-45-reverse">Go</div>
  </div>
</div>


5

我很喜欢你的问题,为了解决问题,我将"transform:rotate()"和"writing-mode:vertical-rl"结合起来,将角落标题旋转并保持对角线!

我只是在CSS中更改了最后2条评论下面的内容:

*{
  box-sizing: border-box;
}
#board {
   display: grid;
   /*first and last row and column are bigger than others*/
   grid-template-columns: 100px repeat(2, 70px) 100px;
   grid-template-rows: 100px repeat(2, 70px) 100px;
   
   /*a, b, c, d are 4 rows and o is center*/
   grid-template-areas:
      "c c c d"
      "b o o d"
      "b o o d"
      "b a a a";
}
#center {
   grid-area: o;
}
.row {
   display: flex;
}
.tile {
   display: flex;
   flex-direction: column;
   border: 1px solid;
   height: 100%;
   width: 100%;
}
.tile-color {
   flex: 3;
   background: red;
   border: 1px solid;
}
.tile-name {
   flex: 6;
}
.tile-price {
   flex: 3;
}

/*Flex directions are used to give the tiles correct order*/
#row-0 {
   grid-area: a;
   flex-direction: row-reverse;
}
#row-1 {
   grid-area: b;
   flex-direction: column-reverse;
}
#row-2 {
   grid-area: c;
   flex-direction: row;
}
#row-3 {
   grid-area: d;
   flex-direction: column;
}

/*To make the corner tiles bigger and square*/
.row > .tile:nth-child(1){
  flex: 0 0 100px;
}

/*Turn tiles*/
#row-1 .tile{
 writing-mode: vertical-rl;
}
#row-2 .tile{
 transform: rotate(180deg);
}
#row-3 .tile{
 writing-mode: vertical-rl;
 transform: rotate(180deg);
}

/*Turn corners*/
.row > .tile:first-child{
 text-align: center;
}
#row-0 > .tile:first-child .tile-name{
 transform: rotate(-45deg) translateY(38px);
}
#row-1 > .tile:first-child .tile-name{
 transform: rotate(-45deg) translateX(-38px);
}
#row-2 > .tile:first-child .tile-name{
 transform: rotate(-45deg) translateY(38px);
}
#row-3 > .tile:first-child .tile-name{
 transform: rotate(-45deg) translateX(-38px);
}
<div id="board">
   <div id="center"></div>
   
   <!--Row 1-->
   <div class="row" id="row-0">
      <div class="tile">
         <div class="tile-name">Go</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 1</div>
         <div class="tile-price">Price 1</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 2</div>
         <div class="tile-price">Price 2</div>
      </div>
   </div>
   
   <!--Row 2-->
   <div class="row" id="row-1">
      <div class="tile">
         <div class="tile-name">Just visiting</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 3</div>
         <div class="tile-price">Price 3</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 4</div>
         <div class="tile-price">Price 4</div>
      </div>
   </div>
   
   <!--Row 3-->
   <div class="row" id="row-2">
      <div class="tile">
         <div class="tile-name">Free Parking</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 4</div>
         <div class="tile-price">Price 4</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 5</div>
         <div class="tile-price">Price 5</div>
      </div>
   </div>
   
   <!--Row 4-->
   <div class="row" id="row-3">
      <div class="tile">
         <div class="tile-name">Jail</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 6</div>
         <div class="tile-price">Price 6</div>
      </div>
      <div class="tile">
         <div class="tile-color"></div>
         <div class="tile-name">Tile 7</div>
         <div class="tile-price">Price 7</div>
      </div>
   </div>
</div>

我注意到 "writing-mode" 没有变成另一个水平方向,所以我把它调整为相同的水平方向并旋转了180º,这样它就保持在完全相同的位置。
希望我能帮到你!

很好,看起来是一个干净的解决方案。 - Christian Vincenzo Traina

5
由于此问题已标记为#javascript,目前没有使用JavaScript的答案,所以我决定尝试回答它。
我假设你的目标是制作一个交互式棋盘游戏,因此无法避免使用JS。
如果您的目标仅是渲染这样的网格,我也尝试几乎完全使用CSS来实现它 - 这意味着只有一堆没有任何类或ID的div,然后基本上通过:nth-child() 伪类设置GridLayout。

const TileType = {
  TECHNOLOGY: 'technology',
  CHANCE: 'chance',
  START: 'start',
  STACKOVERFLOW: 'stackoverflow',
  GO_TO_STACKOVERFLOW: 'goToStackoverflow',
  DEBUGGING: 'debugging',
}

const TechnologyType = {
    BACKEND: 'backend',
    FRONTEND: 'frontend',
    MOBILE: 'mobile',
    NATIVE: 'native',
}

const ChanceType = {
    RED: 'red',
    BLUE: 'blue',
}

class Tile {
  constructor(title, type, value = null) {
    this.title = title;
    this.type = type;
    this.value = value;
  }

  toHTML() {
     const card = document.createElement('div');
     if ( this.title) {
      const title = document.createElement('p');
      title.classList.add('title');
      title.innerText = this.title;
      card.appendChild(title);
      }
     
     card.addEventListener('click', () => console.log(this));
     return card;

  }

}

// Still no static props in JS
const technologyColorMap = {
[TechnologyType.BACKEND]:  '#2ab7ca',
[TechnologyType.FRONTEND]:  '#fed766',
[TechnologyType.MOBILE]:  '#7bc043',
[TechnologyType.NATIVE]:  '#63ace5', 
};
class TechnologyTile extends Tile {
  constructor(title, subType, value = null) {
    super(title, TileType.TECHNOLOGY, value);
    this.technologyType = subType;
  }

   toHTML() {
     const card = super.toHTML();
      card.classList.add('technology');
     const colorBox = document.createElement('div');
     colorBox.classList.add('colorBox');
       colorBox.style.backgroundColor = technologyColorMap[this.technologyType];
     card.prepend(colorBox);
     return card;
  }

}

const chanceTypeColorMap  = {
[ChanceType.RED]:  '#fe4a49',
[ChanceType.BLUE]:  '#005b96',
};

class ChanceTile extends Tile {
  constructor(title, subType, value = null) {
    super(title, TileType.CHANCE, value);
    this.chanceType = subType;
  }

   toHTML() {
     const card = super.toHTML();
     card.classList.add('chance');
     //card.appendChild(this.getIcon());
     return card;
  }

  getIcon() {
    const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.classList.add('chance');
     svg.setAttributeNS(null,"width","180");
    svg.setAttributeNS(null,"height","180");
    const path  = document.createElementNS('http://www.w3.org/2000/svg',"path");
    path.setAttributeNS(null,"d","M60,67c0-13 1-19 8-26c7-9 18-10 28-8c10,2 22,12 22,26c0,14-11,19-15,22c-7,2-10,6-11,11v20m0,12v16");
    path.setAttributeNS(null,"fill", "none");
    path.setAttributeNS(null,"stroke", chanceTypeColorMap[this.chanceType]);
     path.setAttributeNS(null,"stroke-width","6");
     svg.appendChild(path);

    return svg;

  }
}

const tiles = [
  new Tile('Start', TileType.START),
  new TechnologyTile('Java Spring', TechnologyType.BACKEND, 10),
  new ChanceTile('Chance', ChanceType.RED),
  new TechnologyTile('NodeJS', TechnologyType.BACKEND, 15),
  new Tile('StackOverflow', TileType.STACKOVERFLOW),
  new TechnologyTile('Angular', TechnologyType.FRONTEND, 20),
  new TechnologyTile('iOS', TechnologyType.MOBILE, 30),
  new TechnologyTile('React', TechnologyType.FRONTEND, 25),
  new ChanceTile('Chance', ChanceType.BLUE),
  new ChanceTile('Chance', ChanceType.RED),
  new TechnologyTile('Android', TechnologyType.MOBILE, 35),
  new Tile('Go To StackOverlfow', TileType.GO_TO_STACKOVERFLOW),
  new TechnologyTile('Swing', TechnologyType.NATIVE, 40),
  new ChanceTile('Chance', ChanceType.BLUE),
  new TechnologyTile('Qt', TechnologyType.NATIVE, 45), 
  new Tile('Free Debugging', TileType.DEBUGGING),

]
class Board {
  constructor(tiles, root) {
    this.tiles = tiles;
    this.root = root;
  }
  
  render() {
    this.root.innerHTML = '';
    for (let i = 0; i < this.tiles.length; ++i) {
      const tile = this.tiles[i].toHTML();
      if (i == 0 || i == this.tiles.length - 5) {
        tile.classList.add('big-square-left');
      } else if ( i == 4 || i == this.tiles.length - 1) {
        tile.classList.add('big-square-right');
      }

     if (i < 5) {
       tile.classList.add('top-row');

    } else if (i < this.tiles.length - 5) {
         tile.classList.add(i % 2 == 0 ? 'right' : 'left');
    } else {
       tile.classList.add('bottom-row');
    }
      
      this.root.appendChild(tile);
   }
  }
}

const board = new Board(tiles, document.getElementById('root'));
board.render();
#root {
    width: 80vw;
    height: 80vw;
    display: grid;
    grid-template-rows: 2fr repeat(3, 1fr) 2fr;
    grid-template-columns: repeat(7, 1fr);
}

#root > div {
  border: 1px solid black;
  position:relative;
}

#root div:nth-child(2n + 6)  {
  grid-column: 1 / span 2;
}

#root  div:nth-child(2n + 7)  {
  grid-column: 6 / span 2;
}

#root  div:nth-child(2n + 7)  {
  grid-column: 6 / span 2;
}

/*#root  div:nth-child(n + 12)  {*/
#root  div.bottom-row  {
  grid-column: auto;
}

#root div.big-square-left  {
 grid-column: 1 / span 2;
}

#root div.big-square-right  {
    grid-column: 6 / span 2;
}

#root div p.title  {
 text-align: center;
 position:relative;
}

#root div.top-row p.title  {
 transform: rotate(180deg);
 top: 10%;
}

#root div.left p.title  {
 transform: rotate(90deg);
 top: 10%;
}

#root div.left.technology p.title  {
 top: -85%;
}

#root div.right p.title  {
 transform: rotate(270deg);
}

#root div.right.technology p.title  {
 top: -85%;
}


#root div.right p.title  {
 transform: rotate(270deg);
}

#root div.big-square-right.top-row p.title  {
 transform: rotate(225deg);
 top: 25%
}

#root div.big-square-right.bottom-row p.title  {
 transform: rotate(315deg);
 top: 25%
}

#root div.big-square-left.bottom-row p.title  {
 transform: rotate(45deg);
 top: 25%
}

div.colorBox {
    position: relative;
}

#root > div.right > div.colorBox {
    width: 20%;
    height: 100%;
}

#root > div.left > div.colorBox {
    width: 20%;
    height: 100%;
    right: -80%;
}

#root > div.top-row > div.colorBox {
    height: 20%;
    top: 80%;
}


#root > div.bottom-row > div.colorBox {
    height: 20%;
   
}

svg.chance {
  position: absolute;

}

#root > div.bottom-row > svg.chance
{
    transform: scale(0.75);
    left: -86%;
    top: -5%;
}

#root > div.top-row > svg.chance
{
    transform: scale(-0.75);
    left: -86%;
    top: -36%;
}

#root > div.left > svg.chance
{
    transform: scale(0.75) rotate(90deg);
    left: -36%;
    top: -88%;
}

#root > div.right > svg.chance
{
   transform: scale(0.75) rotate(270deg);
    left: -5%;
    top: -89%;
}

#root > div.chance.top-row > p.title
{
   top: 68%;
}

#root > div.chance.right > p.title
{
   left: -38%;
   top: 10%;
}

#root > div.chance.left > p.title
{
   right: -40%;
}

#root > div.chance.bottom-row > p.title
{
   top: -8%;
}
<div id="root"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接