如何在页面上将小倍数的子组放置在一起?

oym*_*onk 6 html javascript d3.js

我有一个数据集,CategoryLevel1其中包含一个名为组的名称的列。我将nest函数应用于Categorylevel1并基于键生成了一系列svg。然后,我创建了代表整个数据集中项目的矩形,并在每个svg中重复了这些矩形。我对每个svg应用了一个过滤器,因此只能看到带有该svg键的数据集项。

我的真实数据集大于此处表示的玩具数据集。上面代码的结果是svgs的网页很长-非常混乱。为了使事情更清楚,我希望将svgs根据称为的列进行分组CategoryLevel2。这是我追求的效果:

在此处输入图片说明

这是我到目前为止的内容:

var doc = `Manual	Name	CategoryLevel1	CategoryLevel2
DOG	"General Furry, Program and Subject Files"	Average Quantity and Planning	Edibles
TR	Senate Committee on animal Standards	Bowl and Plate Design	Edibles
TR	Published Canine	Bowl and Plate Design	Edibles
TR	Canine case files	Bowl and Plate Design	Edibles
DOG	Canine Files 	Avoiding Neck Strain	Edibles
DOG	Canine Files 	Drooling	Edibles
DOG	Canine Files 	Drooling	Edibles
DG	ADVERTISING	At home	At home
DG	PROMOTIONS	At home	At home
DG3	Publications	At home	At home
TR	Public and Information Services	At home	At home
TR	Petting Services	Getting special treats	At home
TR	Petting Services	Getting special treats	At home
TR	Petting Services	Getting special treats	At home
TR	Petting Services	Getting special treats	At home
TR	Petting Services	Getting special treats	At home
TR	Petting Services	Getting special treats	At home
DG	DEVELOPMENT	Optimal time of day - walking	Walks and outings
DG	INCOME AND REVENUE	Optimal time of day - walking	Walks and outings
TR	Fundraising	Optimal time of day - walking	Walks and outings
TR	Fundraising	Optimal time of day - walking	Walks and outings
DG	DEVELOPMENT	Optimal time of day - walking	Walks and outings
DG	INCOME AND REVENUE	Optimal time of day - walking	Walks and outings
TR	Wishbone	Protective Measures	Walks and outings
TR	Wishbone	Protective Measures	Walks and outings
DG	Wishbone	Observant of Limps Etc	Walks and outings
DOG	Wishbone	Observant of Limps Etc	Walks and outings
TR	Wishbone	Observant of Limps Etc	Walks and outings`;

const data = d3.tsvParse(doc, function(d) {
  return {
    Manual: d.Manual,
    Name: d.Name,
    CategoryLevel1: d.CategoryLevel1,
    CategoryLevel2: d.CategoryLevel2
  };
});


var nest = d3.nest()
  .key(function(d) {
    return d.CategoryLevel1;
  })
  .entries(data);

var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0)

var height = 100,
  width = 300;

var color = d3.scaleOrdinal(["#edf8fb", "#b3cde3", "#8c96c6", "#88419d"]);

/* var svg = d3.select("body").append("svg").attr("height", "100%").attr("width", "100%");

var g = d3.select("svg").attr("height", "100%").attr("width", "100%"); */



var svgs = d3.select("body")
  .selectAll("svg")
  .data(nest)
  .enter()
  .append('svg')
  .attr("width", width)
  .attr("height", height + 20);

svgs.append("text")
  .attr('class', 'label')
  .data(nest)
  .attr('x', width / 2)
  .attr('y', height)
  .text(function(d) {
    return d.key;
  })
  .attr('text-anchor', 'middle')

svgs.selectAll("rect")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .filter(function(d, i) {
    const x = d3.select(this.parentNode).datum();
    return x.key == d.CategoryLevel1 ? 1 : 0;
  })
  .attr("height", function(d) {
    return 50;
  })
  .attr("width", "5")
  .attr("x", function(d, i) {
    return i * 10;
  })
  .attr("y", 0)

  .attr("fill", function(d) {
    return color(d.Manual)
  })

  .on("mouseover", function(d, i) {
    div.transition()
      .duration(200)
      .style("opacity", .9);
    div.html(`${d.Name}`)
      .style("left", (d3.event.pageX) + "px")
      .style("top", (d3.event.pageY - 50) + "px");
  })
  .on("mouseout", function(d) {
    div.transition()
      .duration(500)
      .style("opacity", 0);
  });
Run Code Online (Sandbox Code Playgroud)
.page {
  width: 90%;
  margin: auto;
}

.menu {
  height: 100px;
  background-color: #B2D6FF;
  /* Medium blue */
}

