[Plot] Separate out plot axis

Separate plot axis (as prepared for the plot's
Angular template) into its own script. WTD-533
This commit is contained in:
Victor Woeltjen 2014-12-01 16:35:38 -08:00
parent bb708e9a05
commit e1298db760
6 changed files with 89 additions and 72 deletions

View File

@ -24,9 +24,9 @@
{{axes[1].active.name}} {{axes[1].active.name}}
</div> </div>
<div ng-repeat="tick in axes[1].ticks" <div ng-repeat="tick in rangeTicks"
class="gl-plot-tick gl-plot-y-tick-label" class="gl-plot-tick gl-plot-y-tick-label"
ng-style="{ bottom: (100 * $index / (axes[1].ticks.length - 1)) + '%' }"> ng-style="{ bottom: (100 * $index / (rangeTicks.length - 1)) + '%' }">
{{tick.label}} {{tick.label}}
</div> </div>
@ -48,14 +48,14 @@
<div class="gl-plot-hash hash-v" <div class="gl-plot-hash hash-v"
ng-repeat="tick in axes[0].ticks" ng-repeat="tick in domainTicks"
ng-style="{ left: (100 * $index / (axes[0].ticks.length - 1)) + '%', height: '100%' }" ng-style="{ left: (100 * $index / (domainTicks.length - 1)) + '%', height: '100%' }"
ng-show="$index > 0 && $index < (axes[0].ticks.length - 1)"> ng-show="$index > 0 && $index < (domainTicks.length - 1)">
</div> </div>
<div class="gl-plot-hash hash-h" <div class="gl-plot-hash hash-h"
ng-repeat="tick in axes[1].ticks" ng-repeat="tick in rangeTicks"
ng-style="{ bottom: (100 * $index / (axes[1].ticks.length - 1)) + '%', width: '100%' }" ng-style="{ bottom: (100 * $index / (rangeTicks.length - 1)) + '%', width: '100%' }"
ng-show="$index > 0 && $index < (axes[1].ticks.length - 1)"> ng-show="$index > 0 && $index < (rangeTicks.length - 1)">
</div> </div>
<mct-chart draw="draw" <mct-chart draw="draw"
@ -92,10 +92,10 @@
<div class="gl-plot-axis-area gl-plot-x"> <div class="gl-plot-axis-area gl-plot-x">
<div ng-repeat="tick in axes[0].ticks" <div ng-repeat="tick in domainTicks"
class="gl-plot-tick gl-plot-x-tick-label" class="gl-plot-tick gl-plot-x-tick-label"
ng-show="$index > 0 && $index < (axes[0].ticks.length - 1)" ng-show="$index > 0 && $index < (domainTicks.length - 1)"
ng-style="{ left: (100 * $index / (axes[0].ticks.length - 1)) + '%' }"> ng-style="{ left: (100 * $index / (domainTicks.length - 1)) + '%' }">
{{tick.label}} {{tick.label}}
</div> </div>

View File

@ -0,0 +1,35 @@
/*global define*/
define(
[],
function () {
"use strict";
function PlotAxis(axisType, metadatas, defaultValue) {
var keys = {},
options = [];
function buildOptionsForMetadata(m) {
(m[axisType] || []).forEach(function (option) {
if (!keys[option.key]) {
keys[option.key] = true;
options.push(option);
}
});
}
(metadatas || []).forEach(buildOptionsForMetadata);
// Plot axis will be used directly from the Angular
// template, so expose properties directly to facilitate
// two-way data binding (for drop-down menus)
return {
options: options,
active: options[0] || defaultValue
};
}
return PlotAxis;
}
);

View File

