D3.js树结构右侧如何对应添加热图,如图1一样?

想实现的效果 ---如图像图1这样 ,https://juejin.cn/post/684490... 我是参考的这篇文章, 可是我先做出来有些不一样 因为他文章里面有没写右侧的实现方式 像图2一样,如何和能让右侧的热图每个块都对其没有边距呢 有没有懂D3的前辈指教一下 是需要用到什么特有的模式吗 因为左侧是要变化的 右侧的热图的高度也要相应的变化 我现在方块的高度是写死的
image.png

image.png

以下是我全部的代码,直接html打开可用

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  body {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    margin: 0;
  }

  #show-length {
    position: absolute;
    top: 10px;
    left: 10px;
  }

  .links {
    fill: none;
    stroke: #000;
  }

  .link-extensions {
    fill: none;
    stroke: #000;
    stroke-opacity: .25;
  }

  .labels {
    font: 10px sans-serif;
  }

  .link--active {
    stroke: #000 !important;
    stroke-width: 1.5px;
  }

  .link-extension--active {
    stroke-opacity: .6;
  }

  .label--active {
    font-weight: bold;
  }
</style>
<label id="show-length">
  <input type="checkbox"> Show branch length
</label>
<div id="d3jstest"></div>

<!-- Copyright 2011 Jason Davies https://github.com/jasondavies/newick.js -->
<script>function parseNewick (a) { for (var e = [], r = {}, s = a.split(/\s*(;|\(|\)|,|:)\s*/), t = 0; t < s.length; t++) { var n = s[t]; switch (n) { case "(": var c = {}; r.branchset = [c], e.push(r), r = c; break; case ",": var c = {}; e[e.length - 1].branchset.push(c), r = c; break; case ")": r = e.pop(); break; case ":": break; default: var h = s[t - 1]; ")" == h || "(" == h || "," == h ? r.name = n : ":" == h && (r.length = parseFloat(n)) } } return r }</script>

