使用ScalaJS从JSON创建D3树

比尔·弗雷格斯

请注意,这不是一个简单的JS问题。我真的需要ScalaJS帮助。

我一直试图绘制一个简单的,连接的树图已有几天了。它可以任意嵌套在较深的位置。我读了这个文件:

{
  "name": "Animal",
  "children": [
    {
      "name": "Vertebrates",
      "children": [
        {
          "name": "Mammals"
        },
        {
          "name": "Birds"
        }
      ]
    },
    {
      "name": "Invertebrates"
    }
  ]
}

当我运行该程序时:

package example
import scala.scalajs.js
import org.singlespaced.d3js.{Link, Tree, d3}

@js.native
trait AnimalNode extends js.Object {
  val name: String = js.native
  val children: js.Array[AnimalNode] = js.native
}

object ScalaJSExample extends js.JSApp {
  def main(): Unit =
    d3.json("json-example.json", (error: js.Any, json: js.Any) => {
      val jsonTypedFromFile = json.asInstanceOf[AnimalNode]

      val width = 960.0
      val height = 500.0

      val tree: Tree[AnimalNode] = d3.layout.tree().size((width, height))
      val nodes = tree.nodes(jsonTypedFromFile)
      val links = tree.links(nodes)

      val svg = d3.select("#tree").append("svg")
        .attr("width", width).attr("height", height).append("g")
      val diagonal = d3.svg.diagonal() //Want to draw Diagonals across all links.

      svg.data(links)
        .append("path")
        .attr("class", "link")
        .style("stroke-width", 5)
        .attr("d", (myJson: Link[AnimalNode], x: Int, y: js.UndefOr[Int]) => {
          ??? // TODO: Draw Diagonal between source & target. Never reached.
        })
      println("Finished drawing paths.")
    })
}

我在Firebug中收到此错误:

uncaught exception: 
scala.scalajs.runtime.UndefinedBehaviorError:
An undefined behavior was detected: 
    [object Object] is not an instance of org.singlespaced.d3js.Link

我可能需要定位的替代签名是:

