# HG changeset patch # User Tomas Zeman # Date 1446721162 -3600 # Node ID 149647cd3801e19172e06e48f0e36c69db275d7d # Parent 82489d99b23285e888844687b1f654a03ab03c38 RadarChart + nvd3 scala.js façade diff -r 82489d99b232 -r 149647cd3801 build.sbt --- a/build.sbt Thu Oct 08 15:18:33 2015 +0200 +++ b/build.sbt Thu Nov 05 11:59:22 2015 +0100 @@ -27,7 +27,9 @@ buildInfoPackage := "ngtags", buildInfoOptions ++= Seq(BuildInfoOption.ToMap, BuildInfoOption.ToJson) -).jvmSettings().jsSettings() +).jvmSettings().jsSettings( + jsDependencies += ProvidedJS / "RadarChart.js" +) lazy val ngtagsJS = ngtags.js lazy val ngtagsJVM = ngtags.jvm diff -r 82489d99b232 -r 149647cd3801 js/src/main/resources/RadarChart.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/main/resources/RadarChart.js Thu Nov 05 11:59:22 2015 +0100 @@ -0,0 +1,245 @@ +/* + * Cloned from https://gist.github.com/nbremer/6506614 + */ + +//Practically all this code comes from https://github.com/alangrafu/radar-chart-d3 +//I only made some additions and aesthetic adjustments to make the chart look better +//(of course, that is only my point of view) +//Such as a better placement of the titles at each line end, +//adding numbers that reflect what each circular level stands for +//Not placing the last level and slight differences in color +// +//For a bit of extra information check the blog about it: +//http://nbremer.blogspot.nl/2013/09/making-d3-radar-chart-look-bit-better.html + +var RadarChart = { + draw: function(id, d, options){ + var cfg = { + radius: 5, + w: 600, + h: 600, + factor: 1, + factorLegend: .85, + levels: 3, + maxValue: 0, + radians: 2 * Math.PI, + opacityArea: 0.5, + ToRight: 5, + TranslateX: 80, + TranslateY: 30, + ExtraWidthX: 100, + ExtraWidthY: 100, + color: d3.scale.category10(), + offset: 0.0, + formatAxis: d3.format('%'), + formatValue: d3.format('%'), + drawMaxLevel: false + }; + + if (d.length == 0) + return; + + if('undefined' !== typeof options){ + for(var i in options){ + if('undefined' !== typeof options[i]){ + cfg[i] = options[i]; + } + } + } + cfg.maxValue = Math.max(cfg.maxValue, d3.max(d, function(i){return d3.max(i.map(function(o){return o.value;}))})) + cfg.offset; + var allAxis = (d[0].map(function(i, j){return i})); + var total = allAxis.length; + var radius = cfg.factor*Math.min(cfg.w/2, cfg.h/2); + d3.select(id).select("svg").remove(); + + var g = d3.select(id) + .append("svg") + .attr("width", cfg.w+cfg.ExtraWidthX) + .attr("height", cfg.h+cfg.ExtraWidthY) + .append("g") + .attr("transform", "translate(" + cfg.TranslateX + "," + cfg.TranslateY + ")"); + ; + + var tooltip; + + //Circular segments + var maxLevel = cfg.drawMaxLevel ? cfg.levels : cfg.levels - 1; + for(var j=0; j + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.tz.nvd3 + +import scala.scalajs.js +import scala.scalajs.js.annotation.{JSExport, JSExportAll} +import scala.scalajs.js.Dynamic.{global => g} +import scala.scalajs.js.JSConverters._ + +private[nvd3] abstract class Constructable[C <: Constructable[C]]( + b: Map[String, Any] +, cf: Map[String, Any] => C) { + protected def v[T](n: Symbol, v: T): C = cf(b + (n.name -> v)) + def toJs = b.toJSDictionary +} + +class Axis(b: Map[String, Any]) + extends Constructable[Axis](b, m => new Axis(m)) { + def axisLabel(l: String) = v('axisLabel, l) + def showMaxMin(b: Boolean) = v('showMaxMin, b) + def staggerLabels(b: Boolean) = v('staggerLabels, b) + def labelDistance(d: Int) = v('axisLabelDistance, d) + def tickFormat(f: js.Function1[Double, js.Any]) = v('tickFormat, f) + def rotateLabels(deg: Int) = v('rotateLabels, deg) +} + +class Margin(b: Map[String, Any]) + extends Constructable[Margin](b, m => new Margin(m)) { + def top(i: Int) = v('top, i) + def bottom(i: Int) = v('bottom, i) + def left(i: Int) = v('left, i) + def right(i: Int) = v('right, i) +} + +class Legend(b: Map[String, Any]) + extends Constructable[Legend](b, m => new Legend(m)) { + def margin(m: Margin) = v('margin, m) +} + +class Chart(b: Map[String, Any]) + extends Constructable[Chart](b, m => new Chart(m)) { + + def transitionDuration(ms: Int) = v('transitionDuration, ms) + def height(h: Int) = v('height, h) + def width(w: Int) = v('width, w) + def x[R](f: js.Function1[js.Dynamic, R]) = v('x, f) + def y[R](f: js.Function1[js.Dynamic, R]) = v('y, f) + def average(f: js.Function1[js.Dynamic, Any]) = v('average, f) + def forceY(min: Double, max: Double) = v('forceY, js.Array(min, max)) + def color(colors: js.Array[String]) = v('color, colors) + def color(colors: js.Any) = v('color, colors) + def useInteractiveGuideline(b: Boolean) = v('useInteractiveGuideline, b) + def clipVoronoi(b: Boolean) = v('clipVoronoi, b) + def useVoronoi(b: Boolean) = v('useVoronoi, b) + def xAxis(a: Axis) = v('xAxis, a.toJs) + def yAxis(a: Axis) = v('yAxis, a.toJs) + def margin(m: Margin) = v('margin, m.toJs) + def reduceXTicks(b: Boolean) = v('reduceXTicks, b) + def showValues(b: Boolean) = v('showValues, b) + def showControls(b: Boolean) = v('showControls, b) + def showLabels(b: Boolean) = v('showLabels, b) + def showLegend(b: Boolean) = v('showLegend, b) + def staggerLabels(b: Boolean) = v('staggerLabels, b) + def valueFormat[F, T](f: js.Function1[F, T]) = v('valueFormat, f) + def donut(b: Boolean) = v('donut, b) + def legend(l: Legend) = v('legend, l) + def labelThreshold(t: Double) = v('labelThreshold, t) + def clipEdge(b: Boolean) = v('clipEdge, b) +} + +object Chart { + private def as(t: Symbol) = new Chart(Map("type" -> t.name)) + + def bulletChart = as('bulletChart) + def cumulativeLineChart = as('cumulativeLineChart) + def discreteBarChart = as('discreteBarChart) + def pieChart = as('pieChart) + def historicalBarChart = as('historicalBarChart) + def multiBarChart = as('multiBarChart) + def multiBarHorizontalChart = as('multiBarHorizontalChart) + def stackedAreaChart = as('stackedAreaChart) + + def axis(l: String) = new Axis(Map()) axisLabel(l) + def margin = new Margin(Map()) + def legend = new Legend(Map()) +} + +@JSExportAll +case class Options(var chart: js.Dictionary[Any]) + +class RadarChartConfig(b: Map[String, Any]) + extends Constructable[RadarChartConfig](b, m => new RadarChartConfig(m)) { + + def radius(r: Int) = v('radius, r) + def height(h: Int) = v('h, h) + def width(w: Int) = v('w, w) + def factor(f: Double) = v('factor, f) + def factorLegend(f: Double) = v('factorLegend, f) + def levels(l: Int) = v('levels, l) + def maxValue(m: Double) = v('maxValue, m) + def opacityArea(o: Double) = v('opacityArea, o) + def toRight(r: Int) = v('ToRight, r) + def translateX(t: Int) = v('TranslateX, t) + def translateY(t: Int) = v('TranslateY, t) + def extraWidthX(w: Int) = v('ExtraWidthX, w) + def extraWidthY(w: Int) = v('ExtraWidthY, w) + def color(c: js.Function1[Int, String]) = v('color, c) + def offset(d: Double) = v('offset, d) + def formatValue(f: js.Function1[Double, String]) = v('formatValue, f) + def formatAxis(f: js.Function1[Double, String]) = v('formatAxis, f) + def drawMaxLevel(b: Boolean) = v('drawMaxLevel, b) +} + +object RadarChartConfig { + def default = new RadarChartConfig(Map()) +} + +object RadarChart { + case class V(val n: String, val v: Double, val t: Option[() => String] = None) { + @JSExport + def axis = n + @JSExport + def value = v + @JSExport + def tooltip() = t.map(_()).getOrElse("") + } + + def apply(id: String, data: Seq[Seq[V]], cfg: RadarChartConfig) = + g.RadarChart.draw(id, data.map(_.toJSArray).toJSArray, cfg.toJs) +} + +object MultiBarChart { + case class V[X](_x: X, _y: Double) { + @JSExport + def x = _x + @JSExport + def y = _y + } + + case class Series[X](_key: String, _values: Seq[V[X]]) { + @JSExport + def key = _key + @JSExport + def values = _values.toJSArray + } +} + +// vim: set ts=2 sw=2 et: