d3.js无法使用常规更新模式和转换

时间:2015-02-15 22:31:18

标签: javascript d3.js

有人请给我一些关于这个d3.js问题的帮助吗?我正在尝试遵循M. Bostock的“一般更新模式”。我已经做过研究,试图找到一个解决方案,但没有到达任何地方。

我没有使用列和行,而是绘制线条。

程序显示两个模式,即32行组合在一起 “g”,我认为。

我希望这两组线要么一个在另一个上面显示,一组通过样式更改为不透明度消失,或者

将剩余的一组线放在与之相同的位置 第一组消失后,第一组线(原点为0.0)。

我认为问题在于如何将这些与“g”组合在一起但是 不确定。我尝试了各种方法来附加div,容器, 并使用转换,翻译,但没有任何工作。我试过了 改变容器的大小,这也不起作用。

我认为svgs在过渡后被删除了,但我没有 了解如何“向上移动”第二组线。

样本位于jsfiddle:

https://jsfiddle.net/wheatgrass/t3bgcxhu/

感谢您的帮助。我很高兴学习d3.js。

<script>
var num = 0;

var width = 660,
   height = 25;

var radius = 2;

d3.select("body").selectAll("h1").data([{}])
  .enter().insert("h1").html("Some text here")
var svg = d3.select("#svgcontainer").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
var g = svg.append("svg:g") 
    .attr("transform", "translate(0, 0)") ;

function getpatterndata(num) {
if (num == 1)  {
    var pdata = cellular(); }
else { pdata = cellular2(); }
console.log("pdata",pdata);

return pdata;
}

function makelines(datas) {

var entries = d3.entries(datas);

var thelines = [];
var oneline = [];

entries.forEach( function (d) {
var line = d.value.split(" ");
    thelines.push(line);
  });
//console.log("thelines", thelines);
return thelines;
}

function update(thelines,num) {

 // DATA JOIN
 // Join new data with old elements, if any.

 // and UPDATE
 for (i =0; i< thelines.length; i++) {


var oneline = thelines.pop();

//append lines to container
   var sampleSVG = d3.select("body")
    .append("svg")
    .attr("width", 660)
    .attr("height", 10);    

var circles = sampleSVG.selectAll("circle")
                      .data(oneline) 
                   .enter()
                      .append("circle");



var circleAttributes = circles
                   .attr("cx", function(d,i) {return (i*10)} )
                   .attr("cy", 3)
                   .attr("transform", "translate(30," + (0) + ")")
           .transition().duration(2000)
           .attr("r", function(d,i) { if (+d  == 1)
                 { return r=3;  } else { return r = 2;}})
                   .style("fill", function(d) {
                     var returnColor;
                     if (+d === 0) { returnColor = "lightblue";
                     } else if (+d === 1) { returnColor = "red";
                     } else if (+d === 0) { returnColor = "green"; }
                     return returnColor;
                   })
                  .transition(3000).delay(2000)
      .attr("opacity", 0.01)
     .transition().remove();

}

}

function update2(thelines,num) {

// DATA JOIN
// Join new data with old elements, if any.

// and UPDATE
for (i =0; i< thelines.length; i++) {
 //for (i = thelines.length; i >= 0;  i--) {

var oneline = thelines.pop(); 

//append lines to container
var sampleSVG = d3.select("body")
    .append("svg")
    .attr("width", 660)
    .attr("height", 10)    
    .attr("transform", "translate(0, 0)") ;

var circles = sampleSVG.selectAll("body")
                      .data(oneline) //will be oneline
                   .enter()
                      .append("circle");


var circleAttributes = circles
                   .attr("cx", function(d,i) {return (i*10)} )
                   .attr("cy", 3)
                   .attr("transform", "translate(30,0)")
           .transition().duration(2000)
           .attr("r", function(d,i) { if (+d  == 1)
                 { return r=3;  } else { return r = 2;}})
                   .style("fill", function(d) {
                     var returnColor;
                     if (+d === 0) { returnColor = "lightblue";
                     } else if (+d === 1) { returnColor = "red";
                     } else if (+d === 0) { returnColor = "green"; }
                     return returnColor;
                   });
}
}

// The initial display.
var initialpattern = [];
var secpattern = [];
initialpattern = getpatterndata(2);

var thepatternrows = [];
thepatternrows = makelines(initialpattern);



update(thepatternrows,2);


secpattern = getpatterndata(1);

thepatternrows = makelines(secpattern);

update2(thepatternrows,1);

1 个答案:

答案 0 :(得分:0)

我试着看看你的jsfiddle,但是d3资源似乎没有正确加载(控制台记录了一些关于加载not-https资源的错误)。 我创造了一个plunker: http://plnkr.co/edit/UnOiooAFsprAYDQcyNFi?p=preview

var num = 0;

var width = 660,
  height = 800;

var radius = 2;

d3.select("body").selectAll("h1").data([{}]).enter()
  .insert("h1").html("Some text here")
var svg = d3.select("#svgcontainer").append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g");
var g = svg.append("svg:g")
  .attr("transform", "translate(0, 0)");

