Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/chart/scatter/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ export function install(registers: EChartsExtensionInstallRegisters) {
}

export function installScatterJitter(registers: EChartsExtensionInstallRegisters) {
registers.registerLayout(registers.PRIORITY.VISUAL.POST_CHART_LAYOUT, jitterLayout);
registers.registerLayout(registers.PRIORITY.VISUAL.POST_CHART_LAYOUT, jitterLayout());
}
104 changes: 65 additions & 39 deletions src/chart/scatter/jitterLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,79 @@
* under the License.
*/

import type GlobalModel from '../../model/Global';
import type ScatterSeriesModel from './ScatterSeries';
import { needFixJitter, fixJitter } from '../../util/jitter';
import type SingleAxis from '../../coord/single/SingleAxis';
import type Axis2D from '../../coord/cartesian/Axis2D';
import type { StageHandler } from '../../util/types';
import createRenderPlanner from '../helper/createRenderPlanner';

export default function jitterLayout(ecModel: GlobalModel) {
ecModel.eachSeriesByType('scatter', function (seriesModel: ScatterSeriesModel) {
const coordSys = seriesModel.coordinateSystem;
if (coordSys
&& (coordSys.type === 'cartesian2d' || coordSys.type === 'single')) {
const baseAxis = coordSys.getBaseAxis ? coordSys.getBaseAxis() : null;
export default function jitterLayout(): StageHandler {
return {
seriesType: 'scatter',

plan: createRenderPlanner(),

reset(seriesModel: ScatterSeriesModel) {
const coordSys = seriesModel.coordinateSystem;
if (!coordSys || (coordSys.type !== 'cartesian2d' && coordSys.type !== 'single')) {
return;
}
const baseAxis = coordSys.getBaseAxis && coordSys.getBaseAxis() as Axis2D | SingleAxis;
const hasJitter = baseAxis && needFixJitter(seriesModel, baseAxis);
if (!hasJitter) {
return;
}

if (hasJitter) {
const data = seriesModel.getData();
data.each(function (idx) {
const dim = baseAxis.dim;
const orient = (baseAxis as SingleAxis).orient;
const isSingleY = orient === 'horizontal' && baseAxis.type !== 'category'
|| orient === 'vertical' && baseAxis.type === 'category';
const layout = data.getItemLayout(idx);
const rawSize = data.getItemVisual(idx, 'symbolSize');
const size = rawSize instanceof Array ? (rawSize[1] + rawSize[0]) / 2 : rawSize;
const dim = baseAxis.dim;
const orient = (baseAxis as SingleAxis).orient;
const isSingleY = orient === 'horizontal' && baseAxis.type !== 'category'
|| orient === 'vertical' && baseAxis.type === 'category';

if (dim === 'y' || dim === 'single' && isSingleY) {
// x is fixed, and y is floating
const jittered = fixJitter(
baseAxis as Axis2D | SingleAxis,
layout[0],
layout[1],
size / 2
);
data.setItemLayout(idx, [layout[0], jittered]);
}
else if (dim === 'x' || dim === 'single' && !isSingleY) {
// y is fixed, and x is floating
const jittered = fixJitter(
baseAxis as Axis2D | SingleAxis,
layout[1],
layout[0],
size / 2
);
data.setItemLayout(idx, [jittered, layout[1]]);
}
});
const jitterOnY = dim === 'y' || (dim === 'single' && isSingleY);
const jitterOnX = dim === 'x' || (dim === 'single' && !isSingleY);
if (!jitterOnY && !jitterOnX) {
return;
}

return {
progress(params, data): void {
const points = data.getLayout('points') as Float32Array;
const hasPoints = !!points;

for (let i = params.start; i < params.end; i++) {
const offset = hasPoints ? (i - params.start) * 2 : -1;
const layout = hasPoints ? [points[offset], points[offset + 1]] : data.getItemLayout(i);
if (!layout) {
continue;
}

const rawSize = data.getItemVisual(i, 'symbolSize');
const size = rawSize instanceof Array ? (rawSize[1] + rawSize[0]) / 2 : rawSize;

if (jitterOnY) {
// x is fixed, and y is floating
const jittered = fixJitter(baseAxis, layout[0], layout[1], size / 2);
if (hasPoints) {
points[offset + 1] = jittered;
}
else {
layout[1] = jittered;
}
}
else if (jitterOnX) {
// y is fixed, and x is floating
const jittered = fixJitter(baseAxis, layout[1], layout[0], size / 2);
if (hasPoints) {
points[offset] = jittered;
}
else {
layout[0] = jittered;
}
}
}
}
};
}
});
};
}
14 changes: 6 additions & 8 deletions src/util/jitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,19 @@ export function fixJitter(
}
const axisModel = fixedAxis.model as AxisBaseModel;
const jitter = axisModel.get('jitter');
if (!(jitter > 0)) {
return floatCoord;
}
const jitterOverlap = axisModel.get('jitterOverlap');
const jitterMargin = axisModel.get('jitterMargin') || 0;
// Get band width to limit jitter range
const bandWidth = fixedAxis.scale.type === 'ordinal'
? fixedAxis.getBandWidth()
: null;
if (jitter > 0) {
if (jitterOverlap) {
return fixJitterIgnoreOverlaps(floatCoord, jitter, bandWidth, radius);
}
else {
return fixJitterAvoidOverlaps(fixedAxis, fixedCoord, floatCoord, radius, jitter, jitterMargin);
}
if (jitterOverlap) {
return fixJitterIgnoreOverlaps(floatCoord, jitter, bandWidth, radius);
}
return floatCoord;
return fixJitterAvoidOverlaps(fixedAxis, fixedCoord, floatCoord, radius, jitter, jitterMargin);
Comment on lines +70 to +82
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No logical bug here. Just tweaked the code style.

}

function fixJitterIgnoreOverlaps(
Expand Down
1 change: 1 addition & 0 deletions test/runTest/actions/__meta__.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/runTest/actions/scatter-jitter.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

185 changes: 185 additions & 0 deletions test/scatter-jitter.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.