d3不向绑定的rect显示初始数据 [英] d3 not displaying initial data to bound rects

查看:76
本文介绍了d3不向绑定的rect显示初始数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个初始的对象数组,即我的数据.调用一个名为render()的函数,该函数应首先显示绑定到该数据的矩形.但是我没有看到任何矩形.

然后,如果单击这些矩形中的任何一个,则会调用函数removeElement,该函数将从数组中删除该矩形的数据,然后调用render()并使用新数据执行该函数.

如果在任意位置单击svg,则将新数据元素添加到数据中,然后再次调用render,该渲染应根据新数据再次显示矩形.

 <!DOCTYPE html>
<meta charset="utf-8">
<style>
  /*.active {
    stroke: #000;
    stroke-width: 2px;
  }*/

  svg {
    border: 1px solid black;
  }
</style>
<svg width="800" height="300"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
    width = 840 - margin.left - margin.right,
    height = 640 - margin.top - margin.bottom;

  var svg = d3.select("svg");

  var data = [{
    x: 100
  }, {
    x: 300
  }, {
    x: 400
  }, {
    x: 600
  }];

  var ind = 0;
  var groove = svg.append("g")
    .attr("class", "groove_group");

  groove.append("rect")
    .attr("x", 0)
    .attr("y", 150)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", width)
    .style("fill", "grey");

  groove.append("rect")
    .attr("x", 2)
    .attr("y", 152)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");

  render();

  function render() {
    // create group
    var group = svg.selectAll(null)
      .data(data, function(d) {
        return d.x
      });

    group.exit().remove();

    group.enter().append("g")
      .attr("class", "group")
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);

    group.append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 100)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "lightblue")
      .attr('id', function(d, i) {
        return 'handle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black");

    group.append("text")
      .attr("x", function(d, i) {
        if (i == 0) { // first element
          return ((data[i].x / 2));
        } else {
          return (data[i].x - (data[i].x - data[i - 1].x) / 2);
        }
      })
      .attr("y", 100)
      .attr("text-anchor", "middle")
      .style("fill", "black")
      .attr('id', function(d, i) {
        return 'text_' + i;
      })
      .text(function(d, i) {
        if (i == 0) { // first set
          return i + ": " + (data[i].x) + "m";
        } else {
          return i + ": " + ((data[i].x - data[i - 1].x)) + "m";
        }
      });
    
  }
  svg.on("click", function() {
    var coords = d3.mouse(this);

    getPosition(ind, coords[0]);

    render();

  });

  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }

  function dragged(d, i) {
    if (i == 0) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x / 2))
        .text(function(d) {
          return i + " " + d3.event.x
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + " " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else if (i == data.length - 1) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x - data[i - 1].x) / 2 + data[i - 1].x)
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + (width - d3.event.x) / 2)
        .text(function(d) {
          return (i + 1) + ": " + (width - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else {
      d3.select("#text_" + i)
        .attr("x", d.x = d3.event.x - ((d3.event.x - data[i - 1].x) / 2))
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + ": " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    }
  }

  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }

  function removeElement(d, i) {
    d3.event.stopPropagation();
   
    data = data.filter(function(e) {
      return e != d;
    });
    d3.select(this)
      .remove();

    render();
   
  }

  function getPosition(ind, coords) {
    if (coords[0] > data[ind].x) {
      getPosition(++ind);
    } else {
      data.splice(1, 0, {
        x: coords
      });
    }
  }
</script> 

任何帮助将不胜感激,

解决方案

如果您查看group ...

var group = svg.selectAll(null)
    .data(data, function(d) {
        return d.x
    });

...您将看到它只是一个更新"选择.此处没有没有 SVG <g>元素.因此,这...

group.append("rect")
    //etc...

没有效果.

解决方案:使用merge()功能或适当的回车选择:

var groupEnter = group.enter()
    .append("g")
    .attr("class", "group");

groupEnter.append("rect")
    //etc...

这是更新的代码:

 <!DOCTYPE html>
<meta charset="utf-8">
<style>
  /*.active {
    stroke: #000;
    stroke-width: 2px;
  }*/

  svg {
    border: 1px solid black;
  }
</style>
<svg width="800" height="300"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
    width = 840 - margin.left - margin.right,
    height = 640 - margin.top - margin.bottom;

  var svg = d3.select("svg");

  var data = [{
    x: 100
  }, {
    x: 300
  }, {
    x: 400
  }, {
    x: 600
  }];

  var ind = 0;
  var groove = svg.append("g")
    .attr("class", "groove_group");

  groove.append("rect")
    .attr("x", 0)
    .attr("y", 150)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", width)
    .style("fill", "grey");

  groove.append("rect")
    .attr("x", 2)
    .attr("y", 152)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");

  render();

  function render() {
    // create group
    var group = svg.selectAll(null)
      .data(data, function(d) {
        return d.x
      });

    group.exit().remove();

    var groupEnter = group.enter().append("g")
      .attr("class", "group");
      
    groupEnter.call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);

    groupEnter.append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 100)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "lightblue")
      .attr('id', function(d, i) {
        return 'handle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black");

    groupEnter.append("text")
      .attr("x", function(d, i) {
        if (i == 0) { // first element
          return ((data[i].x / 2));
        } else {
          return (data[i].x - (data[i].x - data[i - 1].x) / 2);
        }
      })
      .attr("y", 100)
      .attr("text-anchor", "middle")
      .style("fill", "black")
      .attr('id', function(d, i) {
        return 'text_' + i;
      })
      .text(function(d, i) {
        if (i == 0) { // first set
          return i + ": " + (data[i].x) + "m";
        } else {
          return i + ": " + ((data[i].x - data[i - 1].x)) + "m";
        }
      });
    
  }
  svg.on("click", function() {
    var coords = d3.mouse(this);

    getPosition(ind, coords[0]);

    render();

  });

  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }

  function dragged(d, i) {
    if (i == 0) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x / 2))
        .text(function(d) {
          return i + " " + d3.event.x
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + " " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else if (i == data.length - 1) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x - data[i - 1].x) / 2 + data[i - 1].x)
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + (width - d3.event.x) / 2)
        .text(function(d) {
          return (i + 1) + ": " + (width - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else {
      d3.select("#text_" + i)
        .attr("x", d.x = d3.event.x - ((d3.event.x - data[i - 1].x) / 2))
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + ": " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    }
  }

  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }

  function removeElement(d, i) {
    d3.event.stopPropagation();
   
    data = data.filter(function(e) {
      return e != d;
    });
    d3.select(this)
      .remove();

    render();
   
  }

  function getPosition(ind, coords) {
    if (coords[0] > data[ind].x) {
      getPosition(++ind);
    } else {
      data.splice(1, 0, {
        x: coords
      });
    }
  }
</script> 

PS:您的代码仍然有很多问题(我可以在这里预见未来的问题)...这个答案仅在处理有关输入"选择的主要问题. >

I have an initial array of object which is my data. A function called render() is called which should first display rectangles bound to this data. But I am not seeing any rectangles.

Then if any of these rectangles is clicked a function removeElement is called, which removes that rectangle's data from the array and then calls render() and executes it using the new data.

If the svg is clicked on anywhere a new data element is added to the data, and again render is called which should display the rectangles again according to the new data.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  /*.active {
    stroke: #000;
    stroke-width: 2px;
  }*/

  svg {
    border: 1px solid black;
  }
</style>
<svg width="800" height="300"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
    width = 840 - margin.left - margin.right,
    height = 640 - margin.top - margin.bottom;

  var svg = d3.select("svg");

  var data = [{
    x: 100
  }, {
    x: 300
  }, {
    x: 400
  }, {
    x: 600
  }];

  var ind = 0;
  var groove = svg.append("g")
    .attr("class", "groove_group");

  groove.append("rect")
    .attr("x", 0)
    .attr("y", 150)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", width)
    .style("fill", "grey");

  groove.append("rect")
    .attr("x", 2)
    .attr("y", 152)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");

  render();

  function render() {
    // create group
    var group = svg.selectAll(null)
      .data(data, function(d) {
        return d.x
      });

    group.exit().remove();

    group.enter().append("g")
      .attr("class", "group")
      .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);

    group.append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 100)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "lightblue")
      .attr('id', function(d, i) {
        return 'handle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black");

    group.append("text")
      .attr("x", function(d, i) {
        if (i == 0) { // first element
          return ((data[i].x / 2));
        } else {
          return (data[i].x - (data[i].x - data[i - 1].x) / 2);
        }
      })
      .attr("y", 100)
      .attr("text-anchor", "middle")
      .style("fill", "black")
      .attr('id', function(d, i) {
        return 'text_' + i;
      })
      .text(function(d, i) {
        if (i == 0) { // first set
          return i + ": " + (data[i].x) + "m";
        } else {
          return i + ": " + ((data[i].x - data[i - 1].x)) + "m";
        }
      });
    
  }
  svg.on("click", function() {
    var coords = d3.mouse(this);

    getPosition(ind, coords[0]);

    render();

  });

  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }

  function dragged(d, i) {
    if (i == 0) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x / 2))
        .text(function(d) {
          return i + " " + d3.event.x
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + " " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else if (i == data.length - 1) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x - data[i - 1].x) / 2 + data[i - 1].x)
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + (width - d3.event.x) / 2)
        .text(function(d) {
          return (i + 1) + ": " + (width - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else {
      d3.select("#text_" + i)
        .attr("x", d.x = d3.event.x - ((d3.event.x - data[i - 1].x) / 2))
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + ": " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    }
  }

  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }

  function removeElement(d, i) {
    d3.event.stopPropagation();
   
    data = data.filter(function(e) {
      return e != d;
    });
    d3.select(this)
      .remove();

    render();
   
  }

  function getPosition(ind, coords) {
    if (coords[0] > data[ind].x) {
      getPosition(++ind);
    } else {
      data.splice(1, 0, {
        x: coords
      });
    }
  }
</script>

Any help would be greatly appreciated,

解决方案

If you look at group...

var group = svg.selectAll(null)
    .data(data, function(d) {
        return d.x
    });

... you'll see that it is just an "update" selection. There is no SVG <g> element being appended here. Thus, this...

group.append("rect")
    //etc...

Has no effect.

Solution: Use a merge() function or a proper enter selection:

var groupEnter = group.enter()
    .append("g")
    .attr("class", "group");

groupEnter.append("rect")
    //etc...

Here is the updated code:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  /*.active {
    stroke: #000;
    stroke-width: 2px;
  }*/

  svg {
    border: 1px solid black;
  }
</style>
<svg width="800" height="300"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
  var margin = {
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    },
    width = 840 - margin.left - margin.right,
    height = 640 - margin.top - margin.bottom;

  var svg = d3.select("svg");

  var data = [{
    x: 100
  }, {
    x: 300
  }, {
    x: 400
  }, {
    x: 600
  }];

  var ind = 0;
  var groove = svg.append("g")
    .attr("class", "groove_group");

  groove.append("rect")
    .attr("x", 0)
    .attr("y", 150)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 6)
    .attr("width", width)
    .style("fill", "grey");

  groove.append("rect")
    .attr("x", 2)
    .attr("y", 152)
    .attr("rx", 2)
    .attr("ry", 2)
    .attr("height", 2)
    .attr("width", 796)
    .style("fill", "black");

  render();

  function render() {
    // create group
    var group = svg.selectAll(null)
      .data(data, function(d) {
        return d.x
      });

    group.exit().remove();

    var groupEnter = group.enter().append("g")
      .attr("class", "group");
      
    groupEnter.call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
      .on("click", removeElement);

    groupEnter.append("rect")
      .attr("x", function(d) {
        return d.x;
      })
      .attr("y", 100)
      .attr("height", 100)
      .attr("width", 15)
      .style("fill", "lightblue")
      .attr('id', function(d, i) {
        return 'handle_' + i;
      })
      .attr("rx", 6)
      .attr("ry", 6)
      .attr("stroke-width", 2)
      .attr("stroke", "black");

    groupEnter.append("text")
      .attr("x", function(d, i) {
        if (i == 0) { // first element
          return ((data[i].x / 2));
        } else {
          return (data[i].x - (data[i].x - data[i - 1].x) / 2);
        }
      })
      .attr("y", 100)
      .attr("text-anchor", "middle")
      .style("fill", "black")
      .attr('id', function(d, i) {
        return 'text_' + i;
      })
      .text(function(d, i) {
        if (i == 0) { // first set
          return i + ": " + (data[i].x) + "m";
        } else {
          return i + ": " + ((data[i].x - data[i - 1].x)) + "m";
        }
      });
    
  }
  svg.on("click", function() {
    var coords = d3.mouse(this);

    getPosition(ind, coords[0]);

    render();

  });

  function dragstarted(d) {
    d3.select(this).raise().classed("active", true);
  }

  function dragged(d, i) {
    if (i == 0) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x / 2))
        .text(function(d) {
          return i + " " + d3.event.x
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + " " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else if (i == data.length - 1) {
      d3.select("#text_" + i)
        .attr("x", d.x = (d3.event.x - data[i - 1].x) / 2 + data[i - 1].x)
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + (width - d3.event.x) / 2)
        .text(function(d) {
          return (i + 1) + ": " + (width - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    } else {
      d3.select("#text_" + i)
        .attr("x", d.x = d3.event.x - ((d3.event.x - data[i - 1].x) / 2))
        .text(function(d) {
          return i + ": " + (d3.event.x - data[i - 1].x) + "m"
        });
      d3.select("#text_" + (i + 1))
        .attr("x", d.x = d3.event.x + ((data[i + 1].x - d3.event.x) / 2))
        .text(function(d) {
          return (i + 1) + ": " + (data[i + 1].x - d3.event.x) + "m"
        });
      d3.select(this).select("rect")
        .attr("x", d.x = d3.event.x);
    }
  }

  function dragended(d) {
    d3.select(this)
      .classed("active", false);
  }

  function removeElement(d, i) {
    d3.event.stopPropagation();
   
    data = data.filter(function(e) {
      return e != d;
    });
    d3.select(this)
      .remove();

    render();
   
  }

  function getPosition(ind, coords) {
    if (coords[0] > data[ind].x) {
      getPosition(++ind);
    } else {
      data.splice(1, 0, {
        x: coords
      });
    }
  }
</script>

PS: Your code still have a lot of problems (and I can foresee future questions here)... This answer is dealing only with the main issue regarding the "enter" selection.

这篇关于d3不向绑定的rect显示初始数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