<!-- Copyright 2016 Mike Bostock https://d3js.org -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

  var outerRadius = 670,
    innerRadius = outerRadius - 370;

  var color = d3.scaleOrdinal()
    .domain(["Bacteria", "Eukaryota", "Archaea"])
    .range(d3.schemeCategory10);

  var cluster = d3.cluster()
    .size([500, innerRadius])
    .separation(function (a, b) { return 1; });

  var svg = d3.select("#d3jstest").append("svg")
    .attr("width", outerRadius)
    .attr("height", outerRadius);

  // var legend = svg.append("g")
  //   .attr("class", "legend")
  //   .selectAll("g")
  //   .data(color.domain())
  //   .enter().append("g")
  //   .attr("transform", function (d, i) { return "translate(" + (outerRadius * 2 - 10) + "," + (i * 20 + 10) + ")"; });

  // legend.append("rect")
  //   .attr("x", -18)
  //   .attr("width", 18)
  //   .attr("height", 18)
  //   .attr("fill", color);

  // legend.append("text")
  //   .attr("x", -24)
  //   .attr("y", 9)
  //   .attr("dy", ".35em")
  //   .attr("text-anchor", "end")
  //   .text(function (d) { return d; });

  var chart = svg.append("g")
    .attr("transform", "translate(10,30)");

  d3.text("life.txt", function (error, life) {

    if (error) throw error;

    var root = d3.hierarchy(parseNewick(life), function (d) { return d.branchset; })
      .sum(function (d) { return d.branchset ? 0 : 1; })
      .sort(function (a, b) { return (a.value - b.value) || d3.ascending(a.data.length, b.data.length); });

    console.log(root)

    cluster(root);

    var input = d3.select("#show-length input").on("change", changed),
      timeout = setTimeout(function () { input.property("checked", true).each(changed); }, 2000);

    setRadius(root, root.data.length = 0, innerRadius / maxLength(root));
    setColor(root);

    var linkExtension = chart.append("g")
      .attr("class", "link-extensions")
      .selectAll("path")
      .data(root.links().filter(function (d) { return !d.target.children; }))
      .enter().append("path")
     
      .each(function (d) { d.target.linkExtensionNode = this; })
      .style('stroke', function (d) {
        return 'red'
      })
      .attr("d", linkExtensionConstant);

    // 手动添加了第1列热图
    var node = chart.selectAll("point")
      .data(root.links().filter(function (d) { return !d.target.children; }))
      .enter().append("rect")
      .attr("class", "node111")
      .attr('width', 60)
      .attr('height', 60)
      .style('fill', function (d) {
        return 'red'
      })
      .style('stroke', function (d) {
        return 'red'
      })
      .attr('x', function (d) {
        return d.target.y +10
      })
      .attr('y', function (d) {
        return  d.target.x
      })
      // 根据布局算出的每个节点的坐标位置 来摆放节点
      .attr("transform", "translate(0,-30)");

    //  手动添加了第2列热图
    var node = chart.selectAll("point")
      // 绑定节点数据
      .data(root.links().filter(function (d) { return !d.target.children; }))
      .enter().append("rect")
      .attr("class", "node111")
      .attr('width', 60)
      .attr('height', 60)
      .style('fill', function (d) {
        return 'yellow'
      })
      .style('stroke', function (d) {
        return 'yellow'
      })
      .attr('x', function (d) {
        return d.target.y + 10
      })
      .attr('y', function (d) {
        return  d.target.x
      })
      // 根据布局算出的每个节点的坐标位置 来摆放节点
      .attr("transform", "translate(60,-30)");


    // svg
    //   .selectAll('point')
    //   .data(dataset)
    //   .enter()
    //   .append('rect')
    //   .attr('class', 'rect bordered')
    //   .attr('x', function (d) {
    //     return d.row * gridWidth
    //   })
    //   .attr('y', function (d) {
    //     return d.col * gridHeight
    //   })
    //   .attr('width', gridWidth)
    //   .attr('height', gridHeight)
    //   .style('fill', function (d) {
    //     return colors[d.base]
    //   })
    //   .style('stroke', function (d) {
    //     return colors[d.base]
    //   })





    var link = chart.append("g")
      .attr("class", "links")
      .selectAll("path")
      .data(root.links())
      .enter().append("path")
      .each(function (d) { d.target.linkNode = this; })
      .attr("d", linkConstant)
      .attr("stroke", function (d) { return d.target.color; });

    //   chart.append("g")
    //   .attr("class", "labels")
    // .selectAll("text")
    // .data(root.leaves())
    // .enter().append("text")
    //   .attr("dy", ".31em")
    //   .attr("transform", function(d,i) { return "rotate(" + (d.x - 90) + ")translate(" + (innerRadius + 4) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); })
    //   .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
    //   .text(function(d) { return d.data.name.replace(/_/g, " "); })
    //   .on("mouseover", mouseovered(true))
    //   .on("mouseout", mouseovered(false));


    function changed () {
      clearTimeout(timeout);
      var t = d3.transition().duration(750);
      linkExtension.transition(t).attr("d", this.checked ? linkExtensionVariable : linkExtensionConstant);
      link.transition(t).attr("d", this.checked ? linkVariable : linkConstant);
    }

    function mouseovered (active) {
      return function (d) {
        d3.select(this).classed("label--active", active);
        d3.select(d.linkExtensionNode).classed("link-extension--active", active).each(moveToFront);
        do d3.select(d.linkNode).classed("link--active", active).each(moveToFront); while (d = d.parent);
      };
    }

    function moveToFront () {
      this.parentNode.appendChild(this);
    }
  });

  // Compute the maximum cumulative length of any node in the tree.
  function maxLength (d) {
    return d.data.length + (d.children ? d3.max(d.children, maxLength) : 0);
  }

  // Set the radius of each node by recursively summing and scaling the distance from the root.
  function setRadius (d, y0, k) {
    d.radius = (y0 += d.data.length) * k;
    if (d.children) d.children.forEach(function (d) { setRadius(d, y0, k); });
  }

  // Set the color of each node by recursively inheriting.
  function setColor (d) {
    var name = d.data.name;
    d.color = color.domain().indexOf(name) >= 0 ? color(name) : d.parent ? d.parent.color : null;
    if (d.children) d.children.forEach(setColor);
  }

  function linkVariable (d) {
    return linkStep(d.source.x, d.source.radius, d.target.x, d.target.radius);
  }

  function linkConstant (d) {
    return linkStep(d.source.x, d.source.y, d.target.x, d.target.y);
  }

  function linkExtensionVariable (d) {
    return linkStep(d.target.x, d.target.radius, d.target.x, innerRadius);
  }

  function linkExtensionConstant (d) {
    return linkStep(d.target.x, d.target.y, d.target.x, innerRadius);
  }

  // Like d3.svg.diagonal.radial, but with square corners.
  function linkStep (startAngle, startRadius, endAngle, endRadius) {
    // var c0 = Math.cos(startAngle = (startAngle - 90) / 180 * Math.PI),
    //     s0 = Math.sin(startAngle),
    //     c1 = Math.cos(endAngle = (endAngle - 90) / 180 * Math.PI),
    //     s1 = Math.sin(endAngle);
    // return "M" + startRadius * c0 + "," + startRadius * s0
    //     + (endAngle === startAngle ? "" : "A" + startRadius + "," + startRadius + " 0 0 " + (endAngle > startAngle ? 1 : 0) + " " + startRadius * c1 + "," + startRadius * s1)
    //     + "L" + endRadius * c1 + "," + endRadius * s1;
    return "M" + startRadius + "," + startAngle
      + (endAngle === startAngle ? "" : "L" + startRadius + "," + endAngle)
      + "L" + endRadius + "," + endAngle;


  }

</script>
阅读 1k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题