chiasm-charts
Advanced tools
Comparing version 0.1.1 to 0.1.2
{ | ||
"name": "chiasm-charts", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "Reusable data visualization components.", | ||
@@ -5,0 +5,0 @@ "repository": "git://github.com/chiasm-project/chiasm-charts.git", |
# chiasm-charts | ||
[![](http://bl.ocks.org/curran/raw/46050d18d5ec1ab401fa/thumbnail.png)](http://bl.ocks.org/curran/46050d18d5ec1ab401fa) | ||
Reusable data visualization components for [Chiasm](https://github.com/chiasm-project/chiasm). | ||
Reusable data visualization components. | ||
The beginnings of this library are explained in this [video tutorial: Introduction to Chiasm](https://www.youtube.com/watch?v=MpweS7gNBt4). This video tutorial ends with this [code example: Reactive Mixins for Visualizations](http://bl.ocks.org/curran/5e3c1bed7c9cdd2b431c). | ||
<a href="http://bl.ocks.org/curran/5e3c1bed7c9cdd2b431c"> | ||
<img align="right" src="http://bl.ocks.org/curran/raw/5e3c1bed7c9cdd2b431c/thumbnail.png"> | ||
</a>The beginnings of this library are explained in this [video tutorial: Introduction to Chiasm](https://www.youtube.com/watch?v=MpweS7gNBt4). This video tutorial ends with this [code example: Reactive Mixins for Visualizations](http://bl.ocks.org/curran/5e3c1bed7c9cdd2b431c). | ||
## Examples | ||
| thumbnail | description | | ||
|---|---| | ||
| [![](http://bl.ocks.org/curran/raw/9938078a93a4ba380a0e/thumbnail.png)](http://bl.ocks.org/curran/9938078a93a4ba380a0e) | Interactive Scatter Plot with selectable X, Y columns. | | ||
| [![](http://bl.ocks.org/curran/raw/46050d18d5ec1ab401fa/thumbnail.png)](http://bl.ocks.org/curran/46050d18d5ec1ab401fa) | Chiasm-Charts v0.1.0 | | ||
## Developing | ||
@@ -21,8 +24,14 @@ | ||
After that, you can run the visual tests with the command: | ||
After that, you can launch the visual test suite with the command: | ||
``` | ||
npm run serve-tests | ||
``` | ||
This will launch an instance of [live-server](https://github.com/tapio/live-server), which will automatically re-load the page every time you build the test application bundle. To build the bundle, run | ||
``` | ||
npm run build | ||
``` | ||
This will build the test application, which you can then inspect in a browser window open to the visual test page. This serves as the unit test suite for chiasm-charts. | ||
This will build the test application, which you can then inspect in the browser window open to the visual test page. This serves as the unit test suite for chiasm-charts. |
@@ -8,19 +8,35 @@ var d3 = require("d3"); | ||
var my = ChiasmComponent(); | ||
var my = ChiasmComponent({ | ||
fill: "black", | ||
stroke: "none", | ||
strokeWidth: "1px" | ||
}); | ||
var svg = d3.select(my.initSVG()); | ||
mixins.backgroundColor(my, svg); | ||
var g = mixins.marginConvention(my, svg); | ||
mixins.marginEditor(my, svg); | ||
mixins.column(my, "x"); | ||
mixins.column(my, "y"); | ||
mixins.scale(my, "x"); | ||
mixins.autoScaleType(my, "x"); | ||
mixins.rangeBands(my, "x"); | ||
mixins.scale(my, "y"); | ||
mixins.scaleRange(my, "x"); | ||
mixins.scaleRange(my, "y"); | ||
mixins.autoScaleType(my, "x", "Bands"); | ||
mixins.autoScaleType(my, "y", "Bands"); | ||
// The placement of this line ensures that the bars are drawn | ||
// behind the axis. | ||
var barsG = g.append("g"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
mixins.xAxisLabel(my, xAxisG); | ||
mixins.scale(my, "y", "linear"); | ||
var yAxisG = mixins.yAxis(my, g); | ||
mixins.yAxisLabel(my, yAxisG); | ||
mixins.marginEditor(my, svg); | ||
mixins.xAxisLabel(my, svg); | ||
mixins.yAxisLabel(my, svg); | ||
@@ -32,6 +48,6 @@ // Use a zero based Y scale. | ||
my.when(["dataset", "xScaled", "yScaled", "height", "xRangeBand"], | ||
function (dataset, xScaled, yScaled, height, xRangeBand) { | ||
my.when(["dataset", "xScaled", "yScaled", "height", "xRangeBand", "fill", "stroke", "strokeWidth"], | ||
function (dataset, xScaled, yScaled, height, xRangeBand, fill, stroke, strokeWidth){ | ||
var bars = g.selectAll("rect").data(dataset.data); | ||
var bars = barsG.selectAll("rect").data(dataset.data); | ||
bars.enter().append("rect"); | ||
@@ -42,3 +58,6 @@ bars | ||
.attr("y", yScaled) | ||
.attr("height", function (d){ return height - yScaled(d); }); | ||
.attr("height", function (d){ return height - yScaled(d); }) | ||
.style("stroke", stroke) | ||
.style("stroke-width", strokeWidth) | ||
.style("fill", fill); | ||
bars.exit().remove(); | ||
@@ -45,0 +64,0 @@ |
@@ -18,13 +18,24 @@ // A bot plot component. | ||
var svg = d3.select(my.initSVG()); | ||
mixins.backgroundColor(my, svg); | ||
var g = mixins.marginConvention(my, svg); | ||
mixins.marginEditor(my, svg); | ||
mixins.column(my, "x"); | ||
mixins.column(my, "y"); | ||
mixins.scale(my, "x"); | ||
mixins.scale(my, "y"); | ||
mixins.scaleRange(my, "x"); | ||
mixins.scaleRange(my, "y"); | ||
mixins.autoScaleType(my, "x", "Bands"); | ||
mixins.autoScaleType(my, "y", "Bands"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
mixins.scale(my, "x", "ordinal"); | ||
mixins.xAxisLabel(my, xAxisG); | ||
var yAxisG = mixins.yAxis(my, g); | ||
mixins.scale(my, "y", "linear"); | ||
mixins.yAxisLabel(my, yAxisG); | ||
mixins.marginEditor(my, svg); | ||
mixins.xAxisLabel(my, svg); | ||
mixins.yAxisLabel(my, svg); | ||
@@ -31,0 +42,0 @@ my.when(["dataset", "xAccessor"], function (dataset, xAccessor){ |
@@ -11,20 +11,27 @@ var d3 = require("d3"); | ||
var svg = d3.select(my.initSVG()); | ||
mixins.backgroundColor(my, svg); | ||
var g = mixins.marginConvention(my, svg); | ||
mixins.marginEditor(my, svg); | ||
mixins.scale(my, "x"); | ||
mixins.autoScaleType(my, "x"); | ||
mixins.rangeBands(my, "x"); | ||
mixins.column(my, "x"); | ||
mixins.column(my, "y"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
mixins.xAxisLabel(my, xAxisG); | ||
mixins.scaleRange(my, "x"); | ||
mixins.scaleRange(my, "y"); | ||
mixins.scale(my, "x"); | ||
mixins.scale(my, "y"); | ||
mixins.autoScaleType(my, "y"); | ||
mixins.rangeBands(my, "y"); | ||
mixins.autoScaleType(my, "x", "Bands"); | ||
mixins.autoScaleType(my, "y", "Bands"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
var yAxisG = mixins.yAxis(my, g); | ||
mixins.yAxisLabel(my, yAxisG); | ||
mixins.marginEditor(my, svg); | ||
mixins.xAxisLabel(my, svg); | ||
mixins.yAxisLabel(my, svg); | ||
// TODO make this color scale into a mixin. | ||
my.addPublicProperty("colorColumn", Model.None); | ||
@@ -31,0 +38,0 @@ my.addPublicProperty("colorRangeMin", "#FFFFFF"); |
@@ -14,15 +14,25 @@ var d3 = require("d3"); | ||
var svg = d3.select(my.initSVG()); | ||
mixins.backgroundColor(my, svg); | ||
var g = mixins.marginConvention(my, svg); | ||
mixins.marginEditor(my, svg); | ||
mixins.column(my, "x"); | ||
mixins.column(my, "y"); | ||
mixins.scale(my, "x"); | ||
mixins.scale(my, "y"); | ||
mixins.scaleRange(my, "x"); | ||
mixins.scaleRange(my, "y"); | ||
mixins.autoScaleType(my, "x"); | ||
mixins.autoScaleType(my, "y"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
mixins.scale(my, "x", "time"); | ||
mixins.xAxisLabel(my, xAxisG); | ||
var yAxisG = mixins.yAxis(my, g); | ||
mixins.scale(my, "y", "linear"); | ||
mixins.yAxisLabel(my, yAxisG); | ||
mixins.marginEditor(my, svg); | ||
mixins.xAxisLabel(my, svg); | ||
mixins.yAxisLabel(my, svg); | ||
var line = d3.svg.line() | ||
@@ -29,0 +39,0 @@ |
@@ -14,17 +14,51 @@ var d3 = require("d3"); | ||
var svg = d3.select(my.initSVG()); | ||
mixins.backgroundColor(my, svg); | ||
var g = mixins.marginConvention(my, svg); | ||
mixins.marginEditor(my, svg); | ||
mixins.scale(my, "x", "linear") | ||
mixins.column(my, "x"); | ||
mixins.column(my, "y"); | ||
mixins.scale(my, "x"); | ||
mixins.scale(my, "y"); | ||
mixins.scaleRange(my, "x"); | ||
mixins.scaleRange(my, "y"); | ||
mixins.autoScaleType(my, "x", "Points"); | ||
mixins.autoScaleType(my, "y", "Points"); | ||
var xAxisG = mixins.xAxis(my, g); | ||
mixins.xAxisLabel(my, xAxisG); | ||
mixins.scale(my, "y", "linear"); | ||
var yAxisG = mixins.yAxis(my, g); | ||
mixins.yAxisLabel(my, yAxisG); | ||
mixins.marginEditor(my, svg); | ||
mixins.xAxisLabel(my, svg); | ||
mixins.yAxisLabel(my, svg); | ||
my.when(["dataset", "xAccessor"], function (dataset, xAccessor){ | ||
my.xScaleDomain = d3.extent(dataset.data, xAccessor); | ||
}); | ||
my.xScaleRangePadding = 0.5; | ||
my.yScaleRangePadding = 0.5; | ||
//// Allow the API client to optionally specify fixed min and max values. | ||
//model.xDomainMin = None; | ||
//model.xDomainMax = None; | ||
//model.when(["data", "getX", "xDomainMin", "xDomainMax"], | ||
// function (data, getX, xDomainMin, xDomainMax) { | ||
// if(xDomainMin === None && xDomainMax === None){ | ||
// model.xDomain = d3.extent(data, getX); | ||
// } else { | ||
// if(xDomainMin === None){ | ||
// xDomainMin = d3.min(data, getX); | ||
// } | ||
// if(xDomainMax === None){ | ||
// xDomainMax = d3.max(data, getX); | ||
// } | ||
// model.xDomain = [xDomainMin, xDomainMax] | ||
// } | ||
//}); | ||
// TODO move this elsewhere | ||
//my.when(["dataset", "xAccessor"], function (dataset, xAccessor){ | ||
// my.xScaleDomain = d3.extent(dataset.data, xAccessor); | ||
//}); | ||
@@ -31,0 +65,0 @@ my.when(["dataset", "yAccessor"], function (dataset, yAccessor){ |
@@ -1,369 +0,15 @@ | ||
var d3 = require("d3"); | ||
var Model = require("model-js"); | ||
var ChiasmDataset = require("chiasm-dataset"); | ||
var getColumnMetadata = ChiasmDataset.getColumnMetadata; | ||
module.exports = { | ||
column: require("./scale/column"), | ||
scale: require("./scale/scale"), | ||
scaleRange: require("./scale/scaleRange"), | ||
autoScaleType: require("./scale/autoScaleType"), | ||
// TODO split up this file. | ||
// TODO migrate to ES6 modules & Rollup. | ||
marginConvention: require("./marginConvention"), | ||
marginEditor: require("./marginEditor"), | ||
xAxis: require("./xAxis"), | ||
yAxis: require("./yAxis"), | ||
xAxisLabel: require("./xAxisLabel"), | ||
yAxisLabel: require("./yAxisLabel"), | ||
function marginConvention(my, svg){ | ||
var g = svg.append("g"); | ||
// TODO maybe the margin would be better suited as 4 separate properties? | ||
// margin-top | ||
// margin-bottom | ||
// margin-left | ||
// margin-right | ||
my.addPublicProperty("margin", {top: 20, right: 20, bottom: 50, left: 60}); | ||
my.when(["box", "margin"], function (box, margin){ | ||
my.width = box.width - margin.left - margin.right; | ||
my.height = box.height - margin.top - margin.bottom; | ||
g.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | ||
}); | ||
return g; | ||
} | ||
function marginEditor(my, svg){ | ||
// The width of the handles. | ||
my.addPublicProperty("marginEditorWidth", 15); | ||
// The color of the handles on hover. | ||
my.addPublicProperty("marginEditorFill", "rgba(0, 0, 0, 0.2)"); | ||
var data = [ "left", "right", "top", "bottom" ]; | ||
var handles = svg.selectAll(".margin-handle").data(data); | ||
handles.enter().append("rect") | ||
.attr("class", "margin-handle") | ||
.style("fill", "none") | ||
.style("pointer-events", "all") | ||
var drag = d3.behavior.drag().on("drag", function (d) { | ||
// Mutate the margin object. | ||
my.margin[d] = { | ||
left: d3.event.x, | ||
right: -d3.event.x, | ||
top: d3.event.y, | ||
bottom: -d3.event.y, | ||
}[d]; | ||
// Notify model-js that the margin object has been mutated. | ||
my.margin = my.margin; | ||
// Hide the handles during drag. | ||
handles.style("fill", "none"); | ||
}); | ||
handles.call(drag); | ||
// Fill in the handles on hover. | ||
my.when("marginEditorFill", function (marginEditorFill){ | ||
handles | ||
.on("mouseenter", function (){ | ||
d3.select(this).style("fill", marginEditorFill); | ||
}) | ||
.on("mouseout", function (){ | ||
d3.select(this).style("fill", "none"); | ||
}); | ||
}); | ||
// Update the drag origin function based on the margin. | ||
my.when("margin", function (margin){ | ||
var origins = { | ||
left: { x: margin.left, y: 0 }, | ||
right: { x: -margin.right, y: 0 }, | ||
top: { x: 0, y: margin.top }, | ||
bottom: { x: 0, y: -margin.bottom }, | ||
}; | ||
drag.origin(function(d) { | ||
return origins[d]; | ||
}); | ||
}); | ||
// Render the handles | ||
my.when(["margin", "marginEditorWidth", "width", "height"], | ||
function (margin, marginEditorWidth, width, height){ | ||
var x = { | ||
left: margin.left - marginEditorWidth / 2, | ||
right: margin.left + width - marginEditorWidth / 2, | ||
top: margin.left, | ||
bottom: margin.left | ||
}; | ||
var y = { | ||
left: margin.top, | ||
right: margin.top, | ||
top: margin.top - marginEditorWidth / 2, | ||
bottom: margin.top + height - marginEditorWidth / 2 | ||
}; | ||
var w = { | ||
left: marginEditorWidth, | ||
right: marginEditorWidth, | ||
top: width, | ||
bottom: width | ||
}; | ||
var h = { | ||
left: height, | ||
right: height, | ||
top: marginEditorWidth, | ||
bottom: marginEditorWidth | ||
}; | ||
var cursor = { | ||
left: "ew-resize", | ||
right: "ew-resize", | ||
top: "ns-resize", | ||
bottom: "ns-resize" | ||
}; | ||
handles | ||
.attr("x", function (d){ return x[d]; }) | ||
.attr("y", function (d){ return y[d]; }) | ||
.attr("width", function (d){ return w[d]; }) | ||
.attr("height", function (d){ return h[d]; }) | ||
.style("cursor", function (d){ return cursor[d]; }) | ||
// Rounded corners. | ||
.attr("rx", function (d){ return marginEditorWidth / 2; }) | ||
.attr("ry", function (d){ return marginEditorWidth / 2; }); | ||
}); | ||
} | ||
function scale(my, prefix, initialScaleType){ | ||
var scaleName = prefix + "Scale"; | ||
var scaleDomain = prefix + "ScaleDomain"; | ||
var scaleRange = prefix + "ScaleRange"; | ||
var scalePadding = prefix + "ScaleRangePadding" | ||
var scaleType = prefix + "ScaleType"; | ||
var columnName = prefix + "Column"; | ||
var columnAccessor = prefix + "Accessor"; | ||
var scaled = prefix + "Scaled"; | ||
var columnMetadata = prefix + "Metadata"; | ||
my.addPublicProperty(columnName, Model.None); | ||
// TODO this feels like it should be elsewhere. | ||
if(prefix === "x"){ | ||
my.when("width", function (width){ | ||
my[scaleRange] = [0, width]; | ||
}); | ||
} else if(prefix === "y"){ | ||
my.when("height", function (height){ | ||
my[scaleRange] = [height, 0]; | ||
}); | ||
} | ||
var scaleTypes = { | ||
linear: function (my){ | ||
var myScale = d3.scale.linear(); | ||
return my.when([scaleDomain, scaleRange], function (domain, range){ | ||
if(domain !== Model.None && range !== Model.None){ | ||
my[scaleName] = myScale.domain(domain).range(range); | ||
} | ||
}); | ||
}, | ||
ordinal: function (my){ | ||
var myScale = d3.scale.ordinal(); | ||
return my.when([scaleDomain, scaleRange, scalePadding], function (domain, range, padding){ | ||
if(domain !== Model.None && range !== Model.None){ | ||
// TODO what about rangePoints? | ||
my[scaleName] = myScale.domain(domain).rangeBands(range, padding); | ||
} | ||
}); | ||
}, | ||
time: function (my){ | ||
var myScale = d3.time.scale(); | ||
return my.when([scaleDomain, scaleRange], function (domain, range){ | ||
if(domain !== Model.None && range !== Model.None){ | ||
my[scaleName] = myScale.domain(domain).range(range); | ||
} | ||
}); | ||
} | ||
}; | ||
my.addPublicProperty(scaleDomain, Model.None); | ||
my.addPublicProperty(scaleType, initialScaleType ? initialScaleType : Model.None ) | ||
// This property is relevant only for ordinal scales. | ||
my.addPublicProperty(scalePadding, 0.1); | ||
var oldListener; | ||
my.when(scaleType, function (type){ | ||
if(type !== Model.None){ | ||
// TODO add tests for this line. | ||
if(oldListener){ my.cancel(oldListener); } | ||
oldListener = scaleTypes[type](my); | ||
} | ||
}); | ||
my.when(columnName, function (column){ | ||
my[columnAccessor] = function (d){ return d[column]; }; | ||
}); | ||
my.when([scaleName, columnName], function (scale, column){ | ||
my[scaled] = function (d){ return scale(d[column]); }; | ||
}); | ||
my.when(["dataset", columnName], function (dataset, column){ | ||
if(column !== Model.None){ | ||
my[columnMetadata] = getColumnMetadata(dataset, column); | ||
} | ||
}); | ||
} | ||
// TODO figure out what this really is about. | ||
// The name autoScaleType does not really express what it does. | ||
// It really is more the thing that isolates the difference between | ||
// a bar chart and a histogram. | ||
// This is used in the histogram and heatmap visualizations. | ||
// It has to do with "rangeBands" vs. "rangePoints" too. | ||
function autoScaleType(my, prefix){ | ||
// TODO move these into functions, eliminate duplicate code. | ||
var columnName = prefix + "Column"; | ||
var columnAccessor = prefix + "Accessor"; | ||
var scaleDomain = prefix + "ScaleDomain"; | ||
var scaleType = prefix + "ScaleType"; | ||
var columnAccessor = prefix + "Accessor"; | ||
var columnMetadata = prefix + "Metadata"; | ||
my.when(["dataset", columnMetadata, columnAccessor], function (dataset, meta, accessor){ | ||
if(meta.interval){ | ||
// TODO use symbols, e.g. ChiasmDataset.NUMBER rather than strings. | ||
// TODO use ES6 modules, where symbols make more sense. | ||
var columnIsNumber = (meta.type === "number"); | ||
var columnIsDate = (meta.type === "date"); | ||
if(columnIsNumber){ | ||
// Histogram bins. | ||
my[scaleType] = "linear"; | ||
my[scaleDomain] = d3.extent(dataset.data, accessor); | ||
my[scaleDomain][1] += meta.interval; | ||
} else if(columnIsDate){ | ||
// TODO support time intervals. | ||
} | ||
} else { | ||
// Typical ordinal bars. | ||
my[scaleType] = "ordinal"; | ||
my[scaleDomain] = dataset.data.map(accessor); | ||
} | ||
}); | ||
} | ||
function rangeBands(my, prefix){ | ||
// TODO make these into functions, reduce duplicate code. | ||
var scaleName = prefix + "Scale"; | ||
var columnMetadata = prefix + "Metadata"; | ||
var rangeBand = prefix + "RangeBand"; | ||
my.when([columnMetadata, scaleName], function (metadata, scale) { | ||
if(metadata.interval){ | ||
// Histogram bins. | ||
my[rangeBand] = Math.abs( scale(metadata.interval) - scale(0) ); | ||
} else { | ||
// Typical ordinal bars. | ||
my[rangeBand] = scale.rangeBand(); | ||
} | ||
}); | ||
} | ||
function xAxis(my, g){ | ||
var axisG = g.append("g").attr("class", "x axis"); | ||
var axis = d3.svg.axis(); | ||
my.addPublicProperty("xAxisTickDensity", 70); | ||
my.when(["xScale", "xAxisTickDensity", "width"], function (xScale, xAxisTickDensity, width){ | ||
axis.scale(xScale).ticks(width / xAxisTickDensity) | ||
axisG.call(axis); | ||
}); | ||
my.when("height", function (height){ | ||
axisG.attr("transform", "translate(0," + height + ")"); | ||
}); | ||
return axisG; | ||
} | ||
function yAxis(my, g){ | ||
var axisG = g.append("g").attr("class", "y axis"); | ||
var axis = d3.svg.axis().orient("left"); | ||
my.addPublicProperty("yAxisTickDensity", 30); | ||
my.when(["yScale", "yAxisTickDensity", "height"], function (yScale, yAxisTickDensity, height){ | ||
axis.scale(yScale).ticks(height / yAxisTickDensity) | ||
axisG.call(axis); | ||
}); | ||
return axisG; | ||
} | ||
function xAxisLabel(my, xAxisG){ | ||
var label = xAxisG.append("text").attr("class", "x axis-label"); | ||
my.addPublicProperty("xAxisLabelText", "X Axis Label"); | ||
my.addPublicProperty("xAxisLabelTextOffset", 43); | ||
my.when("xAxisLabelText", function (xAxisLabelText){ | ||
label.text(xAxisLabelText); | ||
}); | ||
my.when("xAxisLabelTextOffset", function (xAxisLabelTextOffset){ | ||
label.attr("y", xAxisLabelTextOffset); | ||
}); | ||
my.when("width", function (width){ | ||
label.attr("x", width / 2); | ||
}); | ||
} | ||
function yAxisLabel(my, yAxisG){ | ||
var label = yAxisG.append("text").attr("class", "y axis-label"); | ||
my.addPublicProperty("yAxisLabelText", "Y Axis Label"); | ||
my.addPublicProperty("yAxisLabelTextOffset", 35); | ||
my.when("yAxisLabelText", function (yAxisLabelText){ | ||
label.text(yAxisLabelText); | ||
}); | ||
my.when(["yAxisLabelTextOffset", "height"], function (offset, height){ | ||
label.attr("transform", "translate(-" + offset + "," + (height / 2) + ") rotate(-90)") | ||
}); | ||
} | ||
module.exports = { | ||
marginConvention: marginConvention, | ||
marginEditor: marginEditor, | ||
scale: scale, | ||
autoScaleType: autoScaleType, | ||
rangeBands: rangeBands, | ||
xAxis: xAxis, | ||
xAxisLabel: xAxisLabel, | ||
yAxis: yAxis, | ||
yAxisLabel: yAxisLabel | ||
backgroundColor: require("./backgroundColor") | ||
}; |
@@ -23,4 +23,4 @@ var Chiasm = require("chiasm"); | ||
// These are custom property values used across many components. | ||
var xAxisLabelTextOffset = 30; | ||
var yAxisLabelTextOffset = 30; | ||
var xAxisLabelTextOffset = 6; | ||
var yAxisLabelTextOffset = 15; | ||
var margin = { top: 10, right: 10, bottom: 40, left: 42 }; | ||
@@ -41,2 +41,3 @@ | ||
"myScatterPlot", | ||
"myScatterPlotOrdinalX", | ||
"myBoxPlot" | ||
@@ -93,2 +94,14 @@ ] | ||
}, | ||
"myScatterPlotOrdinalX": { | ||
"plugin": "scatterPlot", | ||
"state": { | ||
"xAxisLabelText": "Class", | ||
"xColumn": "class", | ||
"yAxisLabelText": "Petal Length", | ||
"yColumn": "petal_length", | ||
"xAxisLabelTextOffset": xAxisLabelTextOffset, | ||
"yAxisLabelTextOffset": yAxisLabelTextOffset, | ||
"margin": margin | ||
} | ||
}, | ||
"myBoxPlot": { | ||
@@ -119,2 +132,4 @@ "plugin": "boxPlot", | ||
"yColumn": "amount", | ||
"fill": "#1EABE8", | ||
"stroke": "#008CC8", | ||
"xAxisLabelTextOffset": xAxisLabelTextOffset, | ||
@@ -195,2 +210,3 @@ "yAxisLabelTextOffset": yAxisLabelTextOffset, | ||
"scatterPlotDataLoader.dataset -> myScatterPlot.dataset", | ||
"scatterPlotDataLoader.dataset -> myScatterPlotOrdinalX.dataset", | ||
"scatterPlotDataLoader.dataset -> myBoxPlot.dataset", | ||
@@ -197,0 +213,0 @@ "scatterPlotDataLoader.dataset -> histogramData.datasetIn", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44919
31
945
37