ソースを参照

[color] configure default color handling

tags/1.2.0
Prateeksha Singh 7年前
コミット
786b8b1ecf
15個のファイルの変更166行の追加201行の削除
  1. +75
    -92
      dist/frappe-charts.esm.js
  2. +1
    -1
      dist/frappe-charts.min.cjs.js
  3. +1
    -1
      dist/frappe-charts.min.esm.js
  4. +1
    -1
      dist/frappe-charts.min.iife.js
  5. +1
    -1
      dist/frappe-charts.min.iife.js.map
  6. +1
    -1
      docs/assets/js/frappe-charts.min.js
  7. +1
    -1
      docs/assets/js/frappe-charts.min.js.map
  8. +3
    -3
      docs/assets/js/index.js
  9. +2
    -2
      docs/index.html
  10. +1
    -1
      src/js/charts/AxisChart.js
  11. +45
    -24
      src/js/charts/BaseChart.js
  12. +3
    -23
      src/js/charts/Heatmap.js
  13. +0
    -46
      src/js/config.js
  14. +0
    -3
      src/js/utils/colors.js
  15. +31
    -1
      src/js/utils/constants.js

+ 75
- 92
dist/frappe-charts.esm.js ファイルの表示

@@ -206,6 +206,24 @@ class SvgTip {
}
}

const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];

const COMPATIBLE_CHARTS = {
bar: ['line', 'scatter', 'percentage', 'pie'],
line: ['scatter', 'bar', 'percentage', 'pie'],
pie: ['line', 'scatter', 'percentage', 'bar'],
percentage: ['bar', 'line', 'scatter', 'pie'],
heatmap: []
};

const DATA_COLOR_DIVISIONS = {
bar: 'datasets',
line: 'datasets',
pie: 'labels',
percentage: 'labels',
heatmap: HEATMAP_DISTRIBUTION_SIZE
};

const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
const TRANSLATE_Y_BASE_CHART = 20;
const LEFT_MARGIN_BASE_CHART = 60;
@@ -234,6 +252,18 @@ const FULL_ANGLE = 360;
// More colors are difficult to parse visually
const HEATMAP_DISTRIBUTION_SIZE = 5;

const HEATMAP_COLORS = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
const DEFAULT_CHART_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];

const DEFAULT_COLORS = {
bar: DEFAULT_CHART_COLORS,
line: DEFAULT_CHART_COLORS,
pie: DEFAULT_CHART_COLORS,
percentage: DEFAULT_CHART_COLORS,
heatmap: HEATMAP_COLORS
};

function floatTwo(d) {
return parseFloat(d.toFixed(2));
}
@@ -891,9 +921,6 @@ const PRESET_COLOR_MAP = {
'dark-grey': '#b8c2cc'
};

const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];

function limitColor(r){
if (r > 255) return 255;
else if (r < 0) return 0;
@@ -923,51 +950,6 @@ const getColor = (color) => {
return PRESET_COLOR_MAP[color] || color;
};

const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];

const COMPATIBLE_CHARTS = {
bar: ['line', 'scatter', 'percentage', 'pie'],
line: ['scatter', 'bar', 'percentage', 'pie'],
pie: ['line', 'scatter', 'percentage', 'bar'],
scatter: ['line', 'bar', 'percentage', 'pie'],
percentage: ['bar', 'line', 'scatter', 'pie'],
heatmap: []
};

// Needs structure as per only labels/datasets
const COLOR_COMPATIBLE_CHARTS = {
bar: ['line', 'scatter'],
line: ['scatter', 'bar'],
pie: ['percentage'],
scatter: ['line', 'bar'],
percentage: ['pie'],
heatmap: []
};

