mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
adding more options
This commit is contained in:
parent
6e80819140
commit
56569c4db6
8 changed files with 185 additions and 115 deletions
|
@ -14,6 +14,56 @@
|
|||
<div class="text-info text-center" ng-show="customColors" ng-click="resetColors()">reset colors</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="invertColors">
|
||||
Invert Color Schema
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<input class="kuiCheckBox" id="invertColors" type="checkbox" ng-model="vis.params.invertColors">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="axisScale">
|
||||
Color Scale
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<select
|
||||
id="axisScale"
|
||||
class="kuiSelect kuiSideBarSelect"
|
||||
ng-model="vis.params.scale"
|
||||
ng-options="mode for mode in vis.type.params.scales"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="defaultYExtents">
|
||||
Scale to Data Bounds
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<input class="kuiCheckBox" id="defaultYExtents" type="checkbox" ng-model="vis.params.defaultYExtents">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="percentageMode">
|
||||
Percentage Mode
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<input class="kuiCheckBox" id="percentageMode" type="checkbox" ng-model="vis.params.percentageMode">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="cellLabels">
|
||||
Show Cell Labels
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<input class="kuiCheckBox" id="cellLabels" type="checkbox" ng-model="vis.params.cellLabels">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="colorsNumber">
|
||||
Number of colors
|
||||
|
|
|
@ -9,7 +9,7 @@ module.directive('heatmapOptions', function ($parse, $compile, getAppState) {
|
|||
template: heatmapOptionsTemplate,
|
||||
replace: true,
|
||||
link: function ($scope) {
|
||||
$scope.isColorRangeOpen = false;
|
||||
$scope.isColorRangeOpen = true;
|
||||
$scope.customColors = false;
|
||||
|
||||
$scope.resetColors = () => {
|
||||
|
@ -43,11 +43,6 @@ module.directive('heatmapOptions', function ($parse, $compile, getAppState) {
|
|||
|
||||
$scope.uiState.on('colorChanged', () => {
|
||||
$scope.customColors = true;
|
||||
/*const appState = getAppState();
|
||||
$scope.realVis.params.colorSchema = 'custom';
|
||||
$scope.vis.params.colorSchema = 'custom';
|
||||
appState.vis.params.colorSchema = 'custom';
|
||||
appState.save();*/
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,29 +37,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="axisScale">
|
||||
Z Axis Scale
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<select
|
||||
id="axisScale"
|
||||
class="kuiSelect kuiSideBarSelect"
|
||||
ng-model="vis.params.scale"
|
||||
ng-options="mode for mode in vis.type.params.scales"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarFormRow">
|
||||
<label class="kuiSideBarFormRow__label" for="defaultYExtents">
|
||||
Scale to Data Bounds
|
||||
</label>
|
||||
<div class="kuiSideBarFormRow__control">
|
||||
<input class="kuiCheckBox" id="defaultYExtents" type="checkbox" ng-model="vis.params.defaultYExtents">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kuiSideBarSectionTitle">
|
||||
<div class="kuiSideBarSectionTitle__text">
|
||||
Heatmap Settings
|
||||
|
|
|
@ -24,9 +24,12 @@ export default function HeatmapVisType(Private) {
|
|||
defaultYExtents: false,
|
||||
setYExtents: false,
|
||||
colorsNumber: 4,
|
||||
colorSchema: 'yellow to red',
|
||||
colorSchema: 'Greens',
|
||||
setColorRange: false,
|
||||
colorsRange: [],
|
||||
invertColors: false,
|
||||
percentageMode: true,
|
||||
cellLabels: false,
|
||||
},
|
||||
legendPositions: [{
|
||||
value: 'left',
|
||||
|
@ -42,7 +45,8 @@ export default function HeatmapVisType(Private) {
|
|||
text: 'bottom',
|
||||
}],
|
||||
scales: ['linear', 'log', 'square root'],
|
||||
colorSchemas: ['yellow to red', 'reds', 'greens', 'blues', 'custom'],
|
||||
colorSchemas: ['Blues', 'Greens', 'Greys', 'Reds', 'YlOrRd', 'autumn', 'bone',
|
||||
'hot', 'coolwarm', 'Spectral', 'gist_earth', 'terrain', 'gnuplot', 'jet'],
|
||||
editor: heatmapTemplate
|
||||
},
|
||||
schemas: new Schemas([
|
||||
|
|
|
@ -1,36 +1,69 @@
|
|||
import _ from 'lodash';
|
||||
import colormaps from './colormaps';
|
||||
|
||||
const reds = [
|
||||
'#99000E', '#A41926', '#AF333E', '#BB4C56', '#C6666E', '#D17F86', '#DD999E', '#E8B2B6', '#F3CCCE', '#FFE6E6'
|
||||
];
|
||||
const greens = [
|
||||
'#E5F5F9', '#CBE1E0', '#B2CDC7', '#98BAAF', '#7FA696', '#65927D', '#4C7F65', '#326B4C', '#195733', '#00441B'
|
||||
];
|
||||
const blues = [
|
||||
'#DEEBF7', '#C6D6E7', '#AEC1D7', '#96ACC8', '#7E97B8', '#6783A9', '#4F6E99', '#37598A', '#1F447A', '#08306B'
|
||||
];
|
||||
const yellowtored = [
|
||||
'#F8F840', '#EEDA35', '#E4BC2A', '#DB9F1F', '#D18114', '#C8640A', '#D05415', '#D84520', '#E0362B', '#E82736'
|
||||
];
|
||||
|
||||
export default function (value, colorSchema) {
|
||||
if (!_.isNumber(value) || value < 0 || value > 9) {
|
||||
throw new Error('heatmap_color expects a number from 0 to 9 as first parameter');
|
||||
function enforceBounds(x) {
|
||||
if (x < 0) {
|
||||
return 0;
|
||||
} else if (x > 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
switch (colorSchema) {
|
||||
case 'reds':
|
||||
return reds[9 - value];
|
||||
case 'greens':
|
||||
return greens[value];
|
||||
case 'blues':
|
||||
return blues[value];
|
||||
case 'yellow to red':
|
||||
return yellowtored[value];
|
||||
default:
|
||||
const start = 120;
|
||||
const end = 360;
|
||||
const c = start + (end - start) * (value * 10);
|
||||
}
|
||||
|
||||
return `hsl(${c},60%,50%)`;
|
||||
function interpolateLinearly(x, values) {
|
||||
// Split values into four lists
|
||||
const xValues = [];
|
||||
const rValues = [];
|
||||
const gValues = [];
|
||||
const bValues = [];
|
||||
values.forEach(value => {
|
||||
xValues.push(value[0]);
|
||||
rValues.push(value[1][0]);
|
||||
gValues.push(value[1][1]);
|
||||
bValues.push(value[1][2]);
|
||||
});
|
||||
|
||||
let i = 1;
|
||||
while (xValues[i] < x) i++;
|
||||
const width = Math.abs(xValues[i - 1] - xValues[i]);
|
||||
const scalingFactor = (x - xValues[i - 1]) / width;
|
||||
// Get the new color values though interpolation
|
||||
const r = rValues[i - 1] + scalingFactor * (rValues[i] - rValues[i - 1]);
|
||||
const g = gValues[i - 1] + scalingFactor * (gValues[i] - gValues[i - 1]);
|
||||
const b = bValues[i - 1] + scalingFactor * (bValues[i] - bValues[i - 1]);
|
||||
return [enforceBounds(r), enforceBounds(g), enforceBounds(b)];
|
||||
}
|
||||
|
||||
function getColor(value, colorSchemaName) {
|
||||
if (!_.isNumber(value) || value < 0 || value > 1) {
|
||||
throw new Error('heatmap_color expects a number from 0 to 1 as first parameter');
|
||||
}
|
||||
};
|
||||
|
||||
const colorSchema = colormaps[colorSchemaName];
|
||||
if (!colorSchema) {
|
||||
throw new Error('invalid colorSchemaName provided');
|
||||
}
|
||||
|
||||
const color = interpolateLinearly(value, colorSchema);
|
||||
const r = Math.round(255 * color[0]);
|
||||
const g = Math.round(255 * color[1]);
|
||||
const b = Math.round(255 * color[2]);
|
||||
return `rgb(${r},${g},${b})`;
|
||||
}
|
||||
|
||||
function drawColormap(colorSchema, width = 100, height = 10) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
for (let i = 0; i <= width; i++) {
|
||||
ctx.fillStyle = getColor(i / width, colorSchema);
|
||||
ctx.fillRect(i, 0, 1, height);
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
|
||||
getColor.prototype.drawColormap = drawColormap;
|
||||
|
||||
export default getColor;
|
||||
|
|
|
@ -1,39 +1,8 @@
|
|||
import _ from 'lodash';
|
||||
import errors from 'ui/errors';
|
||||
import heatmapColorFunc from 'ui/vislib/components/color/heatmap_color';
|
||||
|
||||
export default function ColumnHandler(Private) {
|
||||
|
||||
const getHeatmapLabels = (cfg) => {
|
||||
const colorsNumber = cfg.colorsNumber;
|
||||
const labels = [];
|
||||
for (let i = 0; i < colorsNumber; i++) {
|
||||
let label;
|
||||
const val = Math.ceil(i * (100 / colorsNumber));
|
||||
if (cfg.setColorRange) {
|
||||
const greaterThan = cfg.colorsRange[i].value;
|
||||
label = `> ${greaterThan}`;
|
||||
} else {
|
||||
const nextVal = Math.ceil((i + 1) * (100 / colorsNumber));
|
||||
label = `${val}% - ${nextVal}%`;
|
||||
}
|
||||
labels.push(label);
|
||||
}
|
||||
return labels;
|
||||
};
|
||||
|
||||
const getHeatmapColors = (cfg) => {
|
||||
const colorsNumber = cfg.colorsNumber;
|
||||
const labels = getHeatmapLabels(cfg);
|
||||
const colors = {};
|
||||
for (let i in labels) {
|
||||
if (labels[i]) {
|
||||
colors[labels[i]] = heatmapColorFunc(Math.ceil(i * 10 / colorsNumber), cfg.colorSchema);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
const createSeries = (cfg, series) => {
|
||||
const stacked = ['stacked', 'percentage', 'wiggle', 'silhouette'].includes(cfg.mode);
|
||||
let interpolate = cfg.interpolate;
|
||||
|
@ -195,10 +164,6 @@ export default function ColumnHandler(Private) {
|
|||
text: data.get('yAxisLabel')
|
||||
}
|
||||
});
|
||||
defaults.legend = {
|
||||
labels: getHeatmapLabels(cfg),
|
||||
colors: getHeatmapColors(cfg)
|
||||
};
|
||||
return defaults;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -68,12 +68,6 @@ export default function VisFactory(Private) {
|
|||
|
||||
this.visConfig = new VisConfig(this.visConfigArgs, this.data, this.uiState, this.el);
|
||||
|
||||
const colors = this.getLegendColors();
|
||||
if (colors) {
|
||||
this.uiState.setSilent('vis.defaultColors', null);
|
||||
this.uiState.setSilent('vis.defaultColors', colors);
|
||||
}
|
||||
|
||||
this.handler = new Handler(this, this.visConfig);
|
||||
this._runWithoutResizeChecker('render');
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import VislibVisualizationsPointSeriesProvider from './_point_series';
|
||||
import colorFunc from 'ui/vislib/components/color/heatmap_color';
|
||||
import heatmapColorFunc from 'ui/vislib/components/color/heatmap_color';
|
||||
|
||||
export default function HeatmapChartFactory(Private) {
|
||||
|
||||
|
@ -25,8 +25,69 @@ export default function HeatmapChartFactory(Private) {
|
|||
constructor(handler, chartEl, chartData, seriesConfigArgs) {
|
||||
super(handler, chartEl, chartData, seriesConfigArgs);
|
||||
this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults);
|
||||
|
||||
this.handler.visConfig.set('legend', {
|
||||
labels: this.getHeatmapLabels(this.handler.visConfig),
|
||||
colors: this.getHeatmapColors(this.handler.visConfig)
|
||||
});
|
||||
|
||||
const colors = this.handler.visConfig.get('legend.colors', null);
|
||||
if (colors) {
|
||||
this.handler.vis.uiState.setSilent('vis.defaultColors', null);
|
||||
this.handler.vis.uiState.setSilent('vis.defaultColors', colors);
|
||||
}
|
||||
}
|
||||
|
||||
getHeatmapLabels(cfg) {
|
||||
const percentageMode = cfg.get('percentageMode');
|
||||
const colorsNumber = cfg.get('colorsNumber');
|
||||
const colorsRange = cfg.get('colorsRange');
|
||||
const zScale = this.getValueAxis().getScale();
|
||||
const [min, max] = zScale.domain();
|
||||
const labels = [];
|
||||
for (let i = 0; i < colorsNumber; i++) {
|
||||
let label;
|
||||
|
||||
if (cfg.get('setColorRange')) {
|
||||
const greaterThan = colorsRange[i].value;
|
||||
label = `> ${greaterThan}`;
|
||||
} else {
|
||||
let val = i / colorsNumber;
|
||||
let nextVal = (i + 1) / colorsNumber;
|
||||
if (percentageMode) {
|
||||
val = Math.ceil(val * 100);
|
||||
nextVal = Math.ceil(nextVal * 100);
|
||||
label = `${val}% - ${nextVal}%`;
|
||||
} else {
|
||||
val = val * (max - min) + min;
|
||||
nextVal = nextVal * (max - min) + min;
|
||||
if (max > 1) {
|
||||
val = Math.ceil(val);
|
||||
nextVal = Math.ceil(nextVal);
|
||||
}
|
||||
label = `${val} - ${nextVal}`;
|
||||
}
|
||||
}
|
||||
labels.push(label);
|
||||
}
|
||||
return labels;
|
||||
};
|
||||
|
||||
getHeatmapColors(cfg) {
|
||||
const colorsNumber = cfg.get('colorsNumber');
|
||||
const invertColors = cfg.get('invertColors');
|
||||
const colorSchema = cfg.get('colorSchema');
|
||||
const labels = this.getHeatmapLabels(cfg);
|
||||
const colors = {};
|
||||
for (let i in labels) {
|
||||
if (labels[i]) {
|
||||
const val = invertColors ? 1 - i / colorsNumber : i / colorsNumber;
|
||||
colors[labels[i]] = heatmapColorFunc(val, colorSchema);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
addSquares(svg, data) {
|
||||
const xScale = this.getCategoryAxis().getScale();
|
||||
const yScale = this.handler.valueAxes[1].getScale();
|
||||
|
@ -39,6 +100,7 @@ export default function HeatmapChartFactory(Private) {
|
|||
const setColorRange = this.handler.visConfig.get('setColorRange');
|
||||
const colorsRange = this.handler.visConfig.get('colorsRange');
|
||||
const color = this.handler.data.getColorFunc();
|
||||
const labels = this.handler.visConfig.get('legend.labels');
|
||||
|
||||
const layer = svg.append('g')
|
||||
.attr('class', 'series');
|
||||
|
@ -89,17 +151,7 @@ export default function HeatmapChartFactory(Private) {
|
|||
|
||||
function label(d) {
|
||||
const colorBucket = getColorBucket(d);
|
||||
let label;
|
||||
if (colorBucket < 0) return '';
|
||||
const val = Math.ceil(colorBucket * (100 / colorsNumber));
|
||||
if (setColorRange) {
|
||||
const greaterThan = colorsRange[colorBucket].value;
|
||||
label = `> ${greaterThan}`;
|
||||
} else {
|
||||
const nextVal = Math.ceil((colorBucket + 1) * (100 / colorsNumber));
|
||||
label = `${val}% - ${nextVal}%`;
|
||||
}
|
||||
return label;
|
||||
return labels[colorBucket];
|
||||
}
|
||||
|
||||
function z(d) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue