echarts-nightly
Version:
Apache ECharts is a powerful, interactive charting and data visualization library for browser
154 lines (150 loc) • 5.79 kB
JavaScript
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* AUTO-GENERATED FILE. DO NOT MODIFY.
*/
import Axis2D from '../coord/cartesian/Axis2D.js';
import { makeInner } from './model.js';
export function needFixJitter(seriesModel, axis) {
var coordinateSystem = seriesModel.coordinateSystem;
var coordType = coordinateSystem && coordinateSystem.type;
var baseAxis = coordinateSystem && coordinateSystem.getBaseAxis && coordinateSystem.getBaseAxis();
var scaleType = baseAxis && baseAxis.scale && baseAxis.scale.type;
var seriesValid = coordType === 'cartesian2d' && scaleType === 'ordinal' || coordType === 'single';
var axisValid = axis.model.get('jitter') > 0;
return seriesValid && axisValid;
}
var inner = makeInner();
/**
* Fix jitter for overlapping data points.
*
* @param fixedAxis The axis whose coord doesn't change with jitter.
* @param fixedCoord The coord of fixedAxis.
* @param floatCoord The coord of the other axis, which should be changed with jittering.
* @param radius The radius of the data point, considering the symbol is a circle.
* @returns updated floatCoord.
*/
export function fixJitter(fixedAxis, fixedCoord, floatCoord, radius) {
if (fixedAxis instanceof Axis2D) {
var scaleType = fixedAxis.scale.type;
if (scaleType !== 'category' && scaleType !== 'ordinal') {
return floatCoord;
}
}
var axisModel = fixedAxis.model;
var jitter = axisModel.get('jitter');
var jitterOverlap = axisModel.get('jitterOverlap');
var jitterMargin = axisModel.get('jitterMargin') || 0;
// Get band width to limit jitter range
var 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);
}
}
return floatCoord;
}
function fixJitterIgnoreOverlaps(floatCoord, jitter, bandWidth, radius) {
// Don't clamp single axis
if (bandWidth === null) {
return floatCoord + (Math.random() - 0.5) * jitter;
}
var maxJitter = bandWidth - radius * 2;
var actualJitter = Math.min(Math.max(0, jitter), maxJitter);
return floatCoord + (Math.random() - 0.5) * actualJitter;
}
function fixJitterAvoidOverlaps(fixedAxis, fixedCoord, floatCoord, radius, jitter, margin) {
var store = inner(fixedAxis);
if (!store.items) {
store.items = {
fixedCoord: -1,
floatCoord: -1,
r: -1,
next: null,
prev: null
};
store.items.next = store.items;
store.items.prev = store.items;
}
var items = store.items;
var overlapA = placeJitterOnDirection(items, fixedCoord, floatCoord, radius, jitter, margin, 1);
var overlapB = placeJitterOnDirection(items, fixedCoord, floatCoord, radius, jitter, margin, -1);
var overlapResult = Math.abs(overlapA.resultCoord - floatCoord) < Math.abs(overlapB.resultCoord - floatCoord) ? overlapA : overlapB;
var minFloat = overlapResult.resultCoord;
// Clamp only category axis
var bandWidth = fixedAxis.scale.type === 'ordinal' ? fixedAxis.getBandWidth() : null;
var distance = Math.abs(minFloat - floatCoord);
if (distance > jitter / 2 || bandWidth && distance > bandWidth / 2 - radius) {
// If the new item is moved too far, then give up.
// Fall back to random jitter.
minFloat = fixJitterIgnoreOverlaps(floatCoord, jitter, bandWidth, radius);
}
// Insert to store
var insertBy = overlapResult.insertBy;
var resultDirection = overlapResult.direction;
var pointer1 = resultDirection > 0 ? 'next' : 'prev';
var pointer2 = resultDirection > 0 ? 'prev' : 'next';
var newItem = {
fixedCoord: fixedCoord,
floatCoord: overlapResult.resultCoord,
r: radius,
next: null,
prev: null
};
newItem[pointer1] = insertBy[pointer1];
newItem[pointer2] = insertBy;
insertBy[pointer1][pointer2] = newItem;
insertBy[pointer1] = newItem;
return minFloat;
}
function placeJitterOnDirection(items, fixedCoord, floatCoord, radius, jitter, margin, direction) {
// Check for overlap with previous items.
var y = floatCoord;
var pointer1 = direction > 0 ? 'next' : 'prev';
var insertBy = items;
var item = items[pointer1];
while (item !== items) {
var dx = fixedCoord - item.fixedCoord;
var dy = y - item.floatCoord;
var d2 = dx * dx + dy * dy;
var r = radius + item.r + margin;
if (d2 < r * r) {
// Overlap. Try to move the new item along otherCoord direction.
y = item.floatCoord + Math.sqrt(r * r - dx * dx) * direction;
insertBy = item;
if (Math.abs(y - floatCoord) > jitter / 2) {
// If the new item is moved too far, then give up.
// Fall back to random jitter.
return {
resultCoord: Number.MAX_VALUE,
insertBy: insertBy,
direction: direction
};
}
}
item = item[pointer1];
}
return {
resultCoord: y,
insertBy: insertBy,
direction: direction
};
}