Проблема с переходами d3.js - неправильная морфинг полигона с использованием GeoJson - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь создать листовую карту с наложением D3. В оверлее я хотел бы представить некоторые формы с возможностью динамического переключения между ними - плавного перехода от одного к другому (морфинг). Мне удалось настроить некоторый основной рабочий код, который более или менее выполняет то, что мне нужно, но есть одна проблема.

Когда я нажимаю кнопку, чтобы изменить форму, вместо плавного перехода, окончательная форма «разворачивается», безмного уважения к предыдущему. Что я делаю неправильно? Я видел в некоторых местах в Интернете, что .transition () должен делать эту работу, но не в моем случае. Нужно ли использовать какую-то интерполяцию? Или, может быть, подготовить данные? Буду признателен за любую помощь!

Вот мой код, я также включаю ссылку на демонстрацию: (Там есть карта и две кнопки для изменения формы)

https://jsfiddle.net/xianoss/dLk65pyu/

JS:

var figure1 = {
  "features": [{
    "type": "Feature",
    "properties": {},
    "geometry": {
      "coordinates": [
        [
          [
            -72.256697,
            1.150426
          ],
          [
            -74.579093,
            -7.698964
          ],
          [
            -67.075969,
            -21.93404
          ],
          [
            -68.088295,
            -34.291664
          ],
          [
            -55.285345,
            -31.492019
          ],
          [
            -44.923888,
            -19.0337
          ],
          [
            -46.591249,
            -5.569695
          ],
          [
            -59.394199,
            1.983787
          ],
          [
            -65.051316,
            2.578799
          ],
          [
            -72.256697,
            1.150426
          ]
        ]
      ],
      "type": "Polygon"
    },
    "id": "c9cd572980c7663fc538a70f2092af60"
  }],
  "type": "FeatureCollection"
}

var figure2 = {
  "features": [{
    "type": "Feature",
    "properties": {},
    "geometry": {
      "coordinates": [
        [
          [
            -62.921997,
            -10.077123
          ],
          [
            -62.160825,
            -24.409954
          ],
          [
            -51.208418,
            -18.349548
          ],
          [
            -54.379964,
            -7.653952
          ],
          [
            -62.921997,
            -10.077123
          ]
        ]
      ],
      "type": "Polygon"
    },
    "id": "9db95177c15f320f2293f918b58ff94b"
  }],
  "type": "FeatureCollection"
}


var map = L.map('mapid').setView([-13.294, -60.624], 4);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
  maxZoom: 18,
  id: 'mapbox.streets',
}).addTo(map);

var svg = d3.select(map.getPanes().overlayPane).append("svg");
var g = svg.append("g").attr("class", "leaflet-zoom-hide");

draw(figure1, figure2)

function draw(collection1, collection2) {

  collection = collection1

  var transform = d3.geo.transform({
    point: projectPoint
  })
  var geoGenerator = d3.geo.path().projection(transform);

  var feature = g.selectAll("path")
    .data(collection.features)
    .enter().append("path")
    .attr("class", "green");

  map.on("viewreset", reset);
  reset();

  $("#btn1").click(function() {
    update(collection1, "green")
  });

  $("#btn2").click(function() {
    update(collection2, "red")
  });

  function update(data, color) {
    var t = d3.transition()
      .duration(750);

    var sel = g.selectAll("path")
      .data(data.features)
      .attr("class", color)

    sel.enter()
      .append("path")

    sel
      .transition().duration(1000)
      .attr("d", geoGenerator)
  }

  function reset() {

    var bounds = geoGenerator.bounds(collection),
      topLeft = bounds[0],
      bottomRight = bounds[1];

    svg.attr("width", bottomRight[0] - topLeft[0])
      .attr("height", bottomRight[1] - topLeft[1])
      .style("left", topLeft[0] + "px")
      .style("top", topLeft[1] + "px");

    g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");

    feature.attr("d", geoGenerator);
  }

  function projectPoint(x, y) {
    var point = map.latLngToLayerPoint(new L.LatLng(y, x));
    this.stream.point(point.x, point.y);
  }
}

HTML:

<!doctype html>

<html lang="en">

  <head>
    <meta charset="utf-8">

    <link rel="stylesheet" href="css/styles.css?v=1.0">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
  </head>

  <body>
    <div>
      <button type="button" id="btn1">One</button>
      <button type=" button" id="btn2">Two</button>
    </div>

    <div id="mapid"></div>

    <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script src="https://d3js.org/queue.v1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.5/leaflet.js"></script>

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  </body>

</html>

CSS:

#mapid {
  height: 500px;
}

svg {
  position: relative;
}

path {
  fill-opacity: .7;
  stroke: rgb(90, 89, 89);
  stroke-width: 3.5px;
}

.red {
  fill: rgb(255, 82, 14);
}

.green {
  fill: rgb(16, 236, 64);
}

1 Ответ

0 голосов
/ 30 сентября 2019

Я понял, проблема в данных - похоже, d3 по умолчанию не может обрабатывать такие фигуры. Когда я выровнял две фигуры, чтобы они были более похожими, и упорядочил точки, все работает нормально. Я думаю, мне нужно использовать более продвинутую функцию морфинга, такую ​​как flubber https://bestofjs.org/projects/flubber

. Она работает нормально с этими двумя цифрами:

{
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "coordinates": [
          [
            [
              -63.334278,
              -8.430061
            ],
            [
              -64.029526,
              -16.512253
            ],
            [
              -44.272875,
              -19.923701
            ],
            [
              -48.038806,
              -7.05227
            ],
            [
              -63.334278,
              -8.430061
            ]
          ]
        ],
        "type": "Polygon"
      },
      "id": "5142b4060fc932fe302b7ae7258dc916"
    }
  ],
  "type": "FeatureCollection"
}


{
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "coordinates": [
          [
            [
              -62.921997,
              -10.077123
            ],
            [
              -62.160825,
              -24.409954
            ],
            [
              -51.208418,
              -18.349548
            ],
            [
              -54.379964,
              -7.653952
            ],
            [
              -62.921997,
              -10.077123
            ]
          ]
        ],
        "type": "Polygon"
      },
      "id": "9db95177c15f320f2293f918b58ff94b"
    }
  ],
  "type": "FeatureCollection"
}

...