2016-05-09 20 views
2

これはJSの一般的な質問ではありません。 ScalaJSのヘルプが本当に必要です。ScalaJSを使用してJSONからD3ツリーを作成する

私は数日間、単純な接続ツリーグラフを描こうとしています。それは任意に深く入れ子にすることができます。私は、このファイルを読み込む:

{ 
    "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

+1

あなたはここに多くのコードを持っています。エラーを表示させるために必要なビットまで最小化できますか?これは通常、このような不思議なものをデバッグするための第一歩です... –

+0

@JustinduCoeurどちらが正しい答えに近いかわからないので、私は両方の試みを含めました。私はそれをカットしてうれしいですが、私は動的オプションまたはAnimalNodeオプションを削除する必要がありますか? –

+1

必ずしも問題ではありません。無駄なことではありません。「これはうまくいくと思いますが、エラーを出す」と説明するだけです。余分な行はありません。裸の骨にデータ構造をカットし、1つの経路にカットし、カット、カット、カットします。それはエラーを最小限にする心臓部であり、誰かの注意を引くためにはしばしば必要です。 (そして、しばしば、そうするプロセスが問題がどこにあるか明らかにする) –

答えて

1

Scala.jsラッパー・ライブラリー恐れ。リンクのランタイム・タイプは実際にはラッパーのシグニチャーにマップされないため、.attr("d", (myJson: Link[Node], x: Int, y: js.UndefOr[Int]) => { ... }で失敗します。これは、js.nativeファンクションを介してd3によって作成されるためです。 Scala.jsがプレーンなJSオブジェクトをリンクにキャストできないため、ClassCastExceptionがスローされます。あなたはこれを回避することができます

https://github.com/spaced/scala-js-d3/blob/master/src/main/scala/org/singlespaced/d3js/svg.scala:ラッパーで

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]) 
}) 

もう一つの問題は、投影が部分的にしか実装されていることで、あなたは本当にTODO Sを参照してください(今、あなた自身のリンクの投影を作成カント)。

はたぶん行は、あなたのユースケースのために十分に優れている、私はあなたの例に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") 
    } 
    ) 
    } 


} 
関連する問題