将 <SVG> 宽度缩放到高度(parent 的 100%)

Scale <SVG> width to height (100% of parent)

我正在尝试使用 Bootstrap 5.0 流体容器(一个 header 和一个可以调整以便永远不需要垂直滚动的容器来创建网页模板。在这个容器内部,我想要在 svg 中渲染 D3 地图,该地图将动态缩放到其 parent 容器高度的 100%(无论其 parent 容器当前的高度是多少),并相应地调整其宽度以保持纵横比。

我发现了一些样式可以让我的容器始终缩放到剩余的视口高度而无需垂直滚动,包括在下面,但我不知道如何实例化我的 svg 以仅占用这个垂直 space, 水平缩放和调整大小。

let path = d3.geoPath()

let svg = d3.select("#map-svg")
  .attr("preserveAspectRatio", "xMidYMid meet")
  .attr("viewBox", "0 0 960 600")

d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/counties-albers-10m.json").then(
  function(us) {

    svg.selectAll("path.county")
      .data(topojson.feature(us, us.objects.counties).features)
      .join("path")
      .attr("id", function(d) {
        return d["id"]
      })
      .attr("class", "county")
      .attr("fill", "#E7E7E8")
      .attr("stroke", "#FFFFFF")
      .attr("stroke-linejoin", "round")
      .attr("stroke-width", "0.3")
      .attr("d", path)
  }
)
* {
  margin: 0;
  padding: 0;
  border: 0;
}

html,
body {
  height: 100%;
}

#wrapper-div {
  height: 100%;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: column;
  flex-direction: column;
  outline: 1px solid red;
}

#header-div {
  background-color: lightblue;
  -webkit-flex: 0 0 auto;
  flex: 0 0 auto;
}

#map-div {
  background-color: lightgreen;
  -webkit-flex: 1 1 auto;
  flex: 1 1 auto;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
}

#map-svg {
  background-color: lightpink;
}
<body>
  <div class="container-fluid" id="wrapper-div">
    <div class="container-fluid" id="header-div">
      HEADER TEXT
    </div>
    <div class="container-fluid" id="map-div">
      <svg id="map-svg"></svg>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script src="https://unpkg.com/topojson@3"></script>
  <script src="./index.js"></script>
</body>

当您先将容器的 box-sizing 属性 设置为 border-box 时,可以更轻松地调整容器中的空间,以确保您的容器保持相同的高度和宽度。调整他们的 marginpadding。要使其水平缩放,只需将 width: 100%; 添加到您的 #map-svg。为了使其保持在 100 视口上而不会溢出,我所做的是将 #wrapper-div 设置为具有 100vhheight,使 header 绝对并设置 [ #map-svg 的 =20=] 与 #wrapper-div 的高度相同,也添加了一些填充以避免 header 和地图重叠。检查下面的代码片段以供参考:

let path = d3.geoPath()

let svg = d3.select("#map-svg")
  .attr("preserveAspectRatio", "xMidYMid meet")
  .attr("viewBox", "0 0 960 600")

d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/counties-albers-10m.json").then(
  function(us) {

    svg.selectAll("path.county")
      .data(topojson.feature(us, us.objects.counties).features)
      .join("path")
      .attr("id", function(d) {
        return d["id"]
      })
      .attr("class", "county")
      .attr("fill", "#E7E7E8")
      .attr("stroke", "#FFFFFF")
      .attr("stroke-linejoin", "round")
      .attr("stroke-width", "0.3")
      .attr("d", path)
  }
)
* {
  margin: 0;
  padding: 0;
  border: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

#wrapper-div {
  height: 100vh;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: column;
  flex-direction: column;
  outline: 1px solid red;
}

#header-div {
  background-color: lightblue;
  -webkit-flex: 0 0 auto;
  flex: 0 0 auto;
  position: absolute;
  width: 100%;
}

#map-div {
  background-color: lightgreen;
  -webkit-flex: 1 1 auto;
  flex: 1 1 auto;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
}

#map-svg {
  background-color: lightpink;
  padding: 1.5rem 0 .5rem;
  width: 100%;
  height: 100vh;
}
<body>
  <div class="container-fluid" id="wrapper-div">
    <div class="container-fluid" id="header-div">
      HEADER TEXT
    </div>
    <div class="container-fluid" id="map-div">
      <svg id="map-svg"></svg>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <script src="https://unpkg.com/topojson@3"></script>
  <script src="./index.js"></script>
</body>