简体   繁体   English

如何使d3并发转换工作?

[英]How to make d3 concurrent transitions work?

I've started doing this as a side project to learn D3. 我已经开始这样做作为学习D3的侧面项目。 So please go easy on me; 所以请放轻松我;

Goal: Making an interactive airports map. 目标:制作互动机场地图。 When mouse is over a city planes will take off from that city's airport and land on to the destination. 当鼠标飞过城市时,飞机将从该城市的机场起飞并降落到目的地。

Steps I've followed; 我遵循的步骤;

  1. I've downloaded country and airports data as geojson and defined base map on D3. 我已经将国家和机场数据下载为geojson并在D3上定义了基本地图。

底图

  1. I've write necessary functions to derive spatial information to use in transitions. 我已经编写了必要的函数来导出在转换中使用的空间信息。 You can view code from here if you have time. 如果你有时间,可以从这里查看代码。
  2. I've added transitions to planes. 我已经为飞机添加了过渡。

过渡

Problem: When I have more than one plane to take from a city it's just not moving. 问题:当我从一个城市乘坐多架飞机时,它就不会移动。 Instead it stays on the same position until the transition ends. 相反,它会一直保持在同一位置,直到转换结束。 I can't add concurrent transitions to the objects. 我无法向对象添加并发转换。

错误

My transition function is like; 我的过渡功能就像;

function myTransition(destPoi, originPoi) {
var tr_bl = true;
pathData = []; t_dest_poi = [];
if (tr_bl) {
//Origin destination coordinates taken from the Origin Poi
originPoint[0] = originPoi[1];
originPoint[1] = originPoi[2];
originPoint = geoMercator(originPoint);//Need transformation before using on screen.
var lineGenerator = d3.line().curve(d3.curveCatmullRom);
// Destination coordinate pairs transformed to screen coordinates
// and assigned to an array 
for (i = 0; i < destPoi.length; i++) {
  t_dest_poi[i] = geoMercator(destPoi[i]);
}
//appending new group g2 with id fp 
var g2 = map_svg.append("g").attr("id", "fp");

// Creating the planes and flight paths programmatically.*************************************
for (i = 0; i < destPoi.length; i++) {
  var plane = map_svg.append("path")
    .attr("class", "plane")
    .attr("d", "m25.21488,3.93375c-0.44355,0 -0.84275,0.18332 -1.17933,0.51592c-0.33397,0.33267 -0.61055,0.80884 -0.84275,1.40377c-0.45922,1.18911 -0.74362,2.85964 -0.89755,4.86085c-0.15655,1.99729 -0.18263,4.32223 -0.11741,6.81118c-5.51835,2.26427 -16.7116,6.93857 -17.60916,7.98223c-1.19759,1.38937 -0.81143,2.98095 -0.32874,4.03902l18.39971,-3.74549c0.38616,4.88048 0.94192,9.7138 1.42461,13.50099c-1.80032,0.52703 -5.1609,1.56679 -5.85232,2.21255c-0.95496,0.88711 -0.95496,3.75718 -0.95496,3.75718l7.53,-0.61316c0.17743,1.23545 0.28701,1.95767 0.28701,1.95767l0.01304,0.06557l0.06002,0l0.13829,0l0.0574,0l0.01043,-0.06557c0,0 0.11218,-0.72222 0.28961,-1.95767l7.53164,0.61316c0,0 0,-2.87006 -0.95496,-3.75718c-0.69044,-0.64577 -4.05363,-1.68813 -5.85133,-2.21516c0.48009,-3.77545 1.03061,-8.58921 1.42198,-13.45404l18.18207,3.70115c0.48009,-1.05806 0.86881,-2.64965 -0.32617,-4.03902c-0.88969,-1.03062 -11.81147,-5.60054 -17.39409,-7.89352c0.06524,-2.52287 0.04175,-4.88024 -0.1148,-6.89989l0,-0.00476c-0.15655,-1.99844 -0.44094,-3.6683 -0.90277,-4.8561c-0.22699,-0.59493 -0.50356,-1.07111 -0.83754,-1.40377c-0.33658,-0.3326 -0.73578,-0.51592 -1.18194,-0.51592l0,0l-0.00001,0l0,0z")
    .style("opacity", 1)
    .style("fill", "transparent");
  //creating flight path data with line generator
  pathData[i] = lineGenerator([originPoint, t_dest_poi[i]]);
  //appending created flight path to variable 
  var path = g2.append("path").data([
    [originPoint],
    [t_dest_poi[i]]
  ]).attr("d", d3.line());
//flight path
  g2.selectAll('path')
    .data([
      [originPoint],
      [t_dest_poi[i]]
    ])
    .attr('d', pathData)
    .attr("stroke", "blue")
    .attr("fill", "transparent");

  plane.style("fill", "grey");

  var route = g2.append("path")
    .datum({
      type: "LineString", coordinates: [
        [originPoint],
        [t_dest_poi[i]]]
    })
    .attr("class", "route")
    .attr("d", geoPath)
    .attr("stroke", "blue")
    .attr("fill", "transparent");

  // adding transition to plane
  plane.transition()
    .duration(5000)
    .attrTween("transform", translateAlong([originPoint, t_dest_poi[i]], path.node()))
    .remove();
    }
}
else {
}}