function getpatterndata(num) {
  if (num == 1) {
    var pdata = cellular();
  } else {
    pdata = cellular2();
  }
  console.log("pdata", pdata);

  return pdata;
}

function makelines(datas) {

  var entries = d3.entries(datas);

  var thelines = [];
  var oneline = [];

  entries.forEach(function(d) {
    var line = d.value.split(" ");
    thelines.push(line);
  });
  console.log("thelines", thelines);
  return thelines;
}

function update(thelines, num) {

  // DATA JOIN
  // Join new data with old elements, if any.
console.log(thelines)
  // and UPDATE
  for (i = 0; i < thelines.length; i++) {
    //for (i = thelines.length; i >= 0;  i--) {

    var oneline = thelines.pop();
console.log(oneline);
    //append lines to container
    var circles = g
      .selectAll(".dummy")
      .data(oneline) //will be oneline
      .enter()
      .append("circle")
      .classed('first-update',true);

    //console.log("inside update,oneline", oneline);


    var circleAttributes = circles.attr("cx", function(d, idx) {
      var x= idx*10;
      console.log('x: ',x)
      return x;
    })
      .attr("cy", function(d, idx) {
        var y = (i + 1) * 10;
        console.log('y: ',y)

        return y;
      })
      .attr('r',2)
      .attr("transform", "translate(30," + (0) + ")")
      .transition().duration(2000)
      .attr("r", function(d, i) {
        if (+d == 1) {
          return 3;
        } else {
          return 2;
        }
      })
      .style("fill", function(d) {
        var returnColor;
        if (+d === 0) {
          returnColor = "lightblue";
        } else if (+d === 1) {
          returnColor = "red";
        } else if (+d === 0) {
          returnColor = "green";
        }
        return returnColor;
      })
      .transition(3000)
      .delay(2000)
      .attr("opacity", 0.01)
      .transition();
    //.remove();

  }

} //end function

function update2(thelines, num) {

  // DATA JOIN
  // Join new data with old elements, if any.

  // and UPDATE
  for (i = 0; i < thelines.length; i++) {
    //for (i = thelines.length; i >= 0;  i--) {

    var oneline = thelines.pop();

    //append lines to container
    //var sampleSVG = d3.select('svg');
    var circles = g //.selectAll("body")
      .selectAll('.dummy')
      .data(oneline)
    //will be oneline
    .enter()
      .append("circle");
    console.log("inside update,oneline", oneline);


    var circleAttributes = circles.attr("cx", function(d, idx) {
      return (idx * 10);
    })
      .attr("cy", function(d,idx){return i*10;})
      .attr("transform", "translate(30,0)")
      .transition().duration(2000)
      .attr("r", function(d, i) {
        if (+d == 1) {
          return 3;
        } else {
          return 2;
        }
      })
      .style("fill", function(d) {
        var returnColor;
        if (+d === 0) {
          returnColor = "lightblue";
        } else if (+d === 1) {
          returnColor = "red";
        } else if (+d === 0) {
          returnColor = "green";
        }
        return returnColor;
      });
  }
}

// The initial display.
var initialpattern = [];
var secpattern = [];
initialpattern = getpatterndata(2);

var thepatternrows = [];
thepatternrows = makelines(initialpattern);

console.log("thepatternrows", thepatternrows);
update(thepatternrows, 2);

//d3.select('div').attr("class",".inside").selectAll("*").remove();

secpattern = getpatterndata(1);

thepatternrows = makelines(secpattern);

update2(thepatternrows, 1);



//#myc11a.js

//randomized, and returns a big list of strings separated by a space
function cellular2() {
  // This is the same as the other pattern input except it randomizes
  // the neighbors.
  // My attempt to translate from python to d3.js javascript
  //def ca():
  //   ''' Celluar automata with Python - K. Hong'''
  //   # 64 Boolean - True(1) : '*'
  //   #            - False(0): '-'
  //   # Rule - the status of current cell vaue is True
  //   # if only one of the two neighbors at the previous step is True('*')
  //   # otherwise, the current cell status is False('-')

  //  # list representing the current status of 64 cells
  var ca = [];
  for (i = 0; i < 64; i++) {

    var arval = Math.round(Math.random());
    ca.push(arval);
  }

  //# new Cellular values

  //   dic = { 0:"-", 1: "*" }


  //# initial draw - step 0
  //print  ''.join( [dic[e] for e in ca_new])
  //console.log('initial ca',ca);

  var ca_next_string = '';
  var castring = ca.valueOf();
  //console.log("initial castring",castring);
  var castring2 = ca.join(" ");
  //console.log("initial castring2",castring2);


  var ca_lol0 = [];
  ca_lol0.push(castring2);
  //ca_lol0.push("\n");

  var ca_new = ca;


  castring = ''
  castring2 = ''
  // additional 31 steps
  // loop through 0 to 63 and store the current cell status in ca_new list
  var ca_next = [];
  var step = 1;
  while (step < 32) {
    ca_new = [];
    // loop through 0 to 63 and store the current cell status in ca_new list
    for (var i = 0; i < 64; i++) {
      // inside cells - check the neighbor cell state
      if (i > 0 && i < 63) {
        if (ca[i - 1] == ca[i + 1]) {
          ca_new.push(0);
        } else {
          ca_new.push(1);
        }
      }

      // left-most cell : check the second cell
      else if (i == 0) {
        if (ca[1] == 1) {
          ca_new.push(1);
        } else {
          ca_new.push(0);
        }
      }

      // right-most cell : check the second to the last cell
      else if (i == 63) {
        if (ca[62] == 1) {
          ca_new.push(1);
        } else {
          ca_new.push(0);
        }
      }


      castring0 = ca_new.join(" ");
      castring20 = ca_new.concat("\n");
    } //end of for

    //draw current cell state
    //this one contains 0,1

    ca_lol0.push(castring20.join(' '))
    //ca_lol0.push(castring20)
    //ca_lol0.push('\n')

    //update cell list
    ca = ca_new;
    ca_next = [];
    step = step + 1;
  } //end of while

  //           console.log("final list of strings",ca_lol0);
  console.log("pattern of randomized neighbors");
  // return castring20;
  return ca_lol0;

}

//myc11.js
//returns a big list of strings separated by a space
function cellular() {
  // my attempt to translate from python to d3.js javascript
  //def ca():
  //   ''' Celluar automata with Python - K. Hong'''
  //   # 64 Boolean - True(1) : '*'
  //   #            - False(0): '-'
  //   # Rule - the status of current cell vaue is True
  //   # if only one of the two neighbors at the previous step is True('*')
  //   # otherwise, the current cell status is False('-')

  //  # list representing the current status of 64 cells
  var ca = [
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  ];

  //# new Cellular values

  //   dic = { 0:"-", 1: "*" }


  //# initial draw - step 0
  //print  ''.join( [dic[e] for e in ca_new])
  //console.log('initial ca',ca);

  var ca_next_string = '';
  var castring = ca.valueOf();
  //console.log("initial castring",castring);
  var castring2 = ca.join(" ");
  //console.log("initial castring2",castring2);


  var ca_lol0 = [];
  ca_lol0.push(castring2);
  //ca_lol0.push("\n");

  var ca_new = ca;


  castring = ''
  castring2 = ''
  // additional 31 steps
  // loop through 0 to 63 and store the current cell status in ca_new list
  var ca_next = [];
  var step = 1;
  while (step < 32) {
    ca_new = [];
    // loop through 0 to 63 and store the current cell status in ca_new list
    for (var i = 0; i < 64; i++) {
      // inside cells - check the neighbor cell state
      if (i > 0 && i < 63) {
        if (ca[i - 1] == ca[i + 1]) {
          ca_new.push(0);
        } else {
          ca_new.push(1);
        }
      }

      // left-most cell : check the second cell
      else if (i == 0) {
        if (ca[1] == 1) {
          ca_new.push(1);
        } else {
          ca_new.push(0);
        }
      }

      // right-most cell : check the second to the last cell
      else if (i == 63) {
        if (ca[62] == 1) {
          ca_new.push(1);
        } else {
          ca_new.push(0);
        }
      }


      castring0 = ca_new.join(" ");
      castring20 = ca_new.concat("\n");
    } //end of for

    //draw current cell state
    //this one contains 0,1

    ca_lol0.push(castring20.join(' '))
    //ca_lol0.push(castring20)
    //ca_lol0.push('\n')

    //update cell list
    ca = ca_new;
    ca_next = [];
    step = step + 1;
  } //end of while

  //           console.log("final list of strings",ca_lol0);
  console.log("pattern of static assigned neighbors");
  // return castring20;
  return ca_lol0;

}

我注意到的第一件事是你在更新循环的每次迭代中创建一个svg。此步骤不是必需的,因为您在顶部创建了svg,以及用于存储您的圈子的组(或者我猜)。

至于更新模式,这是它的工作原理(据我理解):

  • 您必须选择要更新的元素类型(在上面的代码中:selectAll(&#39; .dummy&#39;))
  • 您设置要绑定的数据(.data(oneline))
  • 您进行操作(附加圈子,设置属性等)
  • 退出并删除

现在在上面的代码中,我在绑定到数据之前使用了.dummy选择器,以避免选择现有对象。正确的方法是使用.selectAll(&#39; circle&#39;),但在这种情况下,你只会获得一行圆圈,因为每次都会重新选择现有的圆圈。这与您自己循环上线的事实有关。我会尝试直接绑定到原始集合,并尝试正确使用回调函数来计算cx和cy。我是否会自己创建,我甚至会创建一个具有x和y属性的对象数组,这样可以让我轻松地构建我的圆圈(但这是个人数据设计选择)。

另外,要小心在循环中使用变量i,并在回调函数中作为索引器来计算cx和cy,这可能会导致冲突。

我希望这是明确的(呃)并且它有所帮助;否则我会尝试详细说明所需的要点。