代码之家  ›  专栏  ›  技术社区  ›  user3471259

d3设置文本动画,点击按钮移除图像

  •  0
  • user3471259  · 技术社区  · 6 年前

    嗨,我有一个点击按钮事件来启动一些文本的setinterval/clear interval动画,并在点击按钮时添加一个图像。我想帮助如何更好地停止和删除动画文本和删除图像时,一个新的按钮被单击。当数组结束时,文本被一个空字符串替换。每次我点击按钮,图像都会重复。

    这是我的D3代码的简化示例:

    <html lang="en">
    <head>
    
    <meta charset="utf-8">
        <title></title>
        <script src="https://d3js.org/d3.v4.min.js"></script>
        <script src="https://d3js.org/topojson.v0.min.js"></script>
    
      <style>
    
    </style>
    </head>
    
    <body>
    <div id ="container">
    
      <div id ="mapdata"></div>
      <div id = "buttons"></div>
    
    </div>
    
    <script>
    
    
    d3.queue()
    
      .defer(d3.csv, "data/testData.csv")
      .await(ready);
    
    function ready (error, data){
    
    var dataGroup = d3.nest()
          .key(function(d) {return d.year;}).sortKeys(d3.ascending)
          .key(function(d){return d.VoyageID;}).sortKeys(d3.ascending)
          .entries(data);
    
    dataGroup.forEach(function(yearObject,i) {
    
    var buttons = d3.select("#buttons").selectAll("button")
        .data(dataGroup)
        .enter()
        .append("button")
        .attr("class", "buttons")
        .attr("data-group", function(d){return d.key})
        .attr("id", function(d){return "button_" + d.key})
        .append("label")
        .text(function(d){return d.key;})
    
    
    var testData = d3.select("#mapdata").selectAll(".voyageData")
        .data(dataGroup)
        .enter()
        .append("div")
        .attr("class", "voyageData")
        .attr("data-group", function(d){return d.key})
        .attr("id", function(d){return "voyageText_" + d.key})
    
        var data = testData.selectAll(".data")
        .data(function(d) {return d.values;})
        .enter()
        .append("div")
        .attr("class", "data")
        .attr("id", function(d){return "data_" + d.key})
    
        var images = testData.selectAll(".images")
        .data(function(d) {return d.values;})
        images.exit().remove();
        images.enter()
        .append("div")
        .attr("class", "images")
        .attr("id", function(d){return "images_" + d.key})
    
    
    //buttons
    d3.select("#button_1906").on("click", function(d){
      clickButton(d,i);
    });
    d3.select("#button_1845").on("click", function(d){
      clickButton(d,i);
    });
    
    function clickButton(d,i) {
    var voyageClass = d.key;
    
    var voyageID = d.values[0].key;
    
    
    //animate place name and dates
    var j = 0;
    var animation = setInterval(function(){
    
      d3.select("#data_"+ voyageID)
        .text(function(d) { return d.values[j].arrivalDateTxt +" "+d.values[j].placeName; });
    
            j = j + 1;
    
            if(j==d.values[0].values.length)
             clearInterval(animation)
               if(j==d.values[0].values.length)
               d3.select("#data_"+ voyageID)
               .text("") // is there a better way to stop or remove text on completion of animation? I am just replacing it with an empty string.
           },1000);
    
    //add image
    d3.select("#images_" + voyageID)
           .append("img")
           .attr("src", function(d){return  d.values[j].groupPic })
           .attr("width", "40")
           //how do I remove image on completion of animation or click of new button?
    
    }
    
      });
    
    }
    
    </script>
    </body>
    
    </html>
    

    这是我的示例csv:

    VoyageID,arrivalDateTxt,year,placeName,groupPic
    1,14 January 1906,1906,Place 1,ANMS1113[006].jpg
    1,1 May 1907,1906,Place 2,ANMS1113[006].jpg
    1,26 October 1907,1906,Place 3,ANMS1113[006].jpg
    1,4 November 1907,1906,Place 4,ANMS1113[006].jpg
    1,26 November 1907,1906,Place 5,ANMS1113[006].jpg
    1,3 December 1907,1906,Place 6,ANMS1113[006].jpg
    1,10 December 1907,1906,Place 7,ANMS1113[006].jpg
    1,20 December 1907,1906,Place 8,ANMS1113[006].jpg
    1,26 December 1907,1906,Place 9,ANMS1113[006].jpg
    3,12 March 1845,1845,Island 1,00038301_4.jpg
    3,15 March 1845,1845,Island 2,00038301_4.jpg
    3,22 March 1845,1845,Place in ocean 3,00038301_4.jpg
    3,23 July 1845,1845,Place in ocean 4,00038301_4.jpg
    3,19 December 1845,1845,Place in ocean 5,00038301_4.jpg
    3,22 January 1846,1845,Place in ocean 6,00038301_4.jpg
    3,30 January 1846,1845,Back home,00038301_4.jpg
    

    我非常希望有人能帮助我,帮助我改进我的代码在一个更D3的方式。

    提前谢谢你,莎莉

    1 回复  |  直到 6 年前
        1
  •  1
  •   rioV8    6 年前

    要在完成时删除图像,可以使用:

    //animate place name and dates
    var j = 0;
    var animation = setInterval(function(){
    
      d3.select("#data_"+ voyageID)
        .text(function(d) { return d.values[j].arrivalDateTxt +" "+d.values[j].placeName; });
    
      j = j + 1;
    
      if(j==d.values[0].values.length) {
        clearInterval(animation);
        d3.select("#data_"+ voyageID).text("");
        d3.select("#images_" + voyageID).select("img").remove();
      }
    },1000);
    

    设置 .text("") 恢复动画之前的状态/DOM,所以我看不出有什么问题。

    要停止动画,必须跟踪上一个动画

    var runningAnimation = null;
    
    function stopAnimation(animation, voyageID) {
      clearInterval(animation);
      d3.select("#data_"+ voyageID).text(""); // is there a better way to stop or remove text on completion of animation? I am just replacing it with an empty string.
      d3.select("#images_" + voyageID).select("img").remove();
      runningAnimation = null;
    }
    
    function clickButton(d,i) {
    
      if (runningAnimation) { stopAnimation(runningAnimation.animation, runningAnimation.voyageID); }
    
      var voyageClass = d.key;
    
      var voyageID = d.values[0].key;
    
      //animate place name and dates
      var j = 0;
      var animation = setInterval(function(){
    
        d3.select("#data_"+ voyageID)
          .text(function(d) { return d.values[j].arrivalDateTxt +" "+d.values[j].placeName; });
    
        j = j + 1;
    
        if(j==d.values[0].values.length) { stopAnimation(animation, voyageID); }
      },1000);
    
      runningAnimation = { animation: animation, voyageID: voyageID };
    
      //add image
      d3.select("#images_" + voyageID)
        .append("img")
        .attr("src", function(d){return  d.values[j].groupPic })
        .attr("width", "40");
    }
    

    buttons.on("click", clickButton);
    //buttons
    // d3.select("#button_1906").on("click", function(d){
    //   clickButton(d,i);
    // });
    // d3.select("#button_1845").on("click", function(d){
    //   clickButton(d,i);
    // });