function translateAlong(co, path) {
var l = path.getTotalLength();
return function (d, i, a) {
return function (t) {
  var p = path.getPointAtLength(t * l);
  [a1, b1] = co[0];
  [a2, b2] = co[1];
  aci = Math.atan((b2 - b1) / (a2 - a1));
  aci = aci * 180 / Math.PI;
  if (a2 > a1) {
    aci = aci + 90;
  } else {
    aci = aci - 90;
  }
  return "translate(" + (p.x) + "," + (p.y) + ") scale(" + Math.sin(Math.PI * t) + ") rotate(" + aci + ")";
};
};
}

This seems like an issue with updating the path of the #fp element during the transition. 这似乎是在转换期间更新#fp元素的路径的问题。 The relatively easy fix in this case is to handle the transitions separately. 在这种情况下相对容易的修复是分别处理过渡。

In your code, in basemap.js circa line 58-63, you call myTransition() on an array of multiple elements after populating the array in a for loop. 在你的代码中,在第58-63行的basemap.js中,在for循环中填充数组之后,在多个元素的数组上调用myTransition()。

for (i = 0; i <= n - 1; i++) {
  fp[i] = [destAirportObjects[i][1], destAirportObjects[i][2]];
}
myTransition(fp, OriginAirport);

Call the function from within the for loop instead and your transition works fine: 从for循环中调用该函数,您的过渡工作正常:

for (i = 0; i <= n - 1; i++) {
  fp[i] = [destAirportObjects[i][1], destAirportObjects[i][2]];
    myTransition([fp[i]], OriginAirport);
}

If you choose this solution, you should update myTransition() to take a single set of coordinates to make the code easier to understand. 如果选择此解决方案,则应更新myTransition()以获取一组坐标以使代码更易于理解。

Alternatively , don't make any changes to the basemap.js file, but update myTransition so that the creation of the group (var g2) is completed within the destination for loop. 或者 ,不要对basemap.js文件进行任何更改,而是更新myTransition,以便在目标for循环内完成组(var g2)的创建。 Here's what you currently have in move.js starting at line 21: 以下是您目前在第21行开始的move.js中所拥有的内容:

var g2 = map_svg.append("g").attr("id", "fp");

// Creating the planes and flight paths programmatically.*************************************
for (i = 0; i < destPoi.length; i++) {
  //creating flight path data with line generator
  pathData[i] = lineGenerator([originPoint, t_dest_poi[i]]);
  //continue with loop

This is causing the g2 variable to be overwritten each time we move through the loop. 这导致每次我们在循环中移动时都会覆盖g2变量。 There needs to be a distinct group created for each transition/path. 需要为每个转换/路径创建一个不同的组。

// Creating the planes and flight paths programmatically.*************************************
for (i = 0; i < destPoi.length; i++) {
  var g2 = map_svg.append("g").attr("class", "fp");
  //creating flight path data with line generator
  pathData[i] = lineGenerator([originPoint, t_dest_poi[i]]);
  //continue with loop

Finally, since there are multiple elements in this case, "fp" should be the class of var g2, not the ID. 最后,由于在这种情况下有多个元素,“fp”应该是var g2的类,而不是ID。 Remember to update your accessors accordingly. 请记住相应地更新您的访问者。

Edit: Here's the sample for method #1 and method #2 编辑:这是方法#1方法#2的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM