-
Notifications
You must be signed in to change notification settings - Fork 28
Use types for layout.force[...]() #6
Comments
Tnx for your input. On the other side, are there any use cases where it make sense to use a typed |
I tried to re-impement the example: http://bl.ocks.org/mbostock/1095795 The arrays ! Updated code - 2015-11-30 import scala.scalajs.js
import scala.scalajs.js._
import scala.scalajs.js.timers.setTimeout
import org.scalajs.dom
import org.singlespaced.d3js._
import org.singlespaced.d3js.Ops._
import org.singlespaced.d3js.forceModule
import org.singlespaced.d3js.forceModule.Event
import scala.language.implicitConversions
object ForceLayoutExample extends JSApp {
trait Node extends forceModule.Node {
var id: String
}
object Node {
def apply(id: String): Node = {
val n = new js.Object().asInstanceOf[Node]
n.id = id
n
}
}
type Link = forceModule.Link[Node]
object Link {
def apply(x: Node, y: Node): Link = {
val l = new js.Object().asInstanceOf[Link]
l.source = x
l.target = y
l
}
}
def main(): Unit = {
val width = 960
val height = 500
val color = d3.scale.category10()
// node, link will be initialized in the start() function
var node: selection.Update[Node] = null
var link: selection.Update[Link] = null
def tick(e: Event): Unit = {
node.attr("cx", (d: Node) => d.x)
.attr("cy", (d: Node) => d.y)
link.attr("x1", (d: Link) => d.source.x)
.attr("y1", (d: Link) => d.source.y)
.attr("x2", (d: Link) => d.target.x)
.attr("y2", (d: Link) => d.target.y)
}
val nodes = Array[Node]()
val links = Array[Link]()
val force = d3.layout.force[Node, Link]()
.nodes(nodes)
.links(links)
.charge(-400)
.linkDistance(120)
.size(Tuple2(width, height))
.on("tick", tick _)
val svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
// 1. Add three nodes and three links.
setTimeout(0) {
val a = Node("a")
val b = Node("b")
val c = Node("c")
nodes.push(a, b, c);
links.push(Link(a, b), Link(a, c), Link(b, c))
start();
}
// 2. Remove node B and associated links.
setTimeout(3000) {
nodes.splice(1, 1); // remove b
links.shift(); // remove a-b
links.pop(); // remove b-c
start();
}
// Add node B back
setTimeout(6000) {
val a = nodes(0)
val b = Node("b")
val c = nodes(1)
nodes.push(b);
links.push(Link(a, b), Link(b, c))
start();
}
def start() = {
link = svg.selectAll[Link](".link")
.data(force.links(), (d: Link, i: Int) => d.source.id + "-" + d.target.id)
link.enter().insert("line", ".node").attr("class", "link")
link.exit().remove()
node = svg.selectAll[Node](".node")
.data(force.nodes(), (d: Node, i: Int) => d.id)
node.enter().append("circle")
.attr("class", (d: Node) => "node " + d.id)
.attr("r", 8)
node.exit().remove()
force.start()
}
}
} |
Sorry, it was not my intention to close it; as it still not clear how to implement the above example. I pressed the wrong button. |
with switching order of Nodes and Links works:
because of scala Still not so happy with sub classing Nodes and Links because it does not allow to add additional code to it, because of In native JS types, all concrete definitions must have = js.native as body. I may think about . So this can change in future (see also |
Im not sure if this fix catches all parts, but it should handle major part, otherwise reopen or create a new one ;-) |
I had a look to the TODO's to support more typed functions, e.g. to created a custom typed layout.Force.
You may encounter issues with mutable typed classes, which you can't make co-variant, such as e.g. Link[Node].
The following approach may help:
The text was updated successfully, but these errors were encountered: