-
Notifications
You must be signed in to change notification settings - Fork 592
/
encode.js
139 lines (139 loc) · 5.45 KB
/
encode.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { isArray } from 'vega-util';
import { COLOR, OPACITY, SHAPE } from '../../channel';
import { hasConditionalValueDef, isTimeFormatFieldDef, isValueDef } from '../../channeldef';
import { AREA, BAR, CIRCLE, FILL_STROKE_CONFIG, GEOSHAPE, LINE, POINT, SQUARE, TEXT, TICK } from '../../mark';
import { ScaleType } from '../../scale';
import { getFirstDefined, keys } from '../../util';
import { applyMarkConfig, timeFormatExpression } from '../common';
import * as mixins from '../mark/mixins';
import { defaultType } from './properties';
function type(legendCmp, model, channel) {
const scaleType = model.getScaleComponent(channel).get('type');
return getFirstDefined(legendCmp.get('type'), defaultType({ channel, scaleType, alwaysReturn: true }));
}
export function symbols(fieldDef, symbolsSpec, model, channel, legendCmp) {
if (type(legendCmp, model, channel) !== 'symbol') {
return undefined;
}
let out = Object.assign({}, applyMarkConfig({}, model, FILL_STROKE_CONFIG), mixins.color(model)); // FIXME: remove this when VgEncodeEntry is compatible with SymbolEncodeEntry
switch (model.mark) {
case BAR:
case TICK:
case TEXT:
out.shape = { value: 'square' };
break;
case CIRCLE:
case SQUARE:
out.shape = { value: model.mark };
break;
case POINT:
case LINE:
case GEOSHAPE:
case AREA:
// use default circle
break;
}
const { markDef, encoding, config } = model;
const filled = markDef.filled;
const opacity = getMaxValue(encoding.opacity) || markDef.opacity;
if (out.fill) {
// for fill legend, we don't want any fill in symbol
if (channel === 'fill' || (filled && channel === COLOR)) {
delete out.fill;
}
else {
if (out.fill['field']) {
// For others, set fill to some opaque value (or nothing if a color is already set)
if (legendCmp.get('symbolFillColor')) {
delete out.fill;
}
else {
out.fill = { value: config.legend.symbolBaseFillColor || 'black' };
out.fillOpacity = { value: opacity || 1 };
}
}
else if (isArray(out.fill)) {
const fill = getFirstConditionValue(encoding.fill || encoding.color) ||
markDef.fill ||
(filled && markDef.color);
if (fill) {
out.fill = { value: fill };
}
}
}
}
if (out.stroke) {
if (channel === 'stroke' || (!filled && channel === COLOR)) {
delete out.stroke;
}
else {
if (out.stroke['field']) {
// For others, remove stroke field
delete out.stroke;
}
else if (isArray(out.stroke)) {
const stroke = getFirstDefined(getFirstConditionValue(encoding.stroke || encoding.color), markDef.stroke, filled ? markDef.color : undefined);
if (stroke) {
out.stroke = { value: stroke };
}
}
}
}
if (channel !== SHAPE) {
const shape = getFirstConditionValue(encoding.shape) || markDef.shape;
if (shape) {
out.shape = { value: shape };
}
}
if (channel !== OPACITY) {
if (opacity) {
// only apply opacity if it is neither zero or undefined
out.opacity = { value: opacity };
}
}
out = Object.assign({}, out, symbolsSpec);
return keys(out).length > 0 ? out : undefined;
}
export function gradient(fieldDef, gradientSpec, model, channel, legendCmp) {
if (type(legendCmp, model, channel) !== 'gradient') {
return undefined;
}
let out = {};
const opacity = getMaxValue(model.encoding.opacity) || model.markDef.opacity;
if (opacity) {
// only apply opacity if it is neither zero or undefined
out.opacity = { value: opacity };
}
out = Object.assign({}, out, gradientSpec);
return keys(out).length > 0 ? out : undefined;
}
export function labels(fieldDef, labelsSpec, model, channel, legendCmp) {
const legend = model.legend(channel);
const config = model.config;
let out = {};
if (isTimeFormatFieldDef(fieldDef)) {
const isUTCScale = model.getScaleComponent(channel).get('type') === ScaleType.UTC;
const expr = timeFormatExpression('datum.value', fieldDef.timeUnit, legend.format, config.legend.shortTimeLabels, config.timeFormat, isUTCScale);
labelsSpec = Object.assign({}, (expr ? { text: { signal: expr } } : {}), labelsSpec);
}
out = Object.assign({}, out, labelsSpec);
return keys(out).length > 0 ? out : undefined;
}
function getMaxValue(channelDef) {
return getConditionValue(channelDef, (v, conditionalDef) => Math.max(v, conditionalDef.value));
}
function getFirstConditionValue(channelDef) {
return getConditionValue(channelDef, (v, conditionalDef) => {
return getFirstDefined(v, conditionalDef.value);
});
}
function getConditionValue(channelDef, reducer) {
if (hasConditionalValueDef(channelDef)) {
return (isArray(channelDef.condition) ? channelDef.condition : [channelDef.condition]).reduce(reducer, channelDef.value);
}
else if (isValueDef(channelDef)) {
return channelDef.value;
}
return undefined;
}
//# sourceMappingURL=encode.js.map