import * as d3 from "d3"; import { convertValueToAttribute, OrientationEnum, Theme } from "../mmviz-common/index"; import {Layout, createViewModel} from "./layout"; import {LayoutScale} from "./scale"; export function boxLayoutCreator(orientationEnum = OrientationEnum.VERTICAL) { let theme: Theme = Theme.getInstance(); // layout extender return function(dataModel, layoutScale: LayoutScale){ let domain = [dataModel.lowerWhisker, dataModel.upperWhisker], outlierDomain = [], padding, boxStart, boxWidth, boxMidPoint, outliers = dataModel.outliers.slice(0), hasMax = dataModel.max !== undefined, hasMin = dataModel.min !== undefined ; if(hasMax) { outliers.push(dataModel.max); } if(hasMin) { outliers.push(dataModel.min); } if (outliers.length > 0) { outlierDomain = d3.extent(outliers); } if (outlierDomain[0] < domain[0]) { domain[0] = outlierDomain[0]; } if (outlierDomain[1] > domain[1]) { domain[1] = outlierDomain[1]; } if (OrientationEnum.VERTICAL === orientationEnum) { layoutScale.extendDomainY(domain); padding = layoutScale.drawArea.drawWidth * 0.1; boxStart = layoutScale.drawArea.left + padding; boxWidth = layoutScale.drawArea.drawWidth * 0.8; boxMidPoint = boxStart + (boxWidth * 0.5); } else if (OrientationEnum.HORIZONTAL === orientationEnum) { layoutScale.extendDomainX(domain); padding = layoutScale.drawArea.drawHeight * 0.1; boxStart = layoutScale.drawArea.top + padding; boxWidth = layoutScale.drawArea.drawHeight * 0.8; boxMidPoint = boxStart + (boxWidth * 0.5); } function layoutVerticalView(){ let original, outlier, viewModel: any = {}, q1 = layoutScale.yScale(dataModel.q1Val), median = layoutScale.yScale(dataModel.median), q3 = layoutScale.yScale(dataModel.q3Val); viewModel.topWhisker = { x1: boxMidPoint, x2: boxMidPoint, y1: q3, y2: layoutScale.yScale(dataModel.upperWhisker) }; viewModel.box = { x: boxStart, y: q3, width: boxWidth, height: q1 - q3 }; viewModel.median = { x1: boxStart, x2: boxStart + boxWidth, y1: median, y2: median }; viewModel.bottomWhisker = { x1: boxMidPoint, x2: boxMidPoint, y1: q1, y2: layoutScale.yScale(dataModel.lowerWhisker) }; viewModel.outliers = []; for (let o of outliers) { let key = 'outlier'; if(hasMax && o === dataModel.max){ key = 'max'; } else if(hasMax && o === dataModel.min){ key = 'min'; } original = { key: key, value: o } outlier = { x: boxMidPoint, y: layoutScale.yScale(o), r: layoutScale.radius, color: theme.colors.colorDefault, original: original }; if(dataModel.detailsMap){ outlier.details = dataModel.detailsMap(original); } viewModel.outliers.push(outlier); } return viewModel; } function layoutHorizontalView(){ let original, outlier, viewModel: any = {}, q1 = layoutScale.xScale(dataModel.q1Val), median = layoutScale.xScale(dataModel.median), q3 = layoutScale.xScale(dataModel.q3Val) viewModel.topWhisker = { x1: q3, x2: layoutScale.xScale(dataModel.upperWhisker), y1: boxMidPoint, y2: boxMidPoint }; viewModel.box = { x: q1, y: boxStart, width: q3 - q1, height: boxWidth }; viewModel.median = { x1: median, x2: median, y1: boxStart, y2: boxStart + boxWidth, }; viewModel.bottomWhisker = { x1: q1, x2: layoutScale.xScale(dataModel.lowerWhisker), y1: boxMidPoint, y2: boxMidPoint }; viewModel.outliers = []; for (let o of outliers) { let key = 'outlier'; if(hasMax && o === dataModel.max){ key = 'max'; } else if(hasMax && o === dataModel.min){ key = 'min'; } original = { key: key, value: o } outlier = { x: layoutScale.xScale(o), y: boxMidPoint, r: layoutScale.radius, color: theme.colors.colorDefault, original: original }; if(dataModel.detailsMap){ outlier.details = dataModel.detailsMap(original); } viewModel.outliers.push(outlier); } return viewModel; } // layouter return function(){ let viewModel: any = {}; if (OrientationEnum.VERTICAL === orientationEnum) { viewModel = layoutVerticalView(); } else if (OrientationEnum.HORIZONTAL === orientationEnum) { viewModel = layoutHorizontalView(); } return viewModel; } } }