.attr("d", (myJson: Link[Node], x: Int, y: js.UndefOr[Int]) => { ... }

我的代码是ScalaJSD3示例应用程序的分支,可在以下位置找到:https : //github.com/swoogles/scala-js-d3-example-app

它的灵感来自此处的纯Javascript代码:http//bl.ocks.org/d3noob/8375092

有氧的

恐怕Scala.js包装器库有些错误且不完整。.attr("d", (myJson: Link[Node], x: Int, y: js.UndefOr[Int]) => { ... }之所以失败,是因为链接的运行时类型实际上并未映射到包装器的签名,因为它们是由d3通过js.native函数创建的ClassCastException然后抛出A,因为Scala.js无法将普通的JS对象转换为Links。

您可以解决此问题:

val untypedLinks: js.Array[_ <: Any] = animalNodeTree.links(animalNodes)
val animalNodeLinks = untypedLinks.map(link => {
  val linkObj = link.asInstanceOf[js.Dynamic]
  SimpleLink(linkObj.source.asInstanceOf[AnimalNode], linkObj.target.asInstanceOf[AnimalNode])
})

包装器的另一个问题是投影仅部分实现,您现在不能真正为自己的链接创建投影(请参阅TODOs:https : //github.com/spaced/scala-js-d3/blob/master /src/main/scala/org/singlespaced/d3js/svg.scala)。

也许Lines对您的用例足够好,我将http://www.d3noob.org/2014/01/tree-diagrams-in-d3js_11.html中的示例改编为您的示例:

package example

import bill.d3.TreeData
import scala.scalajs.js
import scala.scalajs.js.Dynamic
import org.singlespaced.d3js.{Link, Tree, d3, SimpleLink}
import org.singlespaced.d3js.d3.Primitive
import scala.util.Try
import scala.collection.mutable
import js.JSConverters._

@js.native
trait AnimalNode extends js.Object {
  var id: js.UndefOr[Int] = js.native
  var x: js.UndefOr[Int] = js.native
  var y: js.UndefOr[Int] = js.native
  var depth: Int = js.native
  val parent: String = js.native
  val name: String = js.native
  val children: js.Array[AnimalNode] = js.native
}

object ScalaJSExample extends js.JSApp with TreeData {

  def main(): Unit = {
    println(Try {
      drawTree
    })
  }

  def drawTree = {
    d3.json("json-example.json", (error: js.Any, json: js.Any) => {

      val jsonTypedFromFile = json.asInstanceOf[AnimalNode]

      val width = 960.0
      val height = 650.0
      val marginLeft = 0.0
      val marginTop = 30.0

      val svg = d3.select("#tree").append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + marginLeft + "," + marginTop + ")")

      val tupledDimensions = (width, height)

      val animalNodeTree: Tree[AnimalNode] = d3.layout.tree().size(tupledDimensions)
      val animalNodes: js.Array[AnimalNode] = animalNodeTree.nodes(jsonTypedFromFile)
      val untypedLinks: js.Array[_ <: Any] = animalNodeTree.links(animalNodes)

      val animalNodeLinks = untypedLinks.map(link => {
        val linkObj = link.asInstanceOf[js.Dynamic]
        SimpleLink(linkObj.source.asInstanceOf[AnimalNode], linkObj.target.asInstanceOf[AnimalNode])
      })

      // Normalize for fixed-depth.
      animalNodes.foreach((node: AnimalNode) => {
        node.y = node.depth * 180
        println(node.y)
      })

      var nodeCount: Int = 0

      val node: org.singlespaced.d3js.selection.Update[AnimalNode] = svg.selectAll("g.node").data(animalNodes, (node: AnimalNode, index: Int) => {
          nodeCount += 1
          node.id = nodeCount
          node.id.toString
      })

      val nodeEnter: org.singlespaced.d3js.selection.Enter[AnimalNode] = node.enter()

      val nodeWithPosition = nodeEnter.append("g")
       .attr("class", "node")
       .attr("transform", (animalNode: AnimalNode, x: Int, y: js.UndefOr[Int]) => {
         println(animalNode.id)
         "translate(" + animalNode.x + "," + animalNode.y + ")": Primitive
        })

      nodeWithPosition.append("circle")
       .attr("r", 10)
       .style("fill", "#fff")

      nodeWithPosition.append("text")
       .attr("x", 13)
       .attr("dy", ".35em")
       .attr("text-anchor", "start")
       .text((node: AnimalNode, x: Int, y: js.UndefOr[Int]) => {
          node.name
       })
       .style("fill-opacity", 1)

       val link = svg.selectAll("g.link")
       .data(animalNodeLinks, (link: SimpleLink[AnimalNode], index: Int) => { "" + link.target.id })

      link.enter().insert("line", "g")
       .attr("class", "link")
       .attr("x1", (node: SimpleLink[AnimalNode], x: Int, y: js.UndefOr[Int]) => {
          "" + node.source.x.getOrElse(0.0) : Primitive
        })
       .attr("y1", (node: SimpleLink[AnimalNode], x: Int, y: js.UndefOr[Int]) => {
          "" + node.source.y.getOrElse(0.0) : Primitive
        })
       .attr("x2", (node: SimpleLink[AnimalNode], x: Int, y: js.UndefOr[Int]) => {
          "" + node.target.x.getOrElse(0.0) : Primitive
        })
       .attr("y2", (node: SimpleLink[AnimalNode], x: Int, y: js.UndefOr[Int]) => {
          "" + node.target.y.getOrElse(0.0) : Primitive
        })

      println("Done")
    }
    )
  }


}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用ScalaJS从JSON创建D3树

来自分类Dev

json的D3树布局

来自分类Dev

使用Python创建D3嵌套JSON数据

来自分类Dev

D3树定向

来自分类Dev

d3从JSON路径创建svg

来自分类Dev

使用我创建的带有可折叠树的Json的d3.js flare.json

来自分类Dev

在D3树布局中使用多种链接类型

来自分类Dev

使用d3在树中添加列表或垂直tspan

来自分类Dev

使用D3绕过JSON

来自分类Dev

如何从节点和链接列表创建d3径向树?

来自分类Dev

从具有切换节点的D3树布局创建jsTree

来自分类Dev

带链接的D3树图

来自分类Dev

D3布局树未渲染

来自分类Dev

d3树加入单身儿童

来自分类Dev

垂直翻转 D3 树图

来自分类Dev

D3 - 从 JSON 创建功能集

来自分类Dev

没有flare.json的D3可折叠树

来自分类Dev

如何使用React创建d3力布局图

来自分类Dev

使用d3中的数据绑定创建轴

来自分类Dev

使用D3为气泡图创建图例

来自分类Dev

使用D3创建多层饼图

来自分类Dev

使用D3创建动画的脉冲圆

来自分类Dev

从html创建数组以使用D3 Wordcloud显示

来自分类Dev

使用D3创建世界Choropleth地图

来自分类Dev

尝试使用 D3 创建地图,但未显示

来自分类Dev

d3:使用 DataMaps 创建美国地图

来自分类Dev

如何在VEGA Api中使用D3树数据?

来自分类Dev

使用foreignObjects将节点的文本包装在D3树中

来自分类Dev

D3树图-使用直线而不是对角线时如何过渡链接