首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将ObservableHq简单算法解释为可重用代码片段?

如何将ObservableHq简单算法解释为可重用代码片段?
EN

Stack Overflow用户
提问于 2020-03-20 10:35:52
回答 2查看 1.2K关注 0票数 7

D3js解决方案的主要来源是observableHq.com,但似乎不可能的 (?)通过复制/粘贴重用算法..。是吗?即使检查教程像这样,也没有简单的方式(有更少的插件或程序员的时间消耗!)检查和重用

示例:我需要一个用于缩进树可视化的新的2020 D3js v5算法,并且有一个很好的解决方案:WatableHq.com/@d3/缩进树

下载并不有用,因为它基于复杂的运行时类.

但是,看起来是一个简单的图表生成算法,

代码语言:javascript
复制
chart = {  // the indented-tree algorithm
  const nodes = root.descendants();
  const svg = d3.create("svg")// ...
  // ...
  return svg.node();
}

我是否可以通过简单的人工逐步将其转换成一个简单的HTML,没有复杂的适应性,从<script src="https://d3js.org/d3.v5.min.js"></script>开始,结束时不使用Runtime类?

更多细节为例

想象一下我一步一步的为引缩树算法,我不能完成,需要你的帮助:

假设从一个干净的HTML5模板开始。例如:

代码语言:javascript
复制
<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>Indented Tree</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script>
    function onLOAD() {
        console.log("Hello onLoad!")
        // all copy-paste and adaptations HERE.
        console.log("!Bye!")
    } // \onLOAD
    </script>
</head>
<body onload="onLOAD()">
  <script>
    console.log("Hello!")
    // global INITIALIZATIONS HERE.
  </script>
</body>
</html>
  1. 准备全局变量,似乎是rootnodeSize=17width
  2. 准备数据..。JSON数据位于丑陋的./files/e6537420...上,我用它的实名flare-2.json移到了项目的根目录。
  3. 简单而经典的D3js读取JSON数据的方法:d3.json("./flare-2.json").then( data=> console.log(data) ); 必须测试和检查无CORS错误等。
  4. 准备数据作为root变量。全部进入data => {}块以避免同步问题..。 看来root是基于function(d3,data) { let i = 0; return d3.hierarchy(data).eachBefore(d => d.index = i++); }的。
  5. 复制粘贴chart =以上引用,root后用数据进行统计.
  6. ..。

常见问题

评论问题和答案:

@Mehdi --你能解释一下在代码中包含D3脚本标记和使用运行时库的问题吗?

原始的ObservableHq算法很简单时,我需要另一种方法,通过复制/粘贴和最小的适应性,用简单的方法来重用它。

@Mehdi你读过https://observablehq.com/@observablehq/downloading-and-embedding-notebooks吗?

是的,没有新闻:没有关于如何重用代码的“人工指令”.只有“安装它”和“安装它”。没有我前面解释过的关于“复制/粘贴和最小适应”的说明。

(@没人)-你需要什么回答?

如前所述,一个简单的人类可读的逐步转换过程.理想情况下,通过测试,最终的结果可以证明,例如,它可以在JSFiddle上工作,并使用复制/粘贴代码和一些更多的适应行来显示您的观点。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-22 21:55:37

2020年11月编辑

现在可观察到有一个embed特性,此页中的详细信息。

原始员额

下面是一个逐步的过程,通过复制粘贴代码,并且不需要使用图书馆,将链接的可观察图表移植到一个自我托管的网页中。

从HTML页和HTML页中引用的JavaScript文件开始。假设web服务器正在运行并配置为合适的。

  1. 去拿数据。
  • 如果您想使用自己的数据而不是笔记本中使用的数据,请在web服务器上的目录中提供数据文件。
  • 否则,使用每个Download JSON单元格的菜单中的Download JSON链接,下载附加到笔记本的每个输入数据集。

  1. 使用d3-fetch加载页面中的每个数据集
代码语言:javascript
复制
d3.json("/path/to/data.json").then(function(data) {
  console.log(data); // [{"Hello": "world"}, …]
});
  1. 获取笔记本中包含变量或函数的每个单元格的内容,然后将其放入上一步的.then函数中。这个笔记本形象化器工具可以帮助识别相关的单元格。
  2. 适当地修改刚刚复制的函数的语法。例如,以下笔记本单元:
代码语言:javascript
复制
root = { let i = 0; return d3.hierarchy(data).eachBefore(d => d.index = i++); }

可转化为:

代码语言:javascript
复制
function getRoot(){
   let i = 0;
    return d3.hierarchy(data).eachBefore(d => d.index = i++);
}

