Skip to content
This repository has been archived by the owner on Apr 17, 2022. It is now read-only.

svg.line, line.x, line.y #7

Closed
daenenk opened this issue Nov 30, 2015 · 5 comments
Closed

svg.line, line.x, line.y #7

daenenk opened this issue Nov 30, 2015 · 5 comments

Comments

@daenenk
Copy link

daenenk commented Nov 30, 2015

I re-implemented http://bl.ocks.org/d3noob/b3ff6ae1c120eea654b5
To do this I had to apply following changes in svg.scala:

def line[Datum](): Line[Datum] = js.native
    . . .
trait Line[T] extends js.Object {
   . . .
  def x[Datum >: T](x: js.Function1[Datum, Double]): Line[T] = js.native
  def y[Datum >: T](y: js.Function1[Datum, Double]): Line[T] = js.native
  . . .
}

The example

import scala.scalajs.js
import scala.scalajs.js._
import org.scalajs.dom

import org.singlespaced.d3js.Ops._
import org.singlespaced.d3js.d3

object LineGraphExample extends JSApp {

  trait Data {
    var date: Date
    var close: Double
  }

  def main(): Unit = {

    object margin {
      val top = 30
      val right = 20
      val bottom = 30
      val left = 50
    }

    val width = 600 - margin.left - margin.right
    val height = 270 - margin.top - margin.bottom

    val parseDate = d3.time.format("%d-%b-%y").parse(_)

    val x = d3.time.scale().range(Array(0, width))
    val y = d3.scale.linear().range(Array(height, 0))

    val xAxis = d3.svg.axis().scale(x)
      .orient("bottom").ticks(5)
    val yAxis = d3.svg.axis().scale(y)
      .orient("left").ticks(5)

    val valueline = d3.svg.line[Data]() 
      .x { (d: Data) => x(d.date) }
      .y { (d: Data) => y(d.close) }

    val svg = d3.select("body")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")")

    d3.csv("data.csv", { (error: Any, rawdata: Array[Dictionary[String]]) =>

      val data: Array[Data] = rawdata.map { record =>
        object d extends Data {
          var date = parseDate(record("date"))
          var close = record("close").toDouble
        }
        d
      }

      val Tuple2(minx, maxx) = d3.extent(data.map(_.date))
      x.domain(Array(minx, maxx))

      val maxy = d3.max(data.map(_.close))
      y.domain(Array(0, maxy))

      svg.append("path")
        .attr("class", "line")
        .attr("d", valueline(data))

      svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis)

      svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)

      ()
    })
  }
}
@spaced
Copy link
Owner

spaced commented Nov 30, 2015

https://github.com/mbostock/d3/wiki/SVG-Shapes#_line wrote

The function is passed two arguments, the current datum (d) and the current index (i)

so i will change it to

  def x[Datum >: T](x: js.Function1[Datum, Int, Double]): Line[T] = js.native

ok?
then you can write

.x { (d: Data,i:Int) => x(d.date) }

@spaced spaced closed this as completed in 630b6f7 Nov 30, 2015
@daenenk
Copy link
Author

daenenk commented Dec 1, 2015

Thx for the update. Makes it possible to implement the example now.
Note that it should be possible to define both

  def x[Datum >: T](x: js.Function2[Datum, Int, Double]): Line[T] = js.native
  def x[Datum >: T](x: js.Function1[Datum, Double]): Line[T] = js.native

for a native trait, see http://www.scala-js.org/doc/interoperability/facade-types.html

Methods can be overloaded. This is useful to type accurately some APIs that behave differently depending on the number or types of arguments.

@spaced
Copy link
Owner

spaced commented Dec 2, 2015

Instead of tons of overloading i declare (an other) implicit for it
See Issue #10

@evan-wehi
Copy link

I'm trying to do something very similar to this and have been using this example as a guide. However, this example does not compile. Specifically, the line .attr("d", valueline(data)) (approx line 69) produces:

type mismatch; found : scala.scalajs.js.Array[view.graphs.LineGraphExample.Data] required: view.graphs.LineGraphExample.Data

I'm not a very experience scala developer and this is driving me nuts so any help would be greatly appreciated.

@evan-wehi
Copy link

evan-wehi commented May 9, 2017

I eventually solved this. It should be

    svg.append("path")
      .attr("class", "line")
      .datum(data)  // This is needed to reference the actual data
      .attr("d", line)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants