Merge pull request #735 from zBritva/scroll_properties

Fix scroll properties for categorical data binding.
This commit is contained in:
Ilfat Galiev 2021-09-07 12:38:24 +03:00 коммит произвёл GitHub
Родитель 7ba964fc43 deaca550da
Коммит cc3b158b71
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 65 добавлений и 80 удалений

Просмотреть файл

@ -27,6 +27,7 @@ import { DataAxisExpression } from "../core/prototypes/marks/data_axis.attrs";
import { MappingType, ScaleMapping, ValueMapping } from "../core/specification";
import { Region2DSublayoutOptions } from "../core/prototypes/plot_segments/region_2d/base";
import { GuideAttributeNames } from "../core/prototypes/guides";
import { scaleLinear } from "d3-scale";
export interface TemplateInstance {
chart: Specification.Chart;
@ -477,13 +478,25 @@ export class ChartTemplate {
const scale = new Scale.LinearScale();
scale.inferParameters(vector);
if (inference.autoDomainMin) {
axisDataBinding.domainMin = scale.domainMin;
axisDataBinding.dataDomainMin = scale.domainMin;
}
if (inference.autoDomainMax) {
axisDataBinding.domainMax = scale.domainMax;
axisDataBinding.dataDomainMax = scale.domainMax;
}
if (axisDataBinding.allowScrolling) {
const scrollScale = scaleLinear()
.domain([0, 100])
.range([
axisDataBinding.dataDomainMin,
axisDataBinding.dataDomainMax,
]);
const start = scrollScale(axisDataBinding.scrollPosition);
axisDataBinding.domainMin = start;
axisDataBinding.domainMax = start + axisDataBinding.windowSize;
} else {
axisDataBinding.domainMin = scale.domainMin;
axisDataBinding.domainMax = scale.domainMax;
}
if (axis.defineCategories) {
axisDataBinding.categories = defineCategories(vector);
}

Просмотреть файл

@ -119,7 +119,10 @@ export class AxisRenderer {
this.setStyle(data.style);
this.oppositeSide = data.side == "opposite";
this.scrollRequired = data.allowScrolling;
this.shiftAxis = data.barOffset == null || data.barOffset === 0;
this.shiftAxis =
(data.barOffset == null || data.barOffset === 0) &&
((data.allCategories && data.windowSize < data.allCategories.length) ||
Math.abs(data.dataDomainMax - data.dataDomainMin) > data.windowSize);
switch (data.type) {
case "numerical":
{
@ -1469,57 +1472,6 @@ export function buildAxisWidgets(
]
)
);
widgets.push(
manager.sectionHeader(strings.objects.dataAxis.scrolling)
);
widgets.push(
manager.inputBoolean(
{
property: axisProperty,
field: "allowScrolling",
},
{
type: "checkbox",
label: strings.objects.dataAxis.allowScrolling,
observerConfig: {
isObserver: true,
properties: {
property: axisProperty,
field: "windowSize",
},
value: 10,
},
}
)
);
if (data.allowScrolling) {
widgets.push(
manager.inputNumber(
{
property: axisProperty,
field: "windowSize",
},
{
maximum: 1000,
minimum: 1,
label: strings.objects.dataAxis.windowSize,
}
)
);
widgets.push(
manager.inputNumber(
{
property: axisProperty,
field: "barOffset",
},
{
maximum: 1000,
minimum: -1000000,
label: strings.objects.dataAxis.barOffset,
}
)
);
}
widgets.push(makeAppearance());
}
break;

Просмотреть файл

@ -416,8 +416,16 @@ export class CartesianPlotSegment extends PlotSegmentClass<
const attrs = this.state.attributes;
const props = this.object.properties;
const g = [];
// TODO optimize axis render;
if (props.xData && props.xData.visible && props.xData.allowScrolling) {
if (
props.xData &&
props.xData.visible &&
props.xData.allowScrolling &&
((props.xData.allCategories &&
props.xData.allCategories.length > props.xData.windowSize) ||
Math.abs(props.xData.dataDomainMax - props.xData.dataDomainMin) >
props.xData.windowSize)
) {
const axisRenderer = new AxisRenderer().setAxisDataBinding(
props.xData,
0,
@ -441,12 +449,12 @@ export class CartesianPlotSegment extends PlotSegmentClass<
if (!props.xData.allCategories) {
return;
}
props.xData.scrollPosition = position;
props.xData.scrollPosition = 100 - position;
const start = Math.floor(
((props.xData.allCategories.length - props.xData.windowSize) /
100) *
position
props.xData.scrollPosition
);
props.xData.categories = props.xData.allCategories.slice(
start,
@ -454,13 +462,14 @@ export class CartesianPlotSegment extends PlotSegmentClass<
);
if (props.xData.categories.length === 0) {
props.xData.allCategories
.reverse()
.slice(start - 1, start + props.xData.windowSize);
props.xData.allCategories.slice(
start - 1,
start + props.xData.windowSize
);
}
} else if (props.xData.type === AxisDataBindingType.Numerical) {
const scale = scaleLinear()
.domain([0, 100])
.domain([100, 0])
.range([props.xData.dataDomainMin, props.xData.dataDomainMax]);
props.xData.scrollPosition = position;
const start = scale(position);
@ -478,8 +487,10 @@ export class CartesianPlotSegment extends PlotSegmentClass<
props.yData &&
props.yData.visible &&
props.yData.allowScrolling &&
props.yData.allCategories &&
props.yData.allCategories.length > props.yData.windowSize
((props.yData.allCategories &&
props.yData.allCategories.length > props.yData.windowSize) ||
Math.abs(props.yData.dataDomainMax - props.yData.dataDomainMin) >
props.yData.windowSize)
) {
const axisRenderer = new AxisRenderer().setAxisDataBinding(
props.yData,
@ -510,19 +521,20 @@ export class CartesianPlotSegment extends PlotSegmentClass<
100) *
position
);
props.yData.categories = props.yData.allCategories
.reverse()
.slice(start, start + props.yData.windowSize)
.reverse();
props.yData.categories = props.yData.allCategories.slice(
start,
start + props.yData.windowSize
);
if (props.yData.categories.length === 0) {
props.yData.allCategories
.reverse()
.slice(start - 1, start + props.yData.windowSize);
props.yData.allCategories.slice(
start - 1,
start + props.yData.windowSize
);
}
} else if (props.yData.type === AxisDataBindingType.Numerical) {
const scale = scaleLinear()
.domain([0, 100])
.domain([100, 0])
.range([props.yData.dataDomainMin, props.yData.dataDomainMax]);
props.yData.scrollPosition = position;
const start = scale(position);

Просмотреть файл

@ -48,7 +48,8 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
handlePosition = 0;
}
handlePosition = ((trackSize - handleSize) / 100) * handlePosition; // map % to axis position
handlePosition =
((trackSize - handleSize) / 100) * (100 - handlePosition); // map % to axis position
if (vertical) {
handlePositionY = handlePosition;
@ -113,10 +114,10 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
let newPosition = position;
if (vertical) {
const trackSize = Math.abs(trackElement.bottom - trackElement.top);
newPosition = 100 - (deltaY / trackSize) * 100;
newPosition = (deltaY / trackSize) * 100;
} else {
const trackSize = Math.abs(trackElement.right - trackElement.left);
newPosition = (deltaX / trackSize) * 100;
newPosition = 100 - (deltaX / trackSize) * 100;
}
if (newPosition > 100) {
@ -134,7 +135,14 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
const onClick = React.useCallback(
(sign: number) => {
const newPosition = position + sign * 5;
let newPosition = position + sign * 5;
if (newPosition > 100) {
newPosition = 100;
}
if (newPosition < 0) {
newPosition = 0;
}
setPosition(newPosition);
onScroll(newPosition);
},
@ -195,7 +203,7 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
fill: "#b3b0ad",
}}
onClick={() => {
onClick(-1);
onClick(1);
}}
/>
<path
@ -219,7 +227,7 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
fill: "#b3b0ad",
}}
onClick={() => {
onClick(1);
onClick(-1);
}}
/>
<path
@ -256,7 +264,7 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
fill: "#b3b0ad",
}}
onClick={() => {
onClick(-1);
onClick(1);
}}
/>
<path
@ -278,7 +286,7 @@ export const VirtualScrollBar: React.FC<VirtualScrollBarPropertes> = ({
fill: "#b3b0ad",
}}
onClick={() => {
onClick(1);
onClick(-1);
}}
/>
<path