如何给 canvas max space 并在其上放置左(可滚动)和右 "menu" div?

How to give a canvas max space and place left (scrollable) and right "menu" divs on it?

我已经为我的问题准备了一个完整而简单的jsFiddle

我的 word game 目前使用 HTML table 来布置 HTML canvas 和 jQuery UI 按钮。

我想摆脱 HTML table 而是使用 HTML div 元素,我已经在 red/yellow屏幕截图中带箭头的框:

我想要 div 元素的以下结构:

- fullDiv (should occupy 100% width and height of browser window)
-- hintDiv (100% width, min height, visible on top)
-- mainDiv (100% width, max height)
--- gameDiv (100% width, max height)
---- myCanvas (100% width, max height)
-- leftDiv (min width, same height as mainDiv, scrollable) <- relative position
-- rightDiv (min width, same height as mainDiv) <- relative position
-- totalDiv (100% width, min height, visible on bottom)

想法是尽可能多地给 myCanvas space 并将 leftDivrightDiv 作为其两侧的“菜单”。 leftDiv 将是一个带有可滚动游戏列表的导航菜单,并且具有与 myCanvasrightDiv.

相同的最大可能高度

所以我尝试了下面的代码-

$(function () {
  $(':button').button();
  $('#fullCheck').checkboxradio();

  var gamesMenu = $('#gamesMenu').menu({
    items: '> :not(.ui-widget-header)'
  });

  for (var game = 1; game <= 50; game++) {
    gamesMenu.append('<LI VALUE="' + game + '">GAME ' + game + '</LI>');
  }
    gamesMenu.menu('refresh');
});
body {
  margin: 0;
  padding: 0;
}

#fullDiv {
  width: 100%;
  height: 100vh;
  background: #FFF;
}

#hintDiv,
#totalDiv {
  text-align: center;
}

#mainDiv,
#gameDiv {
  width: 100%;
  height: 100%;
}

#myCanvas {
  width: 100%;
  height: 100%;
  border: 4px red dotted;
  background: #CCF;
}

#leftDiv {
  position: relative;
  left: 0;
  top: 0;
  /* bottom: 0; */
  text-align: center;
  background: #FCC;
}

#rightDiv {
  position: relative;
  right: 0;
  top: 0;
  /* bottom: 0; */
  text-align: center;
  background: #CFC;
}

#gamesMenu {
  overflow-y: scroll;
}

#hintDiv {
  font-style: italic;
}
<div id="fullDiv">
  <div id="hintDiv">Hint</div>
  <div id="mainDiv">
    <div id="gameDiv">
      <canvas id="myCanvas"></canvas>
    </div>

    <div id="leftDiv">
      <button id="newBtn">New game</button>
      <ul id="gamesMenu"></ul>
    </div>

    <div id="rightDiv">
      <input id="fullCheck" type="checkbox">
      <label for="fullCheck">Full screen</label><br>
      <button id="recallBtn">Recall</button><br>
      <button id="shuffleBtn">Shuffle</button><br>
      <button id="swapBtn">Swap</button><br>
      <button id="skipBtn">Skip</button><br>
      <button id="resignBtn">Resign</button><br>
      <button id="pileBtn">Pile</button><br>
      <button id="movesBtn">Moves history</button><br>
      <button id="shareBtn">Share</button><br>
      <button id="playBtn">Play</button>
    </div>
  </div>
  <div id="totalDiv">Total</div>
</div>

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

但是,我的屏幕现在完全乱了:

更新:

这是 Derek 的解决方案(谢谢!)

$(function () {
  $(':button').button();
  $('#fullCheck').checkboxradio();

  var gamesMenu = $('#gamesMenu').menu({
    items: '> :not(.ui-widget-header)'
  });

  for (var game = 1; game <= 50; game++) {
    gamesMenu.append('<LI VALUE="' + game + '">GAME ' + game + '</LI>');
  }

    gamesMenu.menu('refresh');
});
body {
  margin: 0;
  padding: 0;
}

#fullDiv {
  width: 100%;
  height: 100vh;
  background: #FFF;
  display: flex;
  flex-direction: column;
}

#hintDiv,
#totalDiv {
  text-align: center;
  background: yellow;
}

#leftDiv {
  text-align: center;
  background: #FCC;
  display: flex;
  flex-direction: column;
}

#gamesMenu {
  overflow-y: auto;
}

#mainDiv {
  flex-grow: 1;
  display: flex;
  justify-content: space-between;
  overflow: hidden;
}

#gameDiv {
  flex-grow: 1;
}

#myCanvas {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border: 4px red dotted;
  background: #CCF;
}

