Mercurial > hg > dml-open-vis
view src/DML/MainVisBundle/Resources/assets/marionette/modules/GraphicsRenderingModule/GraphicsRenderingModule.20-Renderer.histogram.js @ 1:f38015048f48 tip
Added GPL
author | Daniel Wolff |
---|---|
date | Sat, 13 Feb 2016 20:43:38 +0100 |
parents | 493bcb69166c |
children |
line wrap: on
line source
"use strict"; App.module("GraphicsRenderingModule", function(GraphicsRenderingModule, App, Backbone, Marionette, $, _, Logger) { GraphicsRenderingModule.addInitializer(function(options){ GraphicsRenderingModule.registerRenderer({ id: "histogram", inherit: "_", defaultVegaConfig: { comparisonMode: null, dataDefinition: null, // forXs, forBars, forFloats, forXMean, forXStdDev, forceXsAreEdges colorForFlats: "#666", colorForBars: 0, ylabelDX: 3, xlabelDY: -3, paddingWhenAxisLabelsAreShown: {"top": 5, "left": 40, "bottom": 20, "right": 10}, paddingWhenAxisLabelsAreHidden: {"top": 5, "left": 10, "bottom": 1, "right": 10}, }, _formVC: function(vc, data) { vc.enoughSpaceForAxisLabels = vc.totalWidth > 200; vc.padding = vc.enoughSpaceForAxisLabels ? vc.paddingWhenAxisLabelsAreShown : vc.paddingWhenAxisLabelsAreHidden; vc.width = vc.totalWidth - vc.padding.left - vc.padding.right; vc.height = vc.totalHeight - vc.padding.top - vc.padding.bottom; var xs; var valuesForBars0 = []; var valuesForBars1 = []; var valuesForBars2 = []; var valuesForFlats0 = []; var valuesForFlats1 = []; var valuesForFlats2 = []; var valueForHoris0 = null; var valuesForOverlays0 = []; var xsAreEdges = false; var xsAreCategories = false; if (vc.comparisonMode) { xs = _.isFunction(vc.dataDefinition.forXs) ? vc.dataDefinition.forXs(data.left) : data.left[vc.dataDefinition.forXs]; } else { xs = _.isFunction(vc.dataDefinition.forXs) ? vc.dataDefinition.forXs(data.self) : data.self[vc.dataDefinition.forXs]; } if (vc.comparisonMode) { valuesForBars1 = (_.isFunction(vc.dataDefinition.forBars) ? vc.dataDefinition.forBars (data.left) : data.left [vc.dataDefinition.forBars] ); valuesForBars2 = (_.isFunction(vc.dataDefinition.forBars) ? vc.dataDefinition.forBars (data.right) : data.right[vc.dataDefinition.forBars] ); if (vc.dataDefinition.forFlats) { valuesForFlats1 = (_.isFunction(vc.dataDefinition.forFlats) ? vc.dataDefinition.forFlats(data.left) : data.left [vc.dataDefinition.forFlats]); valuesForFlats2 = (_.isFunction(vc.dataDefinition.forFlats) ? vc.dataDefinition.forFlats(data.right) : data.right[vc.dataDefinition.forFlats]); } } else { valuesForBars0 = (_.isFunction(vc.dataDefinition.forBars) ? vc.dataDefinition.forBars (data.self) : data.self[vc.dataDefinition.forBars ]); if (vc.dataDefinition.forFlats) { valuesForFlats0 = (_.isFunction(vc.dataDefinition.forFlats) ? vc.dataDefinition.forFlats(data.self) : data.self[vc.dataDefinition.forFlats]); } } if (vc.comparisonMode == "direct") { for (var i = 0; i < valuesForBars1.length; i++) { valuesForBars0.push(valuesForBars2[i] - valuesForBars1[i]); } for (var i = 0; i < valuesForFlats1.length; i++) { valuesForFlats0.push(valuesForFlats2[i] - valuesForFlats1[i]); } valuesForBars1 = []; valuesForFlats1 = []; valuesForBars2 = []; valuesForFlats2 = []; } try { if (valuesForBars0.length == xs.length - 1) { xsAreEdges = true; } if (valuesForBars1.length == xs.length - 1) { xsAreEdges = true; } if (vc.dataDefinition.forceXsAreEdges) { xsAreEdges = true; } } catch (e) { throw new App.RepresentationModule.Error({type: "ok-count-0"}); } if (_.isString(xs[0])) { xsAreCategories = true; } var xMean = undefined; if (vc.dataDefinition.forXMean && data.self) { xMean = _.isFunction(vc.dataDefinition.forXMean) ? vc.dataDefinition.forXMean (data.self) : data.self [vc.dataDefinition.forXMean]; } var xStdDev = undefined; if (vc.dataDefinition.forXStdDev && data.self) { xStdDev = _.isFunction(vc.dataDefinition.forXStdDev) ? vc.dataDefinition.forXStdDev (data.self) : data.self [vc.dataDefinition.forXStdDev]; } //var vegaDataByName = {} var generateVegaData = function(name, values, remarkPrefix, remarkSuffix) { var vegaValues = []; var tooltipType = xsAreEdges ? "tooltip_range" : "tooltip_point"; var maxI = values.length; for (var i = 0; i < maxI; i++) { var nextX = xs[i+1]; if (nextX !== undefined || xsAreCategories) { vegaValues.push([tooltipType, values[i], xs[i], nextX, remarkPrefix, remarkSuffix]); } } //console.log(vegaValues); //vegaDataByName[name] = result; return { "name": name, "values": vegaValues }; }; var generateVegaDataForHoris = function(name, values) { return { "name": name, "values": ["tooltip_horis", value] }; }; if (valuesForBars0 .length) {vc.data.push(generateVegaData("bars0", valuesForBars0));} if (valuesForBars1 .length) {vc.data.push(generateVegaData("bars1", valuesForBars1, "left: "));} if (valuesForBars2 .length) {vc.data.push(generateVegaData("bars2", valuesForBars2, "right: "));} if (valuesForFlats0 .length) {vc.data.push(generateVegaData("flats0", valuesForFlats0));} if (valuesForFlats1 .length) {vc.data.push(generateVegaData("flats1", valuesForFlats0, "left: "));} if (valuesForFlats2 .length) {vc.data.push(generateVegaData("flats2", valuesForFlats0, "right: "));} if (valueForHoris0 !== null) {vc.data.push(generateVegaDataForHoris("horis0", valuesForOverlays0));} var scalex = { "name": "scalex", "range": "width", "zero": false, //"nice": true, "round": false, }; if (xsAreCategories) { scalex["domain"] = {"data": valuesForBars0.length ? "bars0" : "bars1", "field": "2"}; scalex["type"] = "ordinal"; scalex["padding"] = 0.2; } else if (xsAreEdges) { scalex["type"] = "linear"; scalex["domain"] = [_.first(xs), _.last(xs)]; scalex["points"] = true; } else { scalex["domain"] = {"data": valuesForBars0.length ? "bars0" : "bars1", "field": "2"}; //scalex["type"] = "ordinal"; //scalex["domain"] = xs; //scalex["points"] = true; scalex["domain"] = [_.first(xs), _.last(xs)]; } var scalexRound = _.clone(scalex); scalexRound.name = "scalex_round"; scalexRound.round = true; vc.scales.push(scalex); vc.scales.push(scalexRound); var mult = 1.1; var generateVegaYScale = function(name, valuesForBars) { var min = _.min(valuesForBars); if (min < 0) { min = min * mult; } var max = _.max(valuesForBars); if (max > 0) { max = max * mult; } return { "name": name, "range": "height", "round": true, "nice": false, "domain": [Math.min(0, min), Math.max(0, max)] }; }; if (valuesForBars0 .length) {vc.scales.push(generateVegaYScale("scale0", valuesForBars0));} if (valuesForBars1 .length) {vc.scales.push(generateVegaYScale("scale1", valuesForBars1));} if (valuesForBars2 .length) {vc.scales.push(generateVegaYScale("scale2", valuesForBars2));} //console.log(vegaScales); //return; var barWidth = (vc.width / xs.length) + 0.5; var offsetForXRight = .5; // if (vegaConfig.width / xs.length > 1) { // offsetForXRight = 0.5; // } var generateVegaMark = function(dataName, scale, type, color, opacity) { var markProperties = { //"fill": {"value": color}, "opacity": {"value": opacity}, "y": {"scale": scale, "field": "1"}, }; if (type == "bar") { markProperties["y2"] = {"scale": scale, "value": 0}; } else { markProperties["height"] = {"value": 2}; } if (xsAreCategories) { markProperties["x"] = {"scale": "scalex", "field": "2"}; markProperties["width"] = {"value": 1}; markProperties["width"] = {"scale": "scalex", "band": true}; } else if (xsAreEdges) { markProperties["x"] = {"scale": "scalex", "field": "2"}; markProperties["x2"] = {"scale": "scalex", "field": "3", "offset": offsetForXRight}; } else { markProperties["x"] = {"scale": "scalex", "field": "2", "offset": offsetForXRight / 2}; //markProperties["x"] = {"scale": "scalex", "field": "2"}; markProperties["width"] = {"value": barWidth}; //markProperties["width"] = {"scale": "scalex", "band": true}; } return { "type": "rect", "from": {"data": dataName}, "properties": { "enter": markProperties, "update": {"fill": {"value": color}}, "hover": {"fill": {"value": "black"}} } }; }; // background (to catch mouse events and remove tooltips) vc.marks.push({ "type": "rect", "properties": { "enter": { "x": {"value": -vc.padding.left}, "y": {"value": -vc.padding.top}, "fill": {"value": "#fff"}, "y2": {"field": {"group": "height"}, "offset": vc.padding.left + vc.padding.right}, "x2": {"field": {"group": "width"}, "offset": vc.padding.top + vc.padding.bottom}, } } }); // Marks if (valuesForBars0 .length) {vc.marks.push(generateVegaMark("bars0", "scale0", "bar", vc.colorForBars, 1));} if (valuesForBars1 .length) {vc.marks.push(generateVegaMark("bars1", "scale1", "bar", vc.colorForBars, .5));} if (valuesForBars2 .length) {vc.marks.push(generateVegaMark("bars2", "scale2", "bar", vc.colorForBars, .5));} if (valuesForFlats0.length) {vc.marks.push(generateVegaMark("flats0", "scale0", "flat", vc.colorForFlats, 1));} if (valuesForFlats1.length) {vc.marks.push(generateVegaMark("flats1", "scale1", "flat", vc.colorForFlats, .5));} if (valuesForFlats2.length) {vc.marks.push(generateVegaMark("flats2", "scale2", "flat", vc.colorForFlats, .5));} // y axis vc.marks.push({ "type": "rect", "properties": { "enter": { "fill": {"value": vc.colorForAxes}, "x": {"value": 0}, "x2": {"field": {"group": "width"}}, "height": {"value": 1}, "y": {"scale": valuesForBars0.length ? "scale0" : "scale1", "value": 0}, } } }); var generateVegaVerticalMark = function(x, color, dataName, strokeDash) { return { "type": "rect", "from": { "data": dataName, }, "properties": { "enter": { "stroke": {"value": vc.colorForAxisLabels}, "strokeWidth": {"value": 1}, "y": {"value": -99}, "y2": {"field": {"group": "height"}}, "x": {"scale": "scalex_round", "value": x}, //"x2": {"scale": "scalex", "value": x, "offset": ""}, "width": {"value": 1}, "strokeDash": {"value": strokeDash} } } }; }; // x mean, x std dev if (xStdDev !== undefined && xMean !== undefined) { vc.data.push({ "name": "stdDev", "values": [["tooltip_value", xStdDev, 0, 0, "standard deviation: "]] }); vc.marks.push(generateVegaVerticalMark(xMean - xStdDev, "#ccc", "stdDev", [1, 1])); vc.marks.push(generateVegaVerticalMark(xMean + xStdDev, "#ccc", "stdDev", [1, 1])); } if (xMean !== undefined) { vc.data.push({ "name": "mean", "values": [["tooltip_value", xMean, 0, 0, "mean: ", xStdDev === 0 ? " (standard deviation is zero)" : undefined]] }); vc.marks.push(generateVegaVerticalMark(xMean, "#666", "mean", 0)); } //Axes var axisOpacity = vc.enoughSpaceForAxisLabels ? {"value" : 1} : {"value" : 0}; vc.axes.push({"type": "x", "scale": "scalex", /*"ticks": 8,*/ "properties": { "axis": { "stroke": {"value": "#fff"}, "strokeWidth": {"value": 0} }, "grid": { "stroke": {"value": "#fff"}, "strokeOpacity": {"value": 0.4}, "strokeWidth": {"value": 1} }, "ticks": { "stroke": {"value": "#fff"}, "strokeWidth": {"value": 0}, "opacity": axisOpacity }, "labels": { "fill": {"value": vc.colorForAxisLabels}, "dy": {"value": vc.xlabelDY}, "font": {"value": vc.fontFace}, "fontSize": {"value": vc.fontSizeForLabelsInAxis}, "opacity": axisOpacity } } }); if (valuesForBars0.length) { vc.axes.push({"type": "y", "scale": "scale0", /*"ticks": 5,*/ "grid": vc.enoughSpaceForAxisLabels, "zero": false, "properties": { "axis": { "stroke": {"value": "#fff"}, "strokeWidth": {"value": 0} }, "grid": { "stroke": {"value": "#fff"}, "strokeOpacity": {"value": 0.4}, "opacity": {"value": 1} }, "ticks": { "stroke": {"value": "#fff"}, "strokeWidth": {"value": 0}, "opacity": axisOpacity }, "labels": { "fill": {"value": vc.colorForAxisLabels}, "fontSize": {"value": vc.fontSizeForLabelsInAxis}, "dx": {"value": vc.ylabelDX}, "font": {"value": vc.fontFace}, "opacity": axisOpacity } } }); }; }, }); }); }, Logger);