root = getRoot()
  1. 如果笔记本中的某个函数需要,定义一个变量width,并用所需的值初始化它。
  2. 调整DOM操作代码,以便将元素附加到DOM中,而不是依赖可观察运行时的隐式执行。

下面片段中的演示:

代码语言:javascript
复制
d3.json("https://rawcdn.githack.com/d3/d3-hierarchy/46f9e8bf1a5a55e94c40158c23025f405adf0be5/test/data/flare.json").then(function(data) {

  const width = 800
    , nodeSize = 17
    , format = d3.format(",")
    , getRoot = function(){
       let i = 0;
        return d3.hierarchy(data).eachBefore(d => d.index = i++);
    }
    , columns = [
      {
        label: "Size", 
        value: d => d.value, 
        format, 
        x: 280
      },
      {
        label: "Count", 
        value: d => d.children ? 0 : 1, 
        format: (value, d) => d.children ? format(value) : "-", 
        x: 340
      }
    ]
    , root = getRoot()
    , chart = function() {
      const nodes = root.descendants();

      const svg = d3.select('#chart')
          .attr("viewBox", [-nodeSize / 2, -nodeSize * 3 / 2, width, (nodes.length + 1) * nodeSize])
          .attr("font-family", "sans-serif")
          .attr("font-size", 10)
          .style("overflow", "visible");


  const link = svg.append("g")
      .attr("fill", "none")
      .attr("stroke", "#999")
    .selectAll("path")
    .data(root.links())
    .join("path")
      .attr("d", d => `
        M${d.source.depth * nodeSize},${d.source.index * nodeSize}
        V${d.target.index * nodeSize}
        h${nodeSize}
      `);

      const node = svg.append("g")
        .selectAll("g")
        .data(nodes)
        .join("g")
          .attr("transform", d => `translate(0,${d.index * nodeSize})`);

      node.append("circle")
          .attr("cx", d => d.depth * nodeSize)
          .attr("r", 2.5)
          .attr("fill", d => d.children ? null : "#999");

      node.append("text")
          .attr("dy", "0.32em")
          .attr("x", d => d.depth * nodeSize + 6)
          .text(d => d.data.name);

      node.append("title")
          .text(d => d.ancestors().reverse().map(d => d.data.name).join("/"));

      for (const {label, value, format, x} of columns) {
        svg.append("text")
            .attr("dy", "0.32em")
            .attr("y", -nodeSize)
            .attr("x", x)
            .attr("text-anchor", "end")
            .attr("font-weight", "bold")
            .text(label);

        node.append("text")
            .attr("dy", "0.32em")
            .attr("x", x)
            .attr("text-anchor", "end")
            .attr("fill", d => d.children ? null : "#555")
          .data(root.copy().sum(value).descendants())
            .text(d => format(d.value, d));
      }

  }

  chart()
    
}).catch(function(err) {
  console.log('error processing data', err)
})
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>
<svg id = 'chart'></svg>

票数 8
EN

Stack Overflow用户

发布于 2020-03-23 21:30:44

最简单的方法是使用它们的运行时嵌入版本。下面是在HTML5模板中重用笔记本的一种非常类似的方法。

您还可以下载运行时和笔记本js,以便在服务器上托管。

这里的诀窍是使用运行时与可观察的反应性细胞对话。

在本例中,我使用d3.json获取新的json数据,并从原始data重新定义记事本单元。

代码语言:javascript
复制
<div id="observablehq-e970adfb"></div>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script type="module">

//Import Observable Runtime

import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
import define from "https://api.observablehq.com/@d3/indented-tree.js?v=3";
const inspect = Inspector.into("#observablehq-e970adfb");

// Notebook instance
const notebook =(new Runtime).module(define, name => (name === "chart") && inspect());


// Using D3.json to load new Json Data

d3.json("https://gist.githubusercontent.com/radames/9018398d6e63bcaae86a0bf125dc6973/raw/33f19a49e1123a36e172cfc7483f0a444caf6ae3/newdata.json").then((newdata) =>{
  
  // When data is loaded you can use notebook to redefine a cell
  // In this case the data cell, where in the notebook it's using a FileAtachent
  // Here you can redefine with any structure hierarchy structure like
  
  notebook.redefine("data", newdata);
})


</script>

编辑以使用 西韦罗项目添加步骤

使用Severo's笔记本视觉器,您可以理解笔记本的数据流并重写独立代码。请记住,从头开始重写可能会变得非常复杂,因为您的代码使用了可观察的特性,例如反应性和状态管理。在这种情况下,我建议您按照上面的响应使用可观察的运行时。

