dc.js 响应式地图和缩放功能(鼠标滚轮)

dc.js responsive map and zoom function (mousewheel)

我已经 fork 示例 dc.js(版本 4)映射文件是这个 JsFiddle。我想要的是地图响应 Bootstrap 容器。因此,如果屏幕尺寸发生变化,地图将正确显示。 SVG 通过将宽度和高度设置为 null 以及 CSS 格式将宽度和高度设置为 100% 来响应。但是我看到底层 <g> (layer0) 元素没有响应。因此,我尝试在投影中添加一个比例元素。但不幸的是,我不知道如何使它像我对 SVG 元素所做的那样灵活。

此外,我希望有放大的可能性。希望有人能帮助我。

<div class="container">
  <div class="row">
    <div class="col">
      <div id="world-map" class="responsive"></div>
    </div>
  </div>
</div>

<pre id="data">country  total
      Belgium   2   
      Germany   3   
      France    4   
</pre>
function world(data) {
  var xf = crossfilter(data);
  var country = xf.dimension(function(d) {
    return d.country;
  });
  var countryGroup = country.group().reduceSum(d => +d.total);

  var worldMap = new dc.GeoChoroplethChart("#world-map");
  d3.json("https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json").then(function(worldJson) {
    worldMap
      .width(null)
      .height(null)
      .dimension(country)
      .group(countryGroup)
      .colors(d3.scaleQuantize().range(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"]))
      .colorDomain([0, 200])
      .colorCalculator(function(d) {
      return d ? worldMap.colors()(d) : '#ccc';
    })
      .overlayGeoJson(worldJson.features, "state", function(d) {
      return d.properties.name;
    })
      .projection(d3.geoEquirectangular()
                  .scale(100)
                  .translate([800 / 2, 400 / 2])
                 )
      .valueAccessor(function(kv) {
      //console.log(kv);
      return kv.value;
    })
      .title(function(d) {
      return d.key + "\nTotal: " + (d.value ? d.value : 0);
    });

    dc.renderAll();

  });
}

const data = d3.tsvParse(d3.select('pre#data').text());

world(data);
.row {
  background: #f8f9fa;
  margin-top: 20px;
}

.col {
  border: solid 1px #6c757d;
  padding: 10px;
}

pre#data {
  display: none;
}

.responsive {
  width: 100%;
  height: 100%;
}

连接父 <g>d3-zoom to change the transform 以响应缩放事件真的很容易。

首先,取出投影初始化,因为稍后我们需要初始值:

  const scale0 = 100, x0 = 800 / 2, y0 = 400 / 2, 
    projection = d3.geoEquirectangular()
      .scale(scale0)
      .translate([x0, y0])
  worldMap
    .projection(projection)

然后在图表呈现后添加缩放处理程序:

  worldMap.on('postRender', chart => {
    const zoom = d3.zoom();
    zoom.on('zoom', () => {
      const {k, x, y} = d3.event.transform;
      chart.select('g.layer0')
        .attr('transform', `translate(${x},${y}) scale(${k})`)
    })
    chart.svg().call(zoom);
  });

每次我们收到缩放事件时,我们都会从事件中提取比例、x 和 y 偏移量,并将它们应用到看起来像

的变换
translate(-350.6778787924404,-173.42665430196223) scale(1.9132163161837539)

第一次尝试时,我应用了新的投影并重新绘制了图表。这有效,但存在性能问题。改变变换是要走的路!

Fork of your fiddle,具有平移和缩放功能。