@ -10,9 +10,10 @@ define(
"./PlotPanZoomStack", "./PlotPanZoomStack",
"./PlotPosition", "./PlotPosition",
"./PlotTickGenerator", "./PlotTickGenerator",
"./PlotFormatter" "./PlotFormatter",
"./PlotAxis"
], ],
function (PlotPreparer, PlotPalette, PlotPanZoomStack, PlotPosition, PlotTickGenerator, PlotFormatter) { function (PlotPreparer, PlotPalette, PlotPanZoomStack, PlotPosition, PlotTickGenerator, PlotFormatter, PlotAxis) {
"use strict"; "use strict";
var AXIS_DEFAULTS = [ var AXIS_DEFAULTS = [
@ -41,22 +42,25 @@ define(
formatter.formatDomainValue)(v); formatter.formatDomainValue)(v);
} }
function mousePositionToDomainRange(mousePosition, domainOffset) { function mousePositionToDomainRange(mousePosition) {
return new PlotPosition( return new PlotPosition(
mousePosition.x, mousePosition.x,
mousePosition.y, mousePosition.y,
mousePosition.width, mousePosition.width,
mousePosition.height, mousePosition.height,
panZoomStack, panZoomStack
domainOffset
).getPosition(); ).getPosition();
} }
function toDisplayable(position) {
return [ position[0] - domainOffset, position[1] ];
}
function updateMarqueeBox() { function updateMarqueeBox() {
$scope.draw.boxes = marqueeStart ? $scope.draw.boxes = marqueeStart ?
[{ [{
start: mousePositionToDomainRange(marqueeStart), start: toDisplayable(mousePositionToDomainRange(marqueeStart)),
end: mousePositionToDomainRange(mousePosition), end: toDisplayable(mousePositionToDomainRange(mousePosition)),
color: [1, 1, 1, 0.5 ] color: [1, 1, 1, 0.5 ]
}] : undefined; }] : undefined;
} }
@ -65,11 +69,23 @@ define(
var panZoom = panZoomStack.getPanZoom(); var panZoom = panZoomStack.getPanZoom();
$scope.draw.dimensions = panZoom.dimensions; $scope.draw.dimensions = panZoom.dimensions;
$scope.draw.origin = panZoom.origin; $scope.draw.origin = [
panZoom.origin[0] - domainOffset,
panZoom.origin[1]
];
}
function updateTicks() {
var tickGenerator = new PlotTickGenerator(panZoomStack, formatter);
$scope.domainTicks =
tickGenerator.generateDomainTicks(DOMAIN_TICKS);
$scope.rangeTicks =
tickGenerator.generateRangeTicks(RANGE_TICKS);
} }
function plotTelemetry() { function plotTelemetry() {
var telemetry, prepared, tickGenerator, data; var telemetry, prepared, data;
telemetry = $scope.telemetry; telemetry = $scope.telemetry;
@ -85,13 +101,6 @@ define(
($scope.axes[1].active || {}).key ($scope.axes[1].active || {}).key
); );
tickGenerator = new PlotTickGenerator(prepared, formatter);
$scope.axes[0].ticks =
tickGenerator.generateDomainTicks(DOMAIN_TICKS);
$scope.axes[1].ticks =
tickGenerator.generateRangeTicks(RANGE_TICKS);
panZoomStack.setBasePanZoom( panZoomStack.setBasePanZoom(
prepared.getOrigin(), prepared.getOrigin(),
prepared.getDimensions() prepared.getDimensions()
@ -109,41 +118,14 @@ define(
updateDrawingBounds(); updateDrawingBounds();
updateMarqueeBox(); updateMarqueeBox();
updateTicks();
} }
function setupAxes(metadatas) { function setupAxes(metadatas) {
var domainKeys = {}, $scope.axes = [
rangeKeys = {}, new PlotAxis("domain", metadatas, AXIS_DEFAULTS[0]),
domains = [], new PlotAxis("range", metadatas, AXIS_DEFAULTS[1])
ranges = []; ];
function buildOptionsForMetadata(m) {
(m.domains || []).forEach(function (domain) {
if (!domainKeys[domain.key]) {
domainKeys[domain.key] = true;
domains.push(domain);
}
});
(m.ranges || []).forEach(function (range) {
if (!rangeKeys[range.key]) {
rangeKeys[range.key] = true;
ranges.push(range);
}
});
}
(metadatas || []).
forEach(buildOptionsForMetadata);
[domains, ranges].forEach(function (options, i) {
var active = $scope.axes[i].active;
$scope.axes[i].options = options;
if (!active || !active.key) {
$scope.axes[i].active =
options[0] || AXIS_DEFAULTS[i];
}
});
} }
function toMousePosition($event) { function toMousePosition($event) {
@ -171,9 +153,9 @@ define(
]; ];
panZoomStack.pushPanZoom(origin, dimensions); panZoomStack.pushPanZoom(origin, dimensions);
updateTicks();
} }
$scope.axes = [ {}, {} ];
$scope.$watch("telemetry.getMetadata()", setupAxes); $scope.$watch("telemetry.getMetadata()", setupAxes);
$scope.$on("telemetryUpdate", plotTelemetry); $scope.$on("telemetryUpdate", plotTelemetry);
$scope.draw = {}; $scope.draw = {};
@ -185,8 +167,7 @@ define(
getHoverCoordinates: function () { getHoverCoordinates: function () {
return mousePosition ? return mousePosition ?
mousePositionToDomainRange( mousePositionToDomainRange(
mousePosition, mousePosition
domainOffset
).map(formatValue) : []; ).map(formatValue) : [];
}, },
hover: function ($event) { hover: function ($event) {

View File

@ -5,9 +5,8 @@ define(
function () { function () {
"use strict"; "use strict";
function PlotPosition(x, y, width, height, panZoomStack, domainOffset) { function PlotPosition(x, y, width, height, panZoomStack) {
var panZoom = panZoomStack.getPanZoom(), var panZoom = panZoomStack.getPanZoom(),
offset = [ domainOffset || 0, 0 ],
origin = panZoom.origin, origin = panZoom.origin,
dimensions = panZoom.dimensions, dimensions = panZoom.dimensions,
position; position;
@ -16,7 +15,7 @@ define(
position = []; position = [];
} else { } else {
position = [ x / width, (height - y) / height ].map(function (v, i) { position = [ x / width, (height - y) / height ].map(function (v, i) {
return v * dimensions[i] + origin[i] + offset[i]; return v * dimensions[i] + origin[i];
}); });
} }

View File

@ -36,9 +36,9 @@ define(
vertices.push([]); vertices.push([]);
for (index = 0; index < data.getPointCount(); index = index + 1) { for (index = 0; index < data.getPointCount(); index = index + 1) {
x = data.getDomainValue(index, domain) - domainOffset; x = data.getDomainValue(index, domain);
y = data.getRangeValue(index, range); y = data.getRangeValue(index, range);
vertices[i].push(x); vertices[i].push(x - domainOffset);
vertices[i].push(y); vertices[i].push(y);
min[0] = Math.min(min[0], x); min[0] = Math.min(min[0], x);
min[1] = Math.min(min[1], y); min[1] = Math.min(min[1], y);

View File

@ -5,7 +5,7 @@ define(
function () { function () {
"use strict"; "use strict";
function PlotTickGenerator(preparer, formatter) { function PlotTickGenerator(panZoomStack, formatter) {
function generateTicks(start, span, count, format) { function generateTicks(start, span, count, format) {
var step = span / (count - 1), var step = span / (count - 1),
@ -24,17 +24,19 @@ define(
return { return {
generateDomainTicks: function (count) { generateDomainTicks: function (count) {
var panZoom = panZoomStack.getPanZoom();
return generateTicks( return generateTicks(
preparer.getOrigin()[0] + preparer.getDomainOffset(), panZoom.origin[0],
preparer.getDimensions()[0], panZoom.dimensions[0],
count, count,
formatter.formatDomainValue formatter.formatDomainValue
); );
}, },
generateRangeTicks: function (count) { generateRangeTicks: function (count) {
var panZoom = panZoomStack.getPanZoom();
return generateTicks( return generateTicks(
preparer.getOrigin()[1], panZoom.origin[1],
preparer.getDimensions()[1], panZoom.dimensions[1],
count, count,
formatter.formatRangeValue formatter.formatRangeValue
); );