现在,考虑到这一点,让我们看看可视化器,然后遵循西韦罗(氏)

  • 绿色单元格对应于导入到笔记本中的外部代码:随需要导入的库(例如d3 =d3(“d3@5”)):您通常会在项目中安装 然后将其导入为ES模块导入笔记本(例如,从“@jashkenas/input”导入{ radio }):您必须在 这个笔记本,检查它自己的依赖图。
  • 灰色细胞是匿名的(未命名的)细胞,一般不会被迁移.它们通常包含解释文本,没有其他单元格可以依赖它们,因此如果 已删除。但是,要小心:如果您的主图表单元格未命名,则 仍然希望复制它的代码。
  • Black cells是用户编写的实际笔记本代码,您将希望将其复制到项目中。
  • 紫细胞是最坚韧的。它们对应于笔记本编写器(参见标准库)通常经常使用的可观察到的功能,它们向独立应用程序的迁移可能是从头开始重写过程中最困难的部分,尤其是可变的单元格和查看单元格,因为它们管理内部状态。

下面是按照以下说明转换的代码

代码语言:javascript
复制
<!--- Green Cells / Imports --->
<script src="https://d3js.org/d3.v5.min.js"></script>

<!--- Char Container --->

<div class="chart"></div>
<script>
  // Run main function
  main();

  // async main so we can run our code like Observable cell by cell
  async function main() {
    // as in Observable each cell runs as an async function
    // so here you can await the output to continue
    const data = await d3.json("https://gist.githubusercontent.com/radames/9018398d6e63bcaae86a0bf125dc6973/raw/33f19a49e1123a36e172cfc7483f0a444caf6ae3/newdata.json");

    // run complex code as inline await / async
    const root = await (async() => {
      let i = 0;
      return d3.hierarchy(data).eachBefore(d => d.index = i++);
    })()

    // easy constant
    const nodeSize = 17;

    // easy constant function
    const format = d3.format(",");

    // easy constant
    const columns = [{
        label: "Size",
        value: d => d.value,
        format,
        x: 280
      },
      {
        label: "Count",
        value: d => d.children ? 0 : 1,
        format: (value, d) => d.children ? format(value) : "-",
        x: 340
      }
    ];
    // on Observable width is reactive, here we have to do it manually
    const width = window.innerHTML;

    window.addEventListener('resize', updateWidth);

    function updateWidth() {
      // update your chart on resize event
    }
    // inline function gets chart svg node
    const chart = (() => {
      const nodes = root.descendants();

      const svg = d3.create("svg")
        .attr("viewBox", [-nodeSize / 2, -nodeSize * 3 / 2, width, (nodes.length + 1) * nodeSize])
        .attr("font-family", "sans-serif")
        .attr("font-size", 10)
        .style("overflow", "visible");

      const link = svg.append("g")
        .attr("fill", "none")
        .attr("stroke", "#999")
        .selectAll("path")
        .data(root.links())
        .join("path")
        .attr("d", d => `
          M${d.source.depth * nodeSize},${d.source.index * nodeSize}
          V${d.target.index * nodeSize}
          h${nodeSize}
        `);

      const node = svg.append("g")
        .selectAll("g")
        .data(nodes)
        .join("g")
        .attr("transform", d => `translate(0,${d.index * nodeSize})`);

      node.append("circle")
        .attr("cx", d => d.depth * nodeSize)
        .attr("r", 2.5)
        .attr("fill", d => d.children ? null : "#999");

      node.append("text")
        .attr("dy", "0.32em")
        .attr("x", d => d.depth * nodeSize + 6)
        .text(d => d.data.name);

      node.append("title")
        .text(d => d.ancestors().reverse().map(d => d.data.name).join("/"));

      for (const {
          label,
          value,
          format,
          x
        } of columns) {
        svg.append("text")
          .attr("dy", "0.32em")
          .attr("y", -nodeSize)
          .attr("x", x)
          .attr("text-anchor", "end")
          .attr("font-weight", "bold")
          .text(label);

        node.append("text")
          .attr("dy", "0.32em")
          .attr("x", x)
          .attr("text-anchor", "end")
          .attr("fill", d => d.children ? null : "#555")
          .data(root.copy().sum(value).descendants())
          .text(d => format(d.value, d));
      }

      return svg.node();
    })()

    // select element container append chart
    const container = document.querySelector(".chart")
    container.appendChild(chart);

  }
</script>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60772491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档