Как изменить интерполяцию для поведения масштабирования в d3.JS



Я использую d3.js V 4.0 для обеспечения масштабирования и панорамирования в SVG. Я использую кнопку сброса, чтобы вернуться в центр изображения. Он работает, но использует стандартный d3.interpolateZoom, так что изображение масштабируется во время перехода. Я просто хочу, чтобы масштабирование выполняло стандартную интерполяцию,но я не могу понять, как изменить интерполятор для поведения масштабирования.
Вот сокращенная версия кода:






var map = document.querySelector('#map');
var everything = d3.select('#everything');
var zoomBehavior = d3.zoom();
zoomBehavior.scaleExtent([0.5, 10])
.on('zoom', zoomed);
d3.select(map).call(zoomBehavior);

function zoomed() {
everything.attr('transform', d3.event.transform);
}

function reset() {
d3.select(this.map)
.transition()
.duration(1000)
.call(zoomBehavior.transform, d3.zoomIdentity);
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.1.0/d3.min.js"></script>
<svg id="map" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g id="everything">
<circle r="5" cx="50" cy="15"></circle>
</g>
</svg>
<button onclick="reset()">reset</button>





К сожалению это не показывает поведение, которое я вижу. (В моей реальной версии масштаб k интерполируется через 0 с помощью Van Wijk smooth zooming ), но вопрос остается в силе. Если бы я изменил интерполятор для такого поведения масштабирования, как и где бы я это сделал? Я пытался дозвониться до зоомбехавиора.интерполировать(d3.интерполировать), что, по-видимому, предполагает документация, но я получаю ошибку, указывающую, что zoomBehavior.интерполяция-это не функция.

425   2  

2 ответов:

Трудно ответить на этот вопрос, не видя поведения, которого вы пытаетесь избежать. Приведенный выше пример кода работает должным образом. Тем не менее, вот пример полного контроля интерполяторов и, следовательно, перехода. Здесь я увеличиваю круг обратно до scale: 1, но x и y в нижнем правом углу svg:

<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.js"></script>
</head>

<body>
  <svg id="map" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <g id="everything">
      <circle r="5" cx="50" cy="15"></circle>
    </g>
  </svg>
  <button onclick="reset()">reset</button>
  <script>
    var map = d3.select('#map'),
        everything = d3.select('#everything');

    var zoomBehavior = d3.zoom();
    zoomBehavior.scaleExtent([0.5, 10])
      .on('zoom', zoomed);

    map.call(zoomBehavior);

    function zoomed() {
      everything.attr('transform', d3.event.transform);
    }

    function reset() {
      d3.select(this.map)
        .transition()
        .duration(1000)
        .tween("custom", function() {
          var curZoom = d3.zoomTransform(map.node()),
            kInter = d3.interpolate(curZoom.k, 1),
            xInter = d3.interpolate(curZoom.x, 240),
            yInter = d3.interpolate(curZoom.y, 99);
          return function(t) {
            var ts = d3.zoomIdentity
              .translate(xInter(t), yInter(t))
              .scale(kInter(t));
            map.call(zoomBehavior.transform, ts);
          };
        });
    }
  </script>
</body>

</html>

У нас была та же проблема, и мы решили ее с помощью метода interpolate. Применительно к вашему коду это будет выглядеть следующим образом:

zoomBehavior.interpolate(d3.interpolate).scaleExtent([0.5, 10])
  .on('zoom', zoomed);

Согласно http://devdocs.io/d3~4/d3-zoom#zoom_interpolate, d3.interpolate применяется "прямая интерполяция между двумя видами", в то время как по умолчанию используется d3.interpolateZoom, который применяет "плавное масштабирование", что ни один из нас не хочет.

Comments

    Ничего не найдено.