Skip to content

Commit

Permalink
Version 5.5.7
Browse files Browse the repository at this point in the history
  • Loading branch information
martynasma committed Nov 17, 2023
1 parent b642901 commit ec81f87
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 66 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@amcharts/amcharts5",
"version": "5.5.6",
"version": "5.5.7",
"author": "amCharts <[email protected]> (https://www.amcharts.com/)",
"description": "amCharts 5",
"homepage": "https://www.amcharts.com/",
Expand Down
13 changes: 13 additions & 0 deletions packages/shared/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
Please note, that this project, while following numbering syntax, it DOES NOT
adhere to [Semantic Versioning](http://semver.org/spec/v2.0.0.html) rules.

## [5.5.7] - 2023-11-17

### Added
- Two new settings on a `ClusteredPointSeries`: `scatterDistance` and `scatterRadius`. Allow exploding clusters of very close points when further zoom-in is no longer possible. [More info](https://www.amcharts.com/docs/v5/charts/map-chart/clustered-point-series/#Scatter_settings).

### Fixed
- `PieSeries` was not issuing proper colors for its slices with some JSON config setups.
- In `StockChart` when percent mode was being switched off and related series toggled via legend, it would revert to percent mode.
- When updating data on a `PieSeries` its ticks could be displayed going all the way to the center briefly.
- Changing data on a main series in a `StockChart` was not updating related indicators properly.
- Legend marker for a `LineSeries` with bullets could display incorrectly if the whole chart was created before adding it to the `Root` container.


## [5.5.6] - 2023-11-10

### Added
Expand Down
150 changes: 148 additions & 2 deletions src/.internal/charts/map/ClusteredPointSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Label } from "../../core/render/Label";

import * as $array from "../../core/util/Array";
import * as $object from "../../core/util/Object";
import * as d3hierarchy from "d3-hierarchy";
import * as $math from "../../core/util/Math";


export interface IClusteredDataItem extends IComponentDataItem {
Expand All @@ -32,6 +34,16 @@ export interface IClusteredPointSeriesDataItem extends IMapPointSeriesDataItem {
* @readonly
*/
cluster?: DataItem<IClusteredDataItem>;

/**
* How much bullet was moved from its original position
*/
dx?: number;

/**
* How much bullet was moved from its original position
*/
dy?: number;
}

export interface IClusteredPointSeriesPrivate extends IMapPointSeriesPrivate {
Expand Down Expand Up @@ -67,6 +79,35 @@ export interface IClusteredPointSeriesSettings extends IMapPointSeriesSettings {
* @see {@link https://www.amcharts.com/docs/v5/charts/map-chart/clustered-point-series/#Group_bullet} for more info
*/
clusteredBullet?: (root: Root, series: ClusteredPointSeries, dataItem: DataItem<IClusteredPointSeriesDataItem>) => Bullet | undefined;

/**
* If bullets are closer to each other than `scatterDistance`, they will be
* scattered so that all are visible.
*
* @see {@link https://www.amcharts.com/docs/v5/charts/map-chart/clustered-point-series/#Scatter_settings} for more info
* @default 5
* @since 5.5.7
*/
scatterDistance?: number;

/**
* Presumed radius of a each bullet when scattering them.
*
* @see {@link https://www.amcharts.com/docs/v5/charts/map-chart/clustered-point-series/#Scatter_settings} for more info
* @default 8
* @since 5.5.7
*/
scatterRadius?: number;

/**
* If a map is zoomed to a maxZoomLevel * stopClusterZoom, clusters will be
* disabled.
*
* @see {@link https://www.amcharts.com/docs/v5/charts/map-chart/clustered-point-series/#Scatter_settings} for more info
* @default 0.95
* @since 5.5.7
*/
stopClusterZoom?: number
}

/**
Expand All @@ -89,9 +130,15 @@ export class ClusteredPointSeries extends MapPointSeries {
protected _dataItem: DataItem<this["_dataItemSettings"]> = this.makeDataItem({});
protected _clusterIndex: number = 0;
protected _clusters: Array<Array<DataItem<this["_dataItemSettings"]>>> = [];

public clusteredDataItems: Array<DataItem<IClusteredDataItem>> = [];

protected _scatterIndex: number = 0;
protected _scatters: Array<Array<DataItem<this["_dataItemSettings"]>>> = [];

public _packLayout = d3hierarchy.pack();

protected _spiral: Array<{ x: number, y: number }> = [];

protected _afterNew() {
this.fields.push("groupId");
this._setRawDefault("groupIdField", "groupId");
Expand All @@ -102,6 +149,10 @@ export class ClusteredPointSeries extends MapPointSeries {
public _updateChildren() {
super._updateChildren();

if (this.isDirty("scatterRadius")) {
this._spiral = $math.spiralPoints(0, 0, 300, 300, 0, 3, 3, 0, 0)
}

const groups: { [index: string]: Array<DataItem<IClusteredPointSeriesDataItem>> } = {};
// distribute to groups
$array.each(this.dataItems, (dataItem) => {
Expand All @@ -113,6 +164,8 @@ export class ClusteredPointSeries extends MapPointSeries {
groups[groupId].push(dataItem);
})

this._scatterIndex = -1;
this._scatters = [];
this._clusterIndex = -1;
this._clusters = [];

Expand All @@ -124,6 +177,10 @@ export class ClusteredPointSeries extends MapPointSeries {
dataItem.setRaw("cluster", undefined);
})

$object.each(groups, (_key, group) => {
this._scatterGroup(group);
})

$object.each(groups, (_key, group) => {
this._clusterGroup(group);
})
Expand Down Expand Up @@ -161,7 +218,7 @@ export class ClusteredPointSeries extends MapPointSeries {

protected _clusterGroup(dataItems: Array<DataItem<IClusteredPointSeriesDataItem>>) {
const chart = this.chart;
if (chart && chart.get("zoomLevel", 1) >= chart.get("maxZoomLevel", 100) * 0.95) {
if (chart && chart.get("zoomLevel", 1) >= chart.get("maxZoomLevel", 100) * this.get("stopClusterZoom", 0.95)) {
// void
}
else {
Expand Down Expand Up @@ -279,6 +336,7 @@ export class ClusteredPointSeries extends MapPointSeries {
if (di && !di.get("clipped")) {
const diPoint = di.get("point");
if (diPoint) {

if (Math.hypot(diPoint.x - point.x, diPoint.y - point.y) < this.get("minDistance", 20)) {
const cluster = this._clusters[this._clusterIndex];
cluster.push(di);
Expand All @@ -290,4 +348,92 @@ export class ClusteredPointSeries extends MapPointSeries {
})
}
}

protected _scatterGroup(dataItems: Array<DataItem<IClusteredPointSeriesDataItem>>) {
const chart = this.chart;
if (chart && chart.get("zoomLevel", 1) >= chart.get("maxZoomLevel", 100) * this.get("stopClusterZoom", 0.95)) {
while (dataItems.length > 0) {
this._scatterIndex++;
this._scatters[this._scatterIndex] = [];
const scatter = this._scatters[this._scatterIndex];
const dataItem = dataItems[0];

scatter.push(dataItem);
$array.remove(dataItems, dataItem);

this._scatterDataItem(dataItem, dataItems);
}

$array.each(this._scatters, (scatter) => {
let len = scatter.length;

if (len > 1) {
let previousCircles: Array<{ x: number, y: number, radius: number }> = [];
let s = 0;
let radius = this.get("scatterRadius", 8);
$array.each(scatter, (dataItem) => {
let spiralPoint = this._spiral[s];
let intersects = true;

if (previousCircles.length > 0) {
while (intersects) {
$array.each(previousCircles, (previousCircle) => {
intersects = false;
while ($math.circlesOverlap({ x: spiralPoint.x, y: spiralPoint.y, radius: radius }, previousCircle)) {
s++;

if (this._spiral[s] == undefined) {
intersects = false;
}
else {
intersects = true;
spiralPoint = this._spiral[s];
}
}
})
}
}

const dx = spiralPoint.x;
const dy = spiralPoint.y;

previousCircles.push({ x: dx, y: dy, radius: radius });

dataItem.set("dx", dx);
dataItem.set("dy", dy);

const bullets = dataItem.bullets;
if (bullets) {
$array.each(bullets, (bullet) => {
const sprite = bullet.get("sprite");
if (sprite) {
sprite.setAll({ dx: dx, dy: dy });
}
})
}
})
}
})
}
}

protected _scatterDataItem(dataItem: DataItem<IClusteredPointSeriesDataItem>, dataItems: Array<DataItem<IClusteredPointSeriesDataItem>>) {
const point = dataItem.get("point");
if (point) {
$array.each(dataItems, (di) => {
if (di && !di.get("clipped")) {
const diPoint = di.get("point");

if (diPoint) {
if (Math.hypot(diPoint.x - point.x, diPoint.y - point.y) < this.get("scatterDistance", 5)) {
const scatter = this._scatters[this._scatterIndex];
scatter.push(di);
$array.remove(dataItems, di);
this._scatterDataItem(di, dataItems);
}
}
}
})
}
}
}
7 changes: 7 additions & 0 deletions src/.internal/charts/map/MapChartDefaultTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ export class MapChartDefaultTheme extends Theme {
autoScale: false
})

r("ClusteredPointSeries").setAll({
minDistance: 20,
scatterDistance: 3,
scatterRadius: 8,
stopClusterZoom: 0.95
})

r("MapLineSeries").setAll({
affectsBounds: false
})
Expand Down
27 changes: 16 additions & 11 deletions src/.internal/charts/pie/PieSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { PieChart } from "./PieChart";

import { PercentSeries, IPercentSeriesSettings, IPercentSeriesDataItem, IPercentSeriesPrivate } from "../percent/PercentSeries";
import { Template } from "../../core/util/Template";
import type { IPoint } from "../../core/util/IPoint";
import { Slice } from "../../core/render/Slice";
import { Tick } from "../../core/render/Tick";
import { RadialLabel } from "../../core/render/RadialLabel";
Expand Down Expand Up @@ -265,20 +266,24 @@ export class PieSeries extends PercentSeries {

x = label.x();
y = label.y();
let points:Array<IPoint> = [];

if(x != 0 && y != 0){
if (label.get("textType") == "circular") {
const labelRadius = label.radius() - label.get("paddingBottom", 0);
const labelAngle = label.get("labelAngle", 0);
x = labelRadius * $math.cos(labelAngle);
y = labelRadius * $math.sin(labelAngle);
}

if (label.get("textType") == "circular") {
const labelRadius = label.radius() - label.get("paddingBottom", 0);
const labelAngle = label.get("labelAngle", 0);
x = labelRadius * $math.cos(labelAngle);
y = labelRadius * $math.sin(labelAngle);
}

let dx = -pr;
if (label.getPrivate("left")) {
dx = pl;
let dx = -pr;
if (label.getPrivate("left")) {
dx = pl;
}
points = [{ x: slice.x() + radius * cos, y: slice.y() + radius * sin }, { x: x + dx, y: y }, { x: x, y: y }];
}

tick.set("points", [{ x: slice.x() + radius * cos, y: slice.y() + radius * sin }, { x: x + dx, y: y }, { x: x, y: y }]);
tick.set("points", points);
}
}

Expand Down
17 changes: 15 additions & 2 deletions src/.internal/charts/stock/StockChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,17 +327,25 @@ export class StockChart extends Container {

if (this.isDirty("stockSeries")) {
if (stockSeries) {
const previous = this._prevSettings.stockSeries;
this.indicators.each((indicator) => {
indicator._setSoft("stockSeries", stockSeries);
if (previous == indicator.get("stockSeries")) {
indicator.set("stockSeries", stockSeries);
}
else {
indicator._setSoft("stockSeries", stockSeries);
}
})
const mainChart = stockSeries.chart;

if (mainChart) {
const previous = this._prevSettings.stockSeries;
mainChart.series.each((series) => {
if (series.isType<DrawingSeries>("DrawingSeries")) {
let s = series.get("series");
if (s == previous) {
series.set("series", stockSeries);
}
else {
series._setSoft("series", stockSeries);
}
}
Expand Down Expand Up @@ -533,9 +541,14 @@ export class StockChart extends Container {
$array.each(seriesList, (series) => {
if (percentScale) {
series.setAll(seriesSettings);
series.states.lookup("default")!.setAll(seriesSettings);
}
else {
series.states.apply("comparingDefaults");
const seriesDefaults = series.states.lookup("comparingDefaults");
if (seriesDefaults) {
series.states.lookup("default")!.setAll(seriesDefaults._settings);
}
}
});
}
Expand Down
Loading

0 comments on commit ec81f87

Please sign in to comment.