Merge pull request #696 from MrRamka/feature/gridlines
Added legend gridlines
This commit is contained in:
Коммит
3788301db8
|
@ -19,6 +19,7 @@ import {
|
|||
buildAxisAppearanceWidgets,
|
||||
defaultAxisStyle,
|
||||
} from "../plot_segments/axis";
|
||||
import { PlotSegmentClass } from "../plot_segments";
|
||||
|
||||
export enum NumericalNumberLegendAttributeNames {
|
||||
x1 = "x1",
|
||||
|
@ -59,6 +60,7 @@ export interface NumericalNumberLegendProperties
|
|||
};
|
||||
polarAngularMode?: boolean;
|
||||
}
|
||||
const PRECISION = 1e-3;
|
||||
|
||||
export class NumericalNumberLegendClass extends ChartElementClass<
|
||||
NumericalNumberLegendProperties,
|
||||
|
@ -284,7 +286,10 @@ export class NumericalNumberLegendClass extends ChartElementClass<
|
|||
domainMax
|
||||
);
|
||||
} else {
|
||||
return this.getLineAxisGraphics(rangeMin, rangeMax, domainMin, domainMax);
|
||||
return Graphics.makeGroup([
|
||||
this.getLineAxisGraphics(rangeMin, rangeMax, domainMin, domainMax),
|
||||
this.getGridLineGraphics(rangeMin, rangeMax, domainMin, domainMax),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +357,110 @@ export class NumericalNumberLegendClass extends ChartElementClass<
|
|||
);
|
||||
}
|
||||
|
||||
public getGridLineGraphics(
|
||||
rangeMin: number,
|
||||
rangeMax: number,
|
||||
domainMin: number,
|
||||
domainMax: number
|
||||
): Graphics.Element {
|
||||
const legendId = this.object._id;
|
||||
const chartConstrains = this.parent.object.constraints;
|
||||
|
||||
if (chartConstrains.length > 0) {
|
||||
//x1, y1, x2, y2
|
||||
//check if 4 constrain for legend
|
||||
const amountLegendConstrain = chartConstrains.filter(
|
||||
(elem) => elem.attributes?.element === legendId
|
||||
);
|
||||
if (amountLegendConstrain.length === 4) {
|
||||
const targetConstrain = chartConstrains?.find(
|
||||
(constant) => constant?.attributes?.element === legendId
|
||||
);
|
||||
const targetId = targetConstrain?.attributes?.targetElement;
|
||||
const plotSIdx = this.parent.object.elements.findIndex(
|
||||
(element) => element._id === targetId
|
||||
);
|
||||
const plotSAttributes = this.parent.state.elements[plotSIdx]
|
||||
?.attributes;
|
||||
|
||||
const x1 = this.state.attributes.x1;
|
||||
const x2 = this.state.attributes.x2;
|
||||
const y1 = this.state.attributes.y1;
|
||||
const y2 = this.state.attributes.y2;
|
||||
|
||||
const isXEquals = Math.abs(<number>x2 - <number>x1) < PRECISION;
|
||||
const isYEquals = Math.abs(<number>y2 - <number>y1) < PRECISION;
|
||||
|
||||
if (!isXEquals && !isYEquals) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const angle = isYEquals ? 0 : 90;
|
||||
|
||||
const dx = <number>plotSAttributes?.x2 - <number>plotSAttributes?.x1;
|
||||
const dy = <number>plotSAttributes?.y2 - <number>plotSAttributes?.y1;
|
||||
|
||||
const length = isYEquals ? dx : dy;
|
||||
const renderer = new AxisRenderer();
|
||||
|
||||
const scaling = (rangeMax - rangeMin) / (domainMax - domainMin);
|
||||
renderer.setLinearScale(
|
||||
domainMin,
|
||||
domainMin + (length - rangeMin) / scaling,
|
||||
rangeMin,
|
||||
length,
|
||||
null
|
||||
);
|
||||
renderer.setStyle({
|
||||
...defaultAxisStyle,
|
||||
...this.object.properties?.axis?.style,
|
||||
});
|
||||
|
||||
//gridline should be in PlotSegment
|
||||
let side = 1;
|
||||
if (isXEquals) {
|
||||
if (y1 > y2) {
|
||||
if (Math.abs(x1 - <number>plotSAttributes?.x1) < PRECISION) {
|
||||
side = -1;
|
||||
} else {
|
||||
side = 1;
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(x1 - <number>plotSAttributes?.x1) < PRECISION) {
|
||||
side = -1;
|
||||
} else {
|
||||
side = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isYEquals) {
|
||||
if (x1 > x2) {
|
||||
if (Math.abs(y1 - <number>plotSAttributes?.y1) < PRECISION) {
|
||||
side = 1;
|
||||
} else {
|
||||
side = -1;
|
||||
}
|
||||
} else {
|
||||
if (Math.abs(y1 - <number>plotSAttributes?.y1) < PRECISION) {
|
||||
side = 1;
|
||||
} else {
|
||||
side = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return renderer.renderGridLine(
|
||||
<number>x1 > <number>x2 ? <number>x2 : <number>x1,
|
||||
<number>y1 > <number>y2 ? <number>y2 : <number>y1,
|
||||
angle,
|
||||
side,
|
||||
isYEquals ? dy : dx
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getAttributePanelWidgets(
|
||||
manager: Controls.WidgetManager
|
||||
): Controls.Widget[] {
|
||||
|
@ -363,6 +472,10 @@ export class NumericalNumberLegendClass extends ChartElementClass<
|
|||
isVisible: props.axis.visible,
|
||||
wordWrap: props.axis.style.wordWrap,
|
||||
}),
|
||||
...PlotSegmentClass.getGridLineAttributePanelWidgets(
|
||||
manager,
|
||||
"axis"
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import { Controls, strokeStyleToDashArray } from "../common";
|
|||
import { AttributeMap, DataType } from "../../specification";
|
||||
import { strings } from "../../../strings";
|
||||
import { defaultFont, defaultFontSize } from "../../../app/stores/defaults";
|
||||
import { NumericalMode } from "../../specification/types";
|
||||
import { AxisDataBindingType, NumericalMode } from "../../specification/types";
|
||||
|
||||
export const defaultAxisStyle: Specification.Types.AxisRenderingStyle = {
|
||||
tickColor: { r: 0, g: 0, b: 0 },
|
||||
|
@ -70,6 +70,7 @@ export class AxisRenderer {
|
|||
public rangeMax: number = 1;
|
||||
public valueToPosition: (value: any) => number;
|
||||
public oppositeSide: boolean = false;
|
||||
private axisDataBindingType: AxisDataBindingType = null;
|
||||
|
||||
private static textMeasurer = new TextMeasurer();
|
||||
|
||||
|
@ -96,6 +97,7 @@ export class AxisRenderer {
|
|||
if (!data) {
|
||||
return this;
|
||||
}
|
||||
this.axisDataBindingType = data.type;
|
||||
this.setStyle(data.style);
|
||||
this.oppositeSide = data.side == "opposite";
|
||||
switch (data.type) {
|
||||
|
@ -343,6 +345,11 @@ export class AxisRenderer {
|
|||
if (style.gridlineStyle === "none") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.axisDataBindingType === AxisDataBindingType.Categorical) {
|
||||
return;
|
||||
}
|
||||
|
||||
const g = makeGroup([]);
|
||||
const cos = Math.cos(Geometry.degreesToRadians(angle));
|
||||
const sin = Math.sin(Geometry.degreesToRadians(angle));
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from "../..";
|
||||
import { AxisRenderer } from "./axis";
|
||||
import { utcFormat } from "d3-time-format";
|
||||
import { NumericalMode } from "../../specification/types";
|
||||
import { AxisDataBindingType, NumericalMode } from "../../specification/types";
|
||||
import { strings } from "../../../strings";
|
||||
import { PanelMode } from "../controls";
|
||||
|
||||
|
@ -99,6 +99,21 @@ export abstract class PlotSegmentClass<
|
|||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (data.type === AxisDataBindingType.Categorical) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return PlotSegmentClass.getGridLineAttributePanelWidgets(
|
||||
manager,
|
||||
axisProperty
|
||||
);
|
||||
}
|
||||
|
||||
public static getGridLineAttributePanelWidgets(
|
||||
manager: Controls.WidgetManager,
|
||||
axisProperty: string
|
||||
) {
|
||||
return [
|
||||
manager.verticalGroup(
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче