You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2020/06/05 09:10:32 UTC
[incubator-echarts] branch label-enhancement updated: feat(label:
add shift-x, shift-y option for moveOverlap in labelLayout
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch label-enhancement
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
The following commit(s) were added to refs/heads/label-enhancement by this push:
new ca57e80 feat(label: add shift-x, shift-y option for moveOverlap in labelLayout
ca57e80 is described below
commit ca57e8034a8d3e8e69f657cbc8ca9f5be6733776
Author: pissang <bm...@gmail.com>
AuthorDate: Fri Jun 5 17:10:07 2020 +0800
feat(label: add shift-x, shift-y option for moveOverlap in labelLayout
---
src/chart/pie/labelLayout.ts | 9 +-
src/echarts.ts | 4 +-
src/label/LabelManager.ts | 111 +++++-----------------
src/label/labelLayoutHelper.ts | 210 ++++++++++++++++++++++++++++++++++++++++-
src/util/types.ts | 8 +-
test/label-layout.html | 122 +++++++++++++++++++++++-
test/labelLine.html | 126 -------------------------
7 files changed, 358 insertions(+), 232 deletions(-)
diff --git a/src/chart/pie/labelLayout.ts b/src/chart/pie/labelLayout.ts
index 9e30c26..473cf5f 100644
--- a/src/chart/pie/labelLayout.ts
+++ b/src/chart/pie/labelLayout.ts
@@ -72,15 +72,10 @@ function adjustSingleSide(
list[j].y += delta;
adjusted = true;
- // const textHeight = list[j].textRect.height;
- // if (list[j].y + textHeight / 2 > viewTop + viewHeight) {
- // list[j].y = viewTop + viewHeight - textHeight / 2;
- // }
-
- if (j > start
- && j + 1 < end
+ if (j > start && j + 1 < end
&& list[j + 1].y > list[j].y + list[j].textRect.height
) {
+ // Shift up so it can be more equaly distributed.
shiftUp(j, delta / 2);
return;
}
diff --git a/src/echarts.ts b/src/echarts.ts
index d4d32c8..4ce37ef 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -1096,7 +1096,7 @@ class ECharts extends Eventful {
updateLabelLayout() {
const labelManager = this._labelManager;
labelManager.updateLayoutConfig(this._api);
- labelManager.layout();
+ labelManager.layout(this._api);
labelManager.processLabelsOverall();
}
@@ -1732,7 +1732,7 @@ class ECharts extends Eventful {
scheduler.unfinished = unfinished || scheduler.unfinished;
labelManager.updateLayoutConfig(api);
- labelManager.layout();
+ labelManager.layout(api);
labelManager.processLabelsOverall();
ecModel.eachSeries(function (seriesModel) {
diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index 194c222..5c5d320 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -20,16 +20,13 @@
// TODO: move labels out of viewport.
import {
- OrientedBoundingRect,
Text as ZRText,
- Point,
BoundingRect,
getECData,
Polyline,
updateProps,
initProps
} from '../util/graphic';
-import { MatrixArray } from 'zrender/src/core/matrix';
import ExtensionAPI from '../ExtensionAPI';
import {
ZRTextAlign,
@@ -47,20 +44,12 @@ import Transformable from 'zrender/src/core/Transformable';
import { updateLabelLinePoints, setLabelLineStyle } from './labelGuideHelper';
import SeriesModel from '../model/Series';
import { makeInner } from '../util/model';
-import { retrieve2, each, keys, isFunction } from 'zrender/src/core/util';
+import { retrieve2, each, keys, isFunction, filter } from 'zrender/src/core/util';
import { PathStyleProps } from 'zrender/src/graphic/Path';
import Model from '../model/Model';
+import { LabelLayoutInfo, prepareLayoutList, hideOverlap, shiftLayoutOnX, shiftLayoutOnY } from './labelLayoutHelper';
-interface DisplayedLabelItem {
- label: ZRText
- rect: BoundingRect
- localRect: BoundingRect
- obb?: OrientedBoundingRect
- axisAligned: boolean
- transform: MatrixArray
-}
-
-interface LabelLayoutDesc {
+interface LabelDesc {
label: ZRText
labelLine: Polyline
@@ -102,7 +91,7 @@ interface SavedLabelAttr {
rect: RectLike
}
-function prepareLayoutCallbackParams(labelItem: LabelLayoutDesc): LabelLayoutOptionCallbackParams {
+function prepareLayoutCallbackParams(labelItem: LabelDesc): LabelLayoutOptionCallbackParams {
const labelAttr = labelItem.defaultAttr;
const label = labelItem.label;
return {
@@ -144,7 +133,7 @@ type LabelLineOptionMixin = {
class LabelManager {
- private _labelList: LabelLayoutDesc[] = [];
+ private _labelList: LabelDesc[] = [];
private _chartViewList: ChartView[] = [];
constructor() {}
@@ -162,7 +151,7 @@ class LabelManager {
dataType: string,
seriesModel: SeriesModel,
label: ZRText,
- layoutOption: LabelLayoutDesc['layoutOption']
+ layoutOption: LabelDesc['layoutOption']
) {
const labelStyle = label.style;
const hostEl = label.__hostTarget;
@@ -353,84 +342,26 @@ class LabelManager {
}
}
- layout() {
- // TODO: sort by priority(area)
- const labelList = this._labelList;
-
- const displayedLabels: DisplayedLabelItem[] = [];
- const mvt = new Point();
+ layout(api: ExtensionAPI) {
+ const width = api.getWidth();
+ const height = api.getHeight();
- // TODO, render overflow visible first, put in the displayedLabels.
- labelList.sort(function (a, b) {
- return b.priority - a.priority;
+ const labelList = prepareLayoutList(this._labelList);
+ const labelsNeedsAdjustOnX = filter(labelList, function (item) {
+ return item.layoutOption.moveOverlap === 'shift-x';
+ });
+ const labelsNeedsAdjustOnY = filter(labelList, function (item) {
+ return item.layoutOption.moveOverlap === 'shift-y';
});
- for (let i = 0; i < labelList.length; i++) {
- const labelItem = labelList[i];
- if (labelItem.defaultAttr.ignore) {
- continue;
- }
-
- const layoutOption = labelItem.computedLayoutOption;
- const label = labelItem.label;
- const transform = label.getComputedTransform();
- // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el.
- const localRect = label.getBoundingRect();
- const isAxisAligned = !transform || (transform[1] < 1e-5 && transform[2] < 1e-5);
-
- const globalRect = localRect.clone();
- globalRect.applyTransform(transform);
-
- let obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
- let overlapped = false;
- const minMargin = layoutOption.minMargin || 0;
- const marginSqr = minMargin * minMargin;
- for (let j = 0; j < displayedLabels.length; j++) {
- const existsTextCfg = displayedLabels[j];
- // Fast rejection.
- if (!globalRect.intersect(existsTextCfg.rect, mvt) && mvt.lenSquare() > marginSqr) {
- continue;
- }
-
- if (isAxisAligned && existsTextCfg.axisAligned) { // Is overlapped
- overlapped = true;
- break;
- }
-
- if (!existsTextCfg.obb) { // If self is not axis aligned. But other is.
- existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform);
- }
-
- if (!obb) { // If self is axis aligned. But other is not.
- obb = new OrientedBoundingRect(localRect, transform);
- }
+ shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width);
+ shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height);
- if (obb.intersect(existsTextCfg.obb, mvt) || mvt.lenSquare() < marginSqr) {
- overlapped = true;
- break;
- }
- }
+ const labelsNeedsHideOverlap = filter(labelList, function (item) {
+ return item.layoutOption.hideOverlap;
+ });
- const labelLine = labelItem.labelLine;
- // TODO Callback to determine if this overlap should be handled?
- if (overlapped && layoutOption.hideOverlap) {
- label.hide();
- labelLine && labelLine.hide();
- }
- else {
- label.attr('ignore', labelItem.defaultAttr.ignore);
- labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
-
- displayedLabels.push({
- label,
- rect: globalRect,
- localRect,
- obb,
- axisAligned: isAxisAligned,
- transform
- });
- }
- }
+ hideOverlap(labelsNeedsHideOverlap);
}
/**
diff --git a/src/label/labelLayoutHelper.ts b/src/label/labelLayoutHelper.ts
index c1df9b6..861012d 100644
--- a/src/label/labelLayoutHelper.ts
+++ b/src/label/labelLayoutHelper.ts
@@ -18,26 +18,226 @@
*/
import ZRText from 'zrender/src/graphic/Text';
+import { LabelLayoutOption } from '../util/types';
+import { BoundingRect, OrientedBoundingRect, Polyline } from '../util/graphic';
+interface LabelLayoutListPrepareInput {
+ label: ZRText
+ labelLine: Polyline
+ computedLayoutOption: LabelLayoutOption
+ priority: number
+ defaultAttr: {
+ ignore: boolean
+ labelGuideIgnore: boolean
+ }
+}
+
+export interface LabelLayoutInfo {
+ label: ZRText
+ labelLine: Polyline
+ priority: number
+ rect: BoundingRect // Global rect
+ localRect: BoundingRect
+ obb?: OrientedBoundingRect // Only available when axisAligned is true
+ axisAligned: boolean
+ layoutOption: LabelLayoutOption
+ defaultAttr: {
+ ignore: boolean
+ labelGuideIgnore: boolean
+ }
+ transform: number[]
+}
+
+export function prepareLayoutList(input: LabelLayoutListPrepareInput[]): LabelLayoutInfo[] {
+ const list: LabelLayoutInfo[] = [];
+
+ for (let i = 0; i < input.length; i++) {
+ const rawItem = input[i];
+ if (rawItem.defaultAttr.ignore) {
+ continue;
+ }
+
+ const layoutOption = rawItem.computedLayoutOption;
+ const label = rawItem.label;
+ const transform = label.getComputedTransform();
+ // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el.
+ const localRect = label.getBoundingRect();
+ const isAxisAligned = !transform || (transform[1] < 1e-5 && transform[2] < 1e-5);
+
+ // Text has a default 1px stroke. Exclude this.
+ const minMargin = (layoutOption.minMargin || 0) + 2.2;
+ const globalRect = localRect.clone();
+ globalRect.applyTransform(transform);
+ globalRect.x -= minMargin / 2;
+ globalRect.y -= minMargin / 2;
+ globalRect.width += minMargin;
+ globalRect.height += minMargin;
+
+ const obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null;
+
+ list.push({
+ label,
+ labelLine: rawItem.labelLine,
+ rect: globalRect,
+ localRect,
+ obb,
+ priority: rawItem.priority,
+ defaultAttr: rawItem.defaultAttr,
+ layoutOption: rawItem.computedLayoutOption,
+ axisAligned: isAxisAligned,
+ transform
+ });
+ }
+ return list;
+}
+
+function shiftLayout(
+ list: LabelLayoutInfo[],
+ xyDim: 'x' | 'y',
+ sizeDim: 'width' | 'height',
+ minBound: number,
+ maxBound: number
+) {
+ if (!list.length) {
+ return;
+ }
+
+ list.sort(function (a, b) {
+ return a.label[xyDim] - b.label[xyDim];
+ });
+
+ function shiftForward(start: number, end: number, delta: number) {
+ for (let j = start; j < end; j++) {
+ list[j].label[xyDim] += delta;
+
+ const rect = list[j].rect;
+ rect[xyDim] += delta;
+
+ if (j > start && j + 1 < end
+ && list[j + 1].rect[xyDim] > rect[xyDim] + rect[sizeDim]
+ ) {
+ // Shift up so it can be more equaly distributed.
+ shiftBackward(j, delta / 2);
+ return;
+ }
+ }
+
+ shiftBackward(end - 1, delta / 2);
+ }
+
+ function shiftBackward(end: number, delta: number) {
+ for (let j = end; j >= 0; j--) {
+ list[j].label[xyDim] -= delta;
+
+ const rect = list[j].rect;
+ rect[xyDim] -= delta;
+
+ // const textSize = rect[sizeDim];
+ const diffToMinBound = rect[xyDim] - minBound;
+ if (diffToMinBound < 0) {
+ rect[xyDim] -= diffToMinBound;
+ list[j].label[xyDim] -= diffToMinBound;
+ }
+
+ if (j > 0
+ && rect[xyDim] > list[j - 1].rect[xyDim] + list[j - 1].rect[sizeDim]
+ ) {
+ break;
+ }
+ }
+ }
+ let lastPos = 0;
+ let delta;
+ const len = list.length;
+ for (let i = 0; i < len; i++) {
+ delta = list[i].label[xyDim] - lastPos;
+ if (delta < 0) {
+ shiftForward(i, len, -delta);
+ }
+ lastPos = list[i].label[xyDim] + list[i].rect[sizeDim];
+ }
+ if (maxBound - lastPos < 0) {
+ shiftBackward(len - 1, lastPos - maxBound);
+ }
+}
/**
* Adjust labels on x direction to avoid overlap.
*/
-export function adjustLayoutOnX(
- list: ZRText[],
+export function shiftLayoutOnX(
+ list: LabelLayoutInfo[],
leftBound: number,
rightBound: number
) {
-
+ shiftLayout(list, 'x', 'width', leftBound, rightBound);
}
/**
* Adjust labels on y direction to avoid overlap.
*/
-export function adjustLayoutOnY(
- list: ZRText[],
+export function shiftLayoutOnY(
+ list: LabelLayoutInfo[],
topBound: number,
bottomBound: number
) {
+ shiftLayout(list, 'y', 'height', topBound, bottomBound);
+}
+
+export function hideOverlap(labelList: LabelLayoutInfo[]) {
+ const displayedLabels: LabelLayoutInfo[] = [];
+
+ // TODO, render overflow visible first, put in the displayedLabels.
+ labelList.sort(function (a, b) {
+ return b.priority - a.priority;
+ });
+
+ for (let i = 0; i < labelList.length; i++) {
+ const labelItem = labelList[i];
+ const globalRect = labelItem.rect;
+ const isAxisAligned = labelItem.axisAligned;
+ const localRect = labelItem.localRect;
+ const transform = labelItem.transform;
+ const label = labelItem.label;
+ const labelLine = labelItem.labelLine;
+
+ let obb = labelItem.obb;
+ let overlapped = false;
+ for (let j = 0; j < displayedLabels.length; j++) {
+ const existsTextCfg = displayedLabels[j];
+ // Fast rejection.
+ if (!globalRect.intersect(existsTextCfg.rect)) {
+ continue;
+ }
+
+ if (isAxisAligned && existsTextCfg.axisAligned) { // Is overlapped
+ overlapped = true;
+ break;
+ }
+
+ if (!existsTextCfg.obb) { // If self is not axis aligned. But other is.
+ existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform);
+ }
+
+ if (!obb) { // If self is axis aligned. But other is not.
+ obb = new OrientedBoundingRect(localRect, transform);
+ }
+
+ if (obb.intersect(existsTextCfg.obb)) {
+ overlapped = true;
+ break;
+ }
+ }
+
+ // TODO Callback to determine if this overlap should be handled?
+ if (overlapped) {
+ label.hide();
+ labelLine && labelLine.hide();
+ }
+ else {
+ label.attr('ignore', labelItem.defaultAttr.ignore);
+ labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore);
+ displayedLabels.push(labelItem);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/util/types.ts b/src/util/types.ts
index fc20b96..7c7228a 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -826,8 +826,14 @@ export interface LabelLayoutOption {
/**
* If move the overlapped label. If label is still overlapped after moved.
* It will determine if to hide this label with `hideOverlap` policy.
+ *
+ * shift-x/y will keep the order on x/y
+ * shuffle-x/y will move the label around the original position randomly.
*/
- moveOverlap?: 'x' | 'y' | boolean
+ moveOverlap?: 'shift-x'
+ | 'shift-y'
+ | 'shuffle-x'
+ | 'shuffle-y'
/**
* If hide the overlapped label. It will be handled after move.
* @default 'none'
diff --git a/test/label-layout.html b/test/label-layout.html
index a3eaf35..f6fe7e6 100644
--- a/test/label-layout.html
+++ b/test/label-layout.html
@@ -46,6 +46,8 @@ under the License.
<div id="main3"></div>
<div id="main4"></div>
<div id="main5"></div>
+ <div id="main6"></div>
+ <div id="main7"></div>
@@ -153,7 +155,7 @@ under the License.
var data = [Math.round(Math.random() * 300)];
- for (var i = 1; i < 200; i++) {
+ for (var i = 1; i < 50; i++) {
var now = new Date(base += oneDay);
date.push([now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/'));
data.push(Math.round((Math.random() - 0.5) * 20 + data[i - 1]));
@@ -200,6 +202,7 @@ under the License.
]
};
var chart = testHelper.create(echarts, 'main1', {
+ width: 600,
title: [
'Overlap of line.'
],
@@ -343,6 +346,123 @@ under the License.
</script>
+ <script>
+ require(['echarts'/*, 'map/js/china' */], function (echarts) {
+ var option;
+ var data = [
+ [[28604,77,17096869,'Australia',1990],[31163,77.4,27662440,'Canada',1990],[1516,68,1154605773,'China',1990],[13670,74.7,10582082,'Cuba',1990],[28599,75,4986705,'Finland',1990],[29476,77.1,56943299,'France',1990],[31476,75.4,78958237,'Germany',1990],[28666,78.1,254830,'Iceland',1990],[1777,57.7,870601776,'India',1990],[29550,79.1,122249285,'Japan',1990],[2076,67.9,20194354,'North Korea',1990],[12087,72,42972254,'South Korea',1990],[24021,75.4,3397534,'New Zealand',1990 [...]
+ [[44056,81.8,23968973,'Australia',2015],[43294,81.7,35939927,'Canada',2015],[13334,76.9,1376048943,'China',2015],[21291,78.5,11389562,'Cuba',2015],[38923,80.8,5503457,'Finland',2015],[37599,81.9,64395345,'France',2015],[44053,81.1,80688545,'Germany',2015],[42182,82.8,329425,'Iceland',2015],[5903,66.8,1311050527,'India',2015],[36162,83.5,126573481,'Japan',2015],[1390,71.4,25155317,'North Korea',2015],[34644,80.7,50293439,'South Korea',2015],[34186,80.6,4528526,'New Zea [...]
+ ];
+
+ option = {
+ xAxis: {},
+ yAxis: {
+ scale: true
+ },
+ series: [{
+ name: '1990',
+ data: data[0],
+ type: 'scatter',
+ symbolSize: function (data) {
+ return Math.sqrt(data[2]) / 5e2;
+ },
+ labelLayout: {
+ y: 20,
+ draggable: true,
+ align: 'center',
+ moveOverlap: 'shift-x',
+ hideOverlap: true,
+ minMargin: 10
+ },
+ labelLine: {
+ show: true,
+ length2: 5,
+ lineStyle: {
+ color: '#bbb'
+ }
+ },
+ label: {
+ show: true,
+ formatter: function (param) {
+ return param.data[3];
+ },
+ color: '#333',
+ textBorderColor: '#fff',
+ textBorderWidth: 1,
+ position: 'top'
+ }
+ }]
+ };
+
+ var chart = testHelper.create(echarts, 'main6', {
+ title: [
+ 'Overlap Shift X'
+ ],
+ option: option
+ });
+ });
+ </script>
+
+
+ <script>
+ require(['echarts'/*, 'map/js/china' */], function (echarts) {
+ var option;
+ var data = [
+ [[28604,77,17096869,'Australia',1990],[31163,77.4,27662440,'Canada',1990],[1516,68,1154605773,'China',1990],[13670,74.7,10582082,'Cuba',1990],[28599,75,4986705,'Finland',1990],[29476,77.1,56943299,'France',1990],[31476,75.4,78958237,'Germany',1990],[28666,78.1,254830,'Iceland',1990],[1777,57.7,870601776,'India',1990],[29550,79.1,122249285,'Japan',1990],[2076,67.9,20194354,'North Korea',1990],[12087,72,42972254,'South Korea',1990],[24021,75.4,3397534,'New Zealand',1990 [...]
+ [[44056,81.8,23968973,'Australia',2015],[43294,81.7,35939927,'Canada',2015],[13334,76.9,1376048943,'China',2015],[21291,78.5,11389562,'Cuba',2015],[38923,80.8,5503457,'Finland',2015],[37599,81.9,64395345,'France',2015],[44053,81.1,80688545,'Germany',2015],[42182,82.8,329425,'Iceland',2015],[5903,66.8,1311050527,'India',2015],[36162,83.5,126573481,'Japan',2015],[1390,71.4,25155317,'North Korea',2015],[34644,80.7,50293439,'South Korea',2015],[34186,80.6,4528526,'New Zea [...]
+ ];
+
+ option = {
+ xAxis: {},
+ yAxis: {
+ scale: true
+ },
+ grid: {
+ width: 300
+ },
+ series: [{
+ name: '1990',
+ data: data[0],
+ type: 'scatter',
+ symbolSize: function (data) {
+ return Math.sqrt(data[2]) / 5e2;
+ },
+ labelLayout: {
+ x: 500,
+ draggable: true,
+ align: 'center',
+ moveOverlap: 'shift-y',
+ // hideOverlap: true,
+ minMargin: 2
+ },
+ labelLine: {
+ show: true,
+ length2: 5,
+ lineStyle: {
+ color: '#bbb'
+ }
+ },
+ label: {
+ show: true,
+ formatter: function (param) {
+ return param.data[3];
+ },
+ color: '#333',
+ textBorderColor: '#fff',
+ textBorderWidth: 1,
+ position: 'top'
+ }
+ }]
+ };
+
+ var chart = testHelper.create(echarts, 'main7', {
+ title: [
+ 'Overlap Shift Y'
+ ],
+ option: option
+ });
+ });
+ </script>
</body>
</html>
diff --git a/test/labelLine.html b/test/labelLine.html
deleted file mode 100644
index d02d1eb..0000000
--- a/test/labelLine.html
+++ /dev/null
@@ -1,126 +0,0 @@
-<!DOCTYPE html>
-<!--
-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.
--->
-
-
-<html>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <script src="lib/esl.js"></script>
- <script src="lib/config.js"></script>
- <script src="lib/jquery.min.js"></script>
- <script src="lib/facePrint.js"></script>
- <script src="lib/testHelper.js"></script>
- <!-- <script src="ut/lib/canteen.js"></script> -->
- <link rel="stylesheet" href="lib/reset.css" />
- </head>
- <body>
- <style>
- </style>
-
-
-
- <div id="main0"></div>
-
-
-
-
-
-
-
-
-
- <script>
- require(['echarts'/*, 'map/js/china' */], function (echarts) {
- var option;
- var data = [
- [[28604,77,17096869,'Australia',1990],[31163,77.4,27662440,'Canada',1990],[1516,68,1154605773,'China',1990],[13670,74.7,10582082,'Cuba',1990],[28599,75,4986705,'Finland',1990],[29476,77.1,56943299,'France',1990],[31476,75.4,78958237,'Germany',1990],[28666,78.1,254830,'Iceland',1990],[1777,57.7,870601776,'India',1990],[29550,79.1,122249285,'Japan',1990],[2076,67.9,20194354,'North Korea',1990],[12087,72,42972254,'South Korea',1990],[24021,75.4,3397534,'New Zealand',1990],[4 [...]
- [[44056,81.8,23968973,'Australia',2015],[43294,81.7,35939927,'Canada',2015],[13334,76.9,1376048943,'China',2015],[21291,78.5,11389562,'Cuba',2015],[38923,80.8,5503457,'Finland',2015],[37599,81.9,64395345,'France',2015],[44053,81.1,80688545,'Germany',2015],[42182,82.8,329425,'Iceland',2015],[5903,66.8,1311050527,'India',2015],[36162,83.5,126573481,'Japan',2015],[1390,71.4,25155317,'North Korea',2015],[34644,80.7,50293439,'South Korea',2015],[34186,80.6,4528526,'New Zealand [...]
- ];
-
- option = {
- xAxis: {},
- yAxis: {},
- series: [{
- name: '1990',
- data: data[0],
- type: 'scatter',
- symbolSize: function (data) {
- return Math.sqrt(data[2]) / 5e2;
- },
- labelLayout: {
- y: 20,
- draggable: true,
- align: 'center',
- hideOverlap: true
- },
- labelLine: {
- show: true,
- length2: 10
- },
- label: {
- show: true,
- formatter: function (param) {
- return param.data[3];
- },
- position: 'top'
- }
- }, {
- name: '2015',
- data: data[1],
- type: 'scatter',
- symbolSize: function (data) {
- return Math.sqrt(data[2]) / 5e2;
- },
- labelLayout: {
- y: 40,
- draggable: true,
- align: 'center',
- hideOverlap: true
- },
- labelLine: {
- show: true,
- length2: 10
- },
- label: {
- show: true,
- formatter: function (param) {
- return param.data[3];
- },
- position: 'top'
- }
- }]
- };
-
- var chart = testHelper.create(echarts, 'main0', {
- title: [
- ],
- option: option
- // height: 300,
- // buttons: [{text: 'btn-txt', onclick: function () {}}],
- // recordCanvas: true,
- });
- });
- </script>
-
-
- </body>
-</html>
-
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org