function getDifferentChart(type, current_type, parent, args) {
if(type === current_type) return;

if(!ALL_CHART_TYPES.includes(type)) {
console.error(`'${type}' is not a valid chart type.`);
}

if(!COMPATIBLE_CHARTS[current_type].includes(type)) {
console.error(`'${current_type}' chart cannot be converted to a '${type}' chart.`);
}

// whether the new chart can use the existing colors
const useColor = COLOR_COMPATIBLE_CHARTS[current_type].includes(type);

// Okay, this is anticlimactic
// this function will need to actually be 'changeChartType(type)'
// that will update only the required elements, but for now ...

args.type = type;
args.colors = useColor ? args.colors : undefined;

return new Chart(parent, args);
}

const UNIT_ANIM_DUR = 350;
const PATH_ANIM_DUR = 350;
const MARKER_LINE_ANIM_DUR = UNIT_ANIM_DUR;
@@ -1188,13 +1170,13 @@ function runSMILAnimation(parent, svgElement, elementsToAnimate) {

class BaseChart {
constructor(parent, options) {
this.rawChartArgs = options;

this.parent = typeof parent === 'string' ? document.querySelector(parent) : parent;
if (!(this.parent instanceof HTMLElement)) {
throw new Error('No `parent` element to render on was provided.');
}

this.rawChartArgs = options;

this.title = options.title || '';
this.subtitle = options.subtitle || '';
this.argHeight = options.height || 240;
@@ -1202,7 +1184,10 @@ class BaseChart {

this.realData = this.prepareData(options.data);
this.data = this.prepareFirstData(this.realData);
this.colors = [];

this.colors = this.validateColors(options.colors)
.concat(DEFAULT_COLORS[this.type]);

this.config = {
showTooltip: 1, // calculate
showLegend: options.showLegend || 1,
@@ -1221,8 +1206,7 @@ class BaseChart {
this.configure(options);
}

configure(args) {
this.setColors(args);
configure() {
this.setMargins();

// Bind window events
@@ -1230,21 +1214,17 @@ class BaseChart {
window.addEventListener('orientationchange', () => this.draw(true));
}

setColors() {
let args = this.rawChartArgs;

// Needs structure as per only labels/datasets, from config
const list = args.type === 'percentage' || args.type === 'pie'
? args.data.labels
: args.data.datasets;

if(!args.colors || (list && args.colors.length < list.length)) {
this.colors = DEFAULT_COLORS;
} else {
this.colors = args.colors;
}

this.colors = this.colors.map(color => getColor(color));
validateColors(colors = []) {
const validColors = [];
colors.forEach((string) => {
const color = getColor(string);
if(!isValidColor(color)) {
console.warn('"' + string + '" is not a valid color.');
} else {
validColors.push(color);
}
});
return validColors;
}

setMargins() {
@@ -1456,7 +1436,29 @@ class BaseChart {
updateDataset() {}

getDifferentChart(type) {
return getDifferentChart(type, this.type, this.parent, this.rawChartArgs);
const currentType = this.type;
let args = this.rawChartArgs;
if(type === currentType) return;

if(!ALL_CHART_TYPES.includes(type)) {
console.error(`'${type}' is not a valid chart type.`);
}

if(!COMPATIBLE_CHARTS[currentType].includes(type)) {
console.error(`'${currentType}' chart cannot be converted to a '${type}' chart.`);
}

// whether the new chart can use the existing colors
const useColor = DATA_COLOR_DIVISIONS[currentType] === DATA_COLOR_DIVISIONS[type];

// Okay, this is anticlimactic
// this function will need to actually be 'changeChartType(type)'
// that will update only the required elements, but for now ...

args.type = type;
args.colors = useColor ? args.colors : undefined;

return new Chart(this.parent, args);
}

unbindWindowEvents(){
@@ -2383,11 +2385,6 @@ class Heatmap extends BaseChart {
let today = new Date();
this.start = options.start || addDays(today, 365);

let legendColors = (options.legendColors || []).slice(0, 5);
this.legendColors = this.validate_colors(legendColors)
? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];

this.translateX = 0;
this.setup();
}
@@ -2398,22 +2395,8 @@ class Heatmap extends BaseChart {
this.translateY = 10;
}

validate_colors(colors) {
if(colors.length < 5) return 0;

let valid = 1;
colors.forEach(function(string) {
if(!isValidColor(string)) {
valid = 0;
console.warn('"' + string + '" is not a valid color.');
}
}, this);

return valid;
}

configure() {
super.configure();
configure(args) {
super.configure(args);
this.today = new Date();

if(!this.start) {
@@ -2542,7 +2525,7 @@ class Heatmap extends BaseChart {
};

let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legendColors[colorIndex], dataAttr);
this.colors[colorIndex], dataAttr);

dataGroup.appendChild(heatSquare);

@@ -2758,7 +2741,7 @@ class AxisChart extends BaseChart {
}

configure(args) {
super.configure();
super.configure(args);

args.axisOptions = args.axisOptions || {};
args.tooltipOptions = args.tooltipOptions || {};


+ 1
- 1
dist/frappe-charts.min.cjs.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
dist/frappe-charts.min.esm.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
dist/frappe-charts.min.iife.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
dist/frappe-charts.min.iife.js.map
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
docs/assets/js/frappe-charts.min.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
docs/assets/js/frappe-charts.min.js.map
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 3
- 3
docs/assets/js/index.js ファイルの表示

@@ -455,7 +455,7 @@ let heatmap = new frappe.Chart("#chart-heatmap", {
legendScale: [0, 1, 2, 4, 5],
height: 115,
discreteDomains: 1,
legendColors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c']
colors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c']
});

console.log(heatmapData, heatmap);
@@ -486,7 +486,7 @@ Array.prototype.slice.call(
legendScale: [0, 1, 2, 4, 5],
height: 115,
discreteDomains: discreteDomains,
legendColors: colors
colors: colors
});

Array.prototype.slice.call(
@@ -524,7 +524,7 @@ Array.prototype.slice.call(
legendScale: [0, 1, 2, 4, 5],
height: 115,
discreteDomains: discreteDomains,
legendColors: colors
colors: colors
});

Array.prototype.slice.call(


+ 2
- 2
docs/index.html ファイルの表示

@@ -203,7 +203,7 @@
// default: today's date in past year
// for an annual heatmap

legendColors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'],
colors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'],
// Set of five incremental colors,
// beginning with a low-saturation color for zero data;
// default: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']
@@ -264,7 +264,7 @@

discreteDomains: 1, // default: 1
start: startDate, // Date object
legendColors: []
colors: []
}
...



+ 1
- 1
src/js/charts/AxisChart.js ファイルの表示

@@ -22,7 +22,7 @@ export default class AxisChart extends BaseChart {
}

configure(args) {
super.configure();
super.configure(args);

args.axisOptions = args.axisOptions || {};
args.tooltipOptions = args.tooltipOptions || {};


+ 45
- 24
src/js/charts/BaseChart.js ファイルの表示

@@ -2,20 +2,21 @@ import SvgTip from '../objects/SvgTip';
import { $, isElementInViewport, getElementContentWidth } from '../utils/dom';
import { makeSVGContainer, makeSVGDefs, makeSVGGroup } from '../utils/draw';
import { VERT_SPACE_OUTSIDE_BASE_CHART, TRANSLATE_Y_BASE_CHART, LEFT_MARGIN_BASE_CHART,
RIGHT_MARGIN_BASE_CHART, INIT_CHART_UPDATE_TIMEOUT, CHART_POST_ANIMATE_TIMEOUT } from '../utils/constants';
import { getColor, DEFAULT_COLORS } from '../utils/colors';
import { getDifferentChart } from '../config';
RIGHT_MARGIN_BASE_CHART, INIT_CHART_UPDATE_TIMEOUT, CHART_POST_ANIMATE_TIMEOUT, DEFAULT_COLORS,
ALL_CHART_TYPES, COMPATIBLE_CHARTS, DATA_COLOR_DIVISIONS} from '../utils/constants';
import { getColor, isValidColor } from '../utils/colors';
import { runSMILAnimation } from '../utils/animation';
import { Chart } from '../chart';

export default class BaseChart {
constructor(parent, options) {
this.rawChartArgs = options;

this.parent = typeof parent === 'string' ? document.querySelector(parent) : parent;
if (!(this.parent instanceof HTMLElement)) {
throw new Error('No `parent` element to render on was provided.');
}

this.rawChartArgs = options;

this.title = options.title || '';
this.subtitle = options.subtitle || '';
this.argHeight = options.height || 240;
@@ -23,7 +24,10 @@ export default class BaseChart {

this.realData = this.prepareData(options.data);
this.data = this.prepareFirstData(this.realData);
this.colors = [];

this.colors = this.validateColors(options.colors)
.concat(DEFAULT_COLORS[this.type]);

this.config = {
showTooltip: 1, // calculate
showLegend: options.showLegend || 1,
@@ -42,8 +46,7 @@ export default class BaseChart {
this.configure(options);
}

configure(args) {
this.setColors(args);
configure() {
this.setMargins();

// Bind window events
@@ -51,21 +54,17 @@ export default class BaseChart {
window.addEventListener('orientationchange', () => this.draw(true));
}

setColors() {
let args = this.rawChartArgs;

// Needs structure as per only labels/datasets, from config
const list = args.type === 'percentage' || args.type === 'pie'
? args.data.labels
: args.data.datasets;

if(!args.colors || (list && args.colors.length < list.length)) {
this.colors = DEFAULT_COLORS;
} else {
this.colors = args.colors;
}

this.colors = this.colors.map(color => getColor(color));
validateColors(colors = []) {
const validColors = [];
colors.forEach((string) => {
const color = getColor(string);
if(!isValidColor(color)) {
console.warn('"' + string + '" is not a valid color.');
} else {
validColors.push(color);
}
});
return validColors;
}

setMargins() {
@@ -277,7 +276,29 @@ export default class BaseChart {
updateDataset() {}

getDifferentChart(type) {
return getDifferentChart(type, this.type, this.parent, this.rawChartArgs);
const currentType = this.type;
let args = this.rawChartArgs;
if(type === currentType) return;

if(!ALL_CHART_TYPES.includes(type)) {
console.error(`'${type}' is not a valid chart type.`);
}

if(!COMPATIBLE_CHARTS[currentType].includes(type)) {
console.error(`'${currentType}' chart cannot be converted to a '${type}' chart.`);
}

// whether the new chart can use the existing colors
const useColor = DATA_COLOR_DIVISIONS[currentType] === DATA_COLOR_DIVISIONS[type];

// Okay, this is anticlimactic
// this function will need to actually be 'changeChartType(type)'
// that will update only the required elements, but for now ...

args.type = type;
args.colors = useColor ? args.colors : undefined;

return new Chart(this.parent, args);
}

unbindWindowEvents(){


+ 3
- 23
src/js/charts/Heatmap.js ファイルの表示

@@ -2,7 +2,6 @@ import BaseChart from './BaseChart';
import { makeSVGGroup, makeHeatSquare, makeText } from '../utils/draw';
import { addDays, getDdMmYyyy, getWeeksBetween } from '../utils/date-utils';
import { calcDistribution, getMaxCheckpoint } from '../utils/intervals';
import { isValidColor } from '../utils/colors';
import { HEATMAP_DISTRIBUTION_SIZE } from '../utils/constants';

export default class Heatmap extends BaseChart {
@@ -17,11 +16,6 @@ export default class Heatmap extends BaseChart {
let today = new Date();
this.start = options.start || addDays(today, 365);

let legendColors = (options.legendColors || []).slice(0, 5);
this.legendColors = this.validate_colors(legendColors)
? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];

this.translateX = 0;
this.setup();
}
@@ -32,22 +26,8 @@ export default class Heatmap extends BaseChart {
this.translateY = 10;
}

validate_colors(colors) {
if(colors.length < 5) return 0;

let valid = 1;
colors.forEach(function(string) {
if(!isValidColor(string)) {
valid = 0;
console.warn('"' + string + '" is not a valid color.');
}
}, this);

return valid;
}

configure() {
super.configure();
configure(args) {
super.configure(args);
this.today = new Date();

if(!this.start) {
@@ -176,7 +156,7 @@ export default class Heatmap extends BaseChart {
};

let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legendColors[colorIndex], dataAttr);
this.colors[colorIndex], dataAttr);

dataGroup.appendChild(heatSquare);



+ 0
- 46
src/js/config.js ファイルの表示

@@ -1,46 +0,0 @@
import { Chart } from './chart';

const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];

const COMPATIBLE_CHARTS = {
bar: ['line', 'scatter', 'percentage', 'pie'],
line: ['scatter', 'bar', 'percentage', 'pie'],
pie: ['line', 'scatter', 'percentage', 'bar'],
scatter: ['line', 'bar', 'percentage', 'pie'],
percentage: ['bar', 'line', 'scatter', 'pie'],
heatmap: []
};

// Needs structure as per only labels/datasets
const COLOR_COMPATIBLE_CHARTS = {
bar: ['line', 'scatter'],
line: ['scatter', 'bar'],
pie: ['percentage'],
scatter: ['line', 'bar'],
percentage: ['pie'],
heatmap: []
};

export function getDifferentChart(type, current_type, parent, args) {
if(type === current_type) return;

if(!ALL_CHART_TYPES.includes(type)) {
console.error(`'${type}' is not a valid chart type.`);
}

if(!COMPATIBLE_CHARTS[current_type].includes(type)) {
console.error(`'${current_type}' chart cannot be converted to a '${type}' chart.`);
}

// whether the new chart can use the existing colors
const useColor = COLOR_COMPATIBLE_CHARTS[current_type].includes(type);

// Okay, this is anticlimactic
// this function will need to actually be 'changeChartType(type)'
// that will update only the required elements, but for now ...

args.type = type;
args.colors = useColor ? args.colors : undefined;

return new Chart(parent, args);
}

+ 0
- 3
src/js/utils/colors.js ファイルの表示

@@ -15,9 +15,6 @@ const PRESET_COLOR_MAP = {
'dark-grey': '#b8c2cc'
};

export const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];

function limitColor(r){
if (r > 255) return 255;
else if (r < 0) return 0;


+ 31
- 1
src/js/utils/constants.js ファイルの表示

@@ -1,3 +1,21 @@
export const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];

export const COMPATIBLE_CHARTS = {
bar: ['line', 'scatter', 'percentage', 'pie'],
line: ['scatter', 'bar', 'percentage', 'pie'],
pie: ['line', 'scatter', 'percentage', 'bar'],
percentage: ['bar', 'line', 'scatter', 'pie'],
heatmap: []
};

export const DATA_COLOR_DIVISIONS = {
bar: 'datasets',
line: 'datasets',
pie: 'labels',
percentage: 'labels',
heatmap: HEATMAP_DISTRIBUTION_SIZE
}

export const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
export const TRANSLATE_Y_BASE_CHART = 20;
export const LEFT_MARGIN_BASE_CHART = 60;
@@ -24,4 +42,16 @@ export const FULL_ANGLE = 360;

// Fixed 5-color theme,
// More colors are difficult to parse visually
export const HEATMAP_DISTRIBUTION_SIZE = 5;
export const HEATMAP_DISTRIBUTION_SIZE = 5;

const HEATMAP_COLORS = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
const DEFAULT_CHART_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
'yellow', 'green', 'light-green', 'purple', 'magenta', 'light-grey', 'dark-grey'];

export const DEFAULT_COLORS = {
bar: DEFAULT_CHART_COLORS,
line: DEFAULT_CHART_COLORS,
pie: DEFAULT_CHART_COLORS,
percentage: DEFAULT_CHART_COLORS,
heatmap: HEATMAP_COLORS
}

読み込み中…
キャンセル
保存