.sidebar {
  height: 50px;
  width: 15%;
  background-color: #F09A9D;
  float: inline-start;
  display: block;
  margin: 0.1%;
  /* Red */
}

.title {
  width: 100%;
  background-color: none;
  display: inline-block;
  float: inline-start;
  /* Yellow */
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: auto;
  height: auto;
  padding: 3px;
  font: 12px sans-serif;
  border: 0px;
  border-radius: 3px;
  pointer-events: none;
  background: lightgrey;
}
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Mapping Dog Care Manuals</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
</head>


</html>
Run Code Online (Sandbox Code Playgroud)

我尝试过的

我尝试创建表示CategoryLevel2的svg,然后附加“ innerSVG”并运行将生成CategoryLevel1 svgs的代码。问题出在过滤器行中-它无法访问CategoryLevel1的正确父级:

.filter(function(d, i) {
    const x = d3.select(this.parentNode).datum();
    return x.key == d.CategoryLevel1 ? 1 : 0;
  })
Run Code Online (Sandbox Code Playgroud)

我还尝试使用“转换,转换”功能基于Categorylevel1分隔矩形,但是拒绝了此操作,因为移动与CategoryLevel1相关联的文本会很棘手。

我现在正在尝试使用d3.hierarchy布局之一。问题是,一旦我将d3.stratify应用于数据集,结果就无法用于生成一系列svg。也就是说,应用以下代码后,DOM中什么都不会显示:(仅供参考,我还用root.descendants()等替换了treeData,

var treeData = d3.stratify()
  .id(function(d) { return d.CategoryLevel1; })
  .parentId(function(d) { return d.CategoryLevel2; })
  (data);

  var svgs = d3.select("chart")
    .selectAll("svg")
    .data(treeData)
    .enter()
    .append('svg')
    .attr("width", width)
    .attr("height", height + 20);
Run Code Online (Sandbox Code Playgroud)

Ger*_*ado 3

这里缺少一个重要信息:您没有告诉我们您要如何分隔CategoryLevel2组:在同一行中?在同一列?还有其他模式吗?

因此,在我的解决方案中,我将使用一个容器<div>display: flex组分成 3,每个值对应一个组CategoryLevel2(分别是Edibles, At Home Walks and outings)。

CategoryLevel2只需使用嵌套函数中的第一个键即可完成此操作:

var nest = d3.nest()
  .key(function(d) {
    return d.CategoryLevel2;
  })
  .key(function(d) {
    return d.CategoryLevel1;
  })
  .entries(data);
Run Code Online (Sandbox Code Playgroud)

这将创建以下数组:

[{key: "Edibles", values: Array},
 {key: "At home", values: Array},
 {key: "Walks and outings", values: Array}];
Run Code Online (Sandbox Code Playgroud)

在每个values值中,您将拥有原始的巢,例如:

{
    "key": "Edibles",
    "values": [{
        "key": "Average Quantity and Planning",
        "values": [
            //etc...
        ]
    }, {
        "key": "Bowl and Plate Design",
        "values": [
            //etc..
        ]
    }, {
        "key": "Avoiding Neck Strain",
        "values": [
            //etc...
        ]
    }, {
        "key": "Drooling",
        "values": [
            //etc
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)

然后使用嵌套数据附加 div:

var divs = d3.select(".container")
  .selectAll(null)
  .data(nest)
  .enter()
  .append("div")
  .attr("class", "innerdiv");
Run Code Online (Sandbox Code Playgroud)

当然,不要忘记将内部数组用于真正的 SVG:

var svgs = divs.selectAll(null)
  .data(function(d) {
    return d.values;
  })
  .enter()
  //etc...
Run Code Online (Sandbox Code Playgroud)

以下是经过这些更改的代码:

var nest = d3.nest()
  .key(function(d) {
    return d.CategoryLevel2;
  })
  .key(function(d) {
    return d.CategoryLevel1;
  })
  .entries(data);
Run Code Online (Sandbox Code Playgroud)
[{key: "Edibles", values: Array},
 {key: "At home", values: Array},
 {key: "Walks and outings", values: Array}];
Run Code Online (Sandbox Code Playgroud)
{
    "key": "Edibles",
    "values": [{
        "key": "Average Quantity and Planning",
        "values": [
            //etc...
        ]
    }, {
        "key": "Bowl and Plate Design",
        "values": [
            //etc..
        ]
    }, {
        "key": "Avoiding Neck Strain",
        "values": [
            //etc...
        ]
    }, {
        "key": "Drooling",
        "values": [
            //etc
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)