d c. js адаптивная карта и функция масштабирования (колесико мыши) - PullRequest
1 голос
/ 30 марта 2020

Я разобрал пример файла карты d c. js (версия 4): JsFiddle . Я хочу, чтобы карта реагировала на контейнер Bootstrap. Так что, если размер экрана меняется, карта отображается правильно. SVG реагирует, устанавливая ширину и высоту равными нулю, и формат CSS, чтобы установить ширину и высоту равными 100%. Однако я вижу, что базовый элемент <g> (layer0) не отвечает. Поэтому я попытался добавить масштабный элемент в проекцию. Но, к сожалению, я не знаю, как сделать это гибким, как я сделал с элементом SVG.

Кроме того, я хотел бы иметь возможность увеличения. Надеюсь, кто-то может помочь мне с этим.

<code><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   
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%;
}

1 Ответ

1 голос
/ 10 апреля 2020

Подключить d3-zoom очень просто, чтобы изменить преобразование родительского элемента <g> в ответ на события масштабирования.

Сначала вытащите инициализация проекции, потому что нам понадобятся начальные значения позже:

  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)

. С первой попытки я применил новую проекцию и перерисовал диаграмму. Это работало, но у него были проблемы с производительностью. Изменение преобразования - это путь к go!

Вилка вашей скрипки , с панорамированием и масштабированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...