#rightDiv {
  text-align: center;
  background: #CFC;
  overflow-y: auto;
}

#hintDiv {
  font-style: italic;
}
<div id="fullDiv">
  <div id="hintDiv">Hint</div>
  <div id="mainDiv">
    <div id="leftDiv">
      <button id="newBtn">New game</button>
      <ul id="gamesMenu"></ul>
    </div>

    <div id="gameDiv">
      <canvas id="myCanvas"></canvas>
    </div>

    <div id="rightDiv">
      <input id="fullCheck" type="checkbox">
      <label for="fullCheck">Full screen</label><br>
      <button id="recallBtn">Recall</button><br>
      <button id="shuffleBtn">Shuffle</button><br>
      <button id="swapBtn">Swap</button><br>
      <button id="skipBtn">Skip</button><br>
      <button id="resignBtn">Resign</button><br>
      <button id="pileBtn">Pile</button><br>
      <button id="movesBtn">Moves history</button><br>
      <button id="shareBtn">Share</button><br>
      <button id="playBtn">Play</button>
    </div>
  </div>
  <div id="totalDiv">Total</div>
</div>

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

更新 2:

出于某种原因 jQuery UI 菜单不可悬停(尽管在 official demo 中是)...

目前我的解决方法是(至少可以看到所选项目):

li.selected {
  font-weight: bold;
  background-color: yellow;
}

var gamesMenu = $('#gamesMenu').menu({
  items: '> :not(.ui-widget-header)',
  select: function(ev, ui) {
    ui.item.addClass('selected').siblings().removeClass('selected');
  }
});

这可以使用 flex 布局来完成。

  • 使 #fullDivflex-direction: column 一起使用 flex 布局,以便它可以在列上对齐。
  • flex: 1 1 auto设置为#mainDiv,这样就可以取space,除了#fullDiv上的#hintDiv#totalDiv
  • 也将 #mainDiv 设置为 flex 布局 justify-content: space-between。你会在 this guide.
  • 上知道的
  • 根据该指南,交换 #leftDiv#gameDiv
  • #gameDiv 上,我已将 canvas 宽度和高度更新为 calc(100% - 8px),因为边框大小将添加到实际 canvas 大小。所以现在,canvas 边框宽度是 4px 所以 canvas 宽度将是 (100% - 8px) + 8px(border size) = 100%.

/*$(function () {
  $(':button').button();
  $('#fullCheck').checkboxradio();

  var gamesMenu = $('#gamesMenu').menu({
    items: '> :not(.ui-widget-header)'
  });

  for (var game = 1; game <= 50; game++) {
    gamesMenu.append('<LI VALUE="' + game + '">GAME ' + game + '</LI>');
  }
});*/
body {
  font-family: Arial, Helvetica, sans-serif;
  margin: 0;
  padding: 0;
}

#fullDiv {
  width: 100%;
  height: 100vh;
  background: #FFF;
}

#hintDiv,
#totalDiv {
  text-align: center;
}

#myCanvas {
  width: calc(100% - 8px);
  height: calc(100% - 8px);
  border: 4px red dotted;
  background: #CCF;
}

#leftDiv {
  text-align: center;
  background: #FCC;
}

#rightDiv {
  text-align: center;
  background: #CFC;
}

#gamesMenu {
  overflow-y: scroll;
}

#publishBtn {
  max-width: 200px;
}

#timer1,
#timer2 {
  color: red;
}

#hintDiv {
  font-style: italic;
}


/*** Additional Codes ***/
#fullDiv {
  display: flex;
  flex-direction: column;
}

#mainDiv {
  flex: 1 1 auto;
  display: flex;
  justify-content: space-between;
}

#gameDiv {
  flex: 1 1 auto;
}
<div id="fullDiv">
  <div id="hintDiv">Hint</div>
  <div id="mainDiv">
    <div id="leftDiv">
      <button id="newBtn">New game</button>
      <ul id="gamesMenu"></ul>
    </div>
    
    <div id="gameDiv">
      <canvas id="myCanvas"></canvas>
    </div>

    <div id="rightDiv">
      <input id="fullCheck" type="checkbox">
      <label for="fullCheck">Full screen</label><br>
      <button id="recallBtn">Recall</button><br>
      <button id="shuffleBtn">Shuffle</button><br>
      <button id="swapBtn">Swap</button><br>
      <button id="skipBtn">Skip</button><br>
      <button id="resignBtn">Resign</button><br>
      <button id="pileBtn">Pile</button><br>
      <button id="movesBtn">Moves history</button><br>
      <button id="shareBtn">Share</button><br>
      <button id="playBtn">Play</button>
    </div>
  </div>
  <div id="totalDiv">Total</div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>