使用Javascript和D3进行DOM操作

[我想测试D3轴的产生,并且我想有一个带有示例列表的演示页面:每个示例都应该有标题,数据和结果。

因此,我创建了一个函数containerSetup(holder, title, dataset),该函数创建了每个示例的容器div,并为每个示例调用了此函数,如下所示:

function containerSetup(holder: any, title: string, dataset: any) {
  ...
}

containerSetup(root, 'Example-1', [
  new Date(2020, 11, 10, 22, 30),
  new Date(2020, 11, 10, 23, 0),
  new Date(2020, 11, 10, 23, 30),
  new Date(2020, 11, 11, 0, 0),
  new Date(2020, 11, 11, 0, 30),
  new Date(2020, 11, 11, 1, 0),
  new Date(2020, 11, 11, 1, 30),
])
containerSetup(root, 'Example-2', [
  new Date(2020, 11, 11, 0, 0),
  new Date(2020, 11, 11, 0, 30),
  new Date(2020, 11, 11, 1, 0),
  new Date(2020, 11, 11, 1, 30),
])

此方法有效,请检查整个代码:

function containerSetup(holder, title, dataset) {
  const { width, height } = dimensions;
  const domain = d3.extent(dataset);
  const range = [0, width - margins.left - margins.right];
  const scaleX = d3.scaleTime()
    .domain(domain)
    .range(range);
  const axisGenerator = d3.axisBottom(scaleX);

  const content = holder
    .append("div")
    .attr("class", `container`)
    .attr("id", `container-${title}`)
    .style("border", "1px solid black")
    .style("margin", "10px")
    .style("width", width);

  const titleContainer = holder
    .select(`#container-${title}`)
    .append("div")
    .attr("class", `title`)
    .attr("id", `title-${title}`)
    .style("border", "1px solid black")
    .style("background-color", "#fae0de")
    .html(title);

  const datasetContainer = holder
    .select(`#container-${title}`)
    .append("div")
    .attr("class", `dataset`)
    .attr("id", `dataset-${title}`)
    .style("border", "1px solid black")
    .style("background-color", "#efefef")
    .html(dataset);

  const axisContainer = holder
    .select(`#container-${title}`)
    .append("div")
    .attr("class", `dataset`)
    .attr("id", `dataset-${title}`)
    .style("border", "1px solid black")
    .style("background-color", "#defade")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", `translate(${margins.left}, ${margins.top})`)
    .append("g")
    .attr("width", width - margins.left - margins.right)
    .attr("height", height - margins.top - margins.bottom)
    .attr("transform", `translate(0, ${height - margins.top - margins.bottom})`)
    .call(axisGenerator);
}

////////////////////////

const root = d3.select("#app");
const dimensions = { width: 600, height: 50 };
const margins = { top: 20, right: 20, bottom: 20, left: 20 };

containerSetup(root, "Example-1", [
  new Date(2020, 11, 10, 22, 30),
  new Date(2020, 11, 10, 23, 0),
  new Date(2020, 11, 10, 23, 30),
  new Date(2020, 11, 11, 0, 0),
  new Date(2020, 11, 11, 0, 30),
  new Date(2020, 11, 11, 1, 0),
  new Date(2020, 11, 11, 1, 30)
]);
containerSetup(root, "Example-2", [
  new Date(2020, 11, 11, 0, 0),
  new Date(2020, 11, 11, 0, 30),
  new Date(2020, 11, 11, 1, 0),
  new Date(2020, 11, 11, 1, 30)
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div id="app"/>

我不喜欢代码的是containerSetup内容的复杂性。我不喜欢如何创建HTML DOM节点,我想在不使用React的情况下获得更简单,更简洁的内容,因为在这个简单的项目中这毫无意义。我尝试使用Hypescript,但它不支持SVG标签,因此即使创建具有某些样式的div并不容易,我还是返回纯Javascript。

然后,我希望具有不同的功能:一个用于示例容器设置,另一个用于创建svg轴节点,然后将该节点传递给将其附加到DOM的第一个函数。我该怎么办?

您有什么建议吗?

1
投票

您可以执行类似的操作:

  const { width, height } = dimensions
  const domain = extent(dataset)
  const range = [0, width - margins.left - margins.right]
  const scaleX = scaleTime().domain(domain).range(range)
  const axisGenerator = axisBottom(scaleX)

  const str = `
  <div class="container" id="container-${title}" style="border: 1px solid black; margin: 10px; width: 600px;">
    <div class="title" id="title-${title}" style="border: 1px solid black; background-color: rgb(250, 224, 222);">
      ${title}
    </div>

    <div class="dataset" id="dataset-${title}" style="border: 1px solid black; background-color: rgb(239, 239, 239);">
      ${dataset}
    </div>

    <div class="axis" id="axis-${title}" style="border: 1px solid black; background-color: rgb(222, 250, 222);">
    </div>
  </div>
`

  const child = holder.append('div').html(str);

  const axisContainer = holder.select(`#axis-${title}`)
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .append('g')
    .attr('transform', `translate(${margins.left}, ${margins.top})`)
    .append('g')
    .attr('width', width - margins.left - margins.right)
    .attr('height', height - margins.top - margins.bottom)
    .attr('transform', `translate(0, ${height - margins.top - margins.bottom})`)
    .call(axisGenerator)