import { FieldType } from 'muze-utils';
import { defaultConfig } from './default-config';
import { LineLayer } from '../line';
import drawArea from './renderer';
import './styles.scss';
import { STACK, ENCODING } from '../../enums/constants';
import { getAxesScales, positionPoints, getLayerColor, getIndividualClassName } from '../../helpers';
/**
* Area layer renders a closed path. The mark type of this layer is ```area```. This layer can be used
* to create stacked or multi-series areas and vertical range area plots by using the encoding properties.
*
* To create this layer using layer configuration from canvas,
* ```
* canvas.layers([{
* mark: 'area',
* transform: {
* type: 'stack' // Produces a stacked area.
* }
* }]);
* ```
*
* @public
*
* @class
* @module AreaLayer
* @extends LineLayer
*/
export default class AreaLayer extends LineLayer {
/** oation of line layer
* @return {Object} Default configuration of layer
*/
static defaultConfig () {
return defaultConfig;
}
/**
*
*
* @static
*
* @memberof AreaLayer
*/
static formalName () {
return 'area';
}
/**
* Calculates the domain from data. It calls its parent class's method which is line layer
* to get the domain and overwrites the domain according to its need.
* @return {Array} Domain values
*/
calculateDomainFromData (data, encodingFieldsInf, fieldsConfig) {
const domains = super.calculateDomainFromData(data, fieldsConfig);
[ENCODING.X, ENCODING.Y].forEach((type) => {
const { [`${type}FieldType`]: fieldType } = encodingFieldsInf;
if (fieldType === FieldType.MEASURE) {
domains[type][0] = Math.min(domains[type][0], 0);
}
});
return domains;
}
/**
* Returns the drawing method of this layer
* @return {Function} Draw method
*/
getDrawFn () {
return drawArea;
}
/**
* Generates the x and y positions for each point
* @param {Array} data Data Array
* @param {Object} encoding Visual Encodings of the layer
* @param {Object} axes Contains the axis
* @return {Array} Array of points
*/
translatePoints (data, encodingFieldsInf, axes) {
let points = [];
const transformType = this.transformType();
const colorAxis = axes.color;
const config = this.config();
const encoding = config.encoding;
const colorEncoding = encoding.color;
const colorField = colorEncoding.field;
const fieldsConfig = this.data().getFieldsConfig();
const colorFieldIndex = colorField && fieldsConfig[colorField].index;
const { xField, yField, y0Field } = encodingFieldsInf;
const {
xAxis,
yAxis
} = getAxesScales(axes);
const classNameFn = config.individualClassName;
const isXDim = fieldsConfig[xField] && fieldsConfig[xField].def.type === FieldType.DIMENSION;
const isYDim = fieldsConfig[yField] && fieldsConfig[yField].def.type === FieldType.DIMENSION;
const key = isXDim ? 'x' : (isYDim ? 'y' : null);
points = data.map((d, i) => {
const xPx = xAxis.getScaleValue(d.x) + xAxis.getUnitWidth() / 2;
const yPx = yAxis.getScaleValue(d.y);
const y0Px = (y0Field || transformType === STACK) ? yAxis.getScaleValue(d.y0) : yAxis.getScaleValue(0);
const { color, rawColor } = getLayerColor({ datum: d, index: i }, {
colorEncoding, colorAxis, colorFieldIndex });
const style = {};
const meta = {};
style.fill = color;
// style['fill-opacity'] = 0;
meta.stateColor = {};
meta.originalColor = rawColor;
meta.colorTransform = {};
const point = {
enter: {
x: xPx,
y: d.y === null ? d.y : yAxis.getScaleValue(0),
y0: d.y0 === null ? d.y0 : yAxis.getScaleValue(0)
},
update: {
x: xPx,
y: d.y === null ? d.y : yPx,
y0: d.y0 === null ? d.y0 : y0Px
},
_id: d._id,
_data: d._data,
source: d._data,
rowId: d._id,
className: classNameFn ? classNameFn(d, i, data, this) : '',
style,
meta
};
point.className = getIndividualClassName(d, i, data, this);
this.cachePoint(d[key], point);
return point;
});
points = positionPoints(this, points);
return points;
}
/**
* Get the css styles need to be applied on the line path
* @param {string} color Color value
* @return {Object} Path styles
*/
getPathStyle (color) {
return {
fill: color
};
}
}