@@ -59,10 +82,11 @@ export default class Wcontainer extends React.Component {
);
}
- renderMainNormal(contentStyle, fullContent) {
+ renderMainNormal(contentStyle: React.CSSProperties, fullContent: boolean) {
const { children: propsChildren, title } = this.props;
const oneChild = React.Children.count(propsChildren) === 1;
+ // @ts-ignore
if ((oneChild && propsChildren && propsChildren.type && propsChildren.type.isG2Chart) || fullContent) {
return (
@@ -85,6 +109,7 @@ export default class Wcontainer extends React.Component {
);
}
+ // @ts-ignore
if (child.type.displayName === 'Wicon' || child.type.displayName === 'Wcircle') {
return (
@@ -92,13 +117,15 @@ export default class Wcontainer extends React.Component {
);
}
- if (child.type.displayName === 'CloudChartsG2MiniLine') {
+ // @ts-ignore
+ if (child.type.displayName === 'Wminiline') {
return (
{child}
);
}
+ // @ts-ignore
if (child.type.displayName === 'Divider') {
return (
@@ -113,13 +140,15 @@ export default class Wcontainer extends React.Component {
);
}
- renderMainCross(contentStyle) {
+ renderMainCross(contentStyle: React.CSSProperties) {
let maxColPerRow = 0;
let currentColPerRow = 0;
// 计算栅格的ColSpan
React.Children.forEach(this.props.children, (child) => {
+ // @ts-ignore
if (child.type.displayName !== 'Divider') {
currentColPerRow += 1;
+ // @ts-ignore
} else if (child.type && child.type !== 'combiner') {
if (currentColPerRow > maxColPerRow) {
maxColPerRow = currentColPerRow;
@@ -150,12 +179,14 @@ export default class Wcontainer extends React.Component {
);
}
+ container: HTMLDivElement;
+
render() {
- const { width, height, arrange, title, titleBorder, operation, className, style, titleStyle, contentStyle, fullContent, isMobile, catchError, ...otherProps } = this.props;
+ const { width, height, arrange, title, titleBorder, operation, className, style, titleStyle, contentStyle, fullContent, isMobile, catchError, onError, ...otherProps } = this.props;
const mainClasses = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
[`${prefix}`]: true,
- [`${prefix}-mobile`]: isMobileWithProps(this.props, isMobile),
+ [`${prefix}-mobile`]: isMobileWithProps(this.props),
[className]: !!className
});
@@ -184,15 +215,12 @@ export default class Wcontainer extends React.Component {
}
}
-Wcontainer.propTypes = {
- title: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
- height: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
-};
-
-function chunks(arr, maxSpan) {
- const rs = [];
- let oneRow = [];
+function chunks(arr: React.ReactNode, maxSpan: number) {
+ const rs: React.ReactElement[] = [];
+ let oneRow: React.ReactElement[] = [];
+ const len = React.Children.count(arr);
React.Children.forEach(arr, (child, i) => {
+ // @ts-ignore
if (child.type && child.type.displayName === 'Divider') {
rs.push(
@@ -200,6 +228,7 @@ function chunks(arr, maxSpan) {
);
oneRow = [];
+ // @ts-ignore
} else if (child.type === 'combiner' && oneRow.length) {
const lastChild = oneRow[oneRow.length - 1].props.children;
const lastSpan = oneRow[oneRow.length - 1].props.span;
@@ -208,7 +237,7 @@ function chunks(arr, maxSpan) {
{lastChild}
);
- } else if (i === arr.length - 1) {
+ } else if (i === len - 1) {
oneRow.push(
{child}
@@ -229,6 +258,3 @@ function chunks(arr, maxSpan) {
});
return rs;
}
-
-Wcontainer.divider = Divider;
-Wcontainer.combiner = 'combiner';
diff --git a/components/Wcontainer/scss/function.scss b/src/Wcontainer/scss/function.scss
similarity index 100%
rename from components/Wcontainer/scss/function.scss
rename to src/Wcontainer/scss/function.scss
diff --git a/components/Wcontainer/scss/mixin.scss b/src/Wcontainer/scss/mixin.scss
similarity index 100%
rename from components/Wcontainer/scss/mixin.scss
rename to src/Wcontainer/scss/mixin.scss
diff --git a/components/Wcontainer/scss/variable.scss b/src/Wcontainer/scss/variable.scss
similarity index 98%
rename from components/Wcontainer/scss/variable.scss
rename to src/Wcontainer/scss/variable.scss
index 701e4648..1a6d1e15 100644
--- a/components/Wcontainer/scss/variable.scss
+++ b/src/Wcontainer/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wcontainer-prefix: '.cloud-wcontainer';
+$wcontainer-prefix: '.#{$base-prefix}-wcontainer';
$wcontainer-bg-color: getVar(widgets-container-background, $widgets-container-background);
diff --git a/src/Wcontainer/views/divider.tsx b/src/Wcontainer/views/divider.tsx
new file mode 100644
index 00000000..2ee096e0
--- /dev/null
+++ b/src/Wcontainer/views/divider.tsx
@@ -0,0 +1,20 @@
+'use strict';
+
+import * as React from 'react';
+import { PrefixName } from '../../constants';
+
+const prefix = `${PrefixName}-wcontainer`;
+
+export default class Divider extends React.PureComponent {
+ static displayName = 'Divider';
+
+ shouldComponentUpdate() {
+ return false;
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/Wcount/dep/CountUp.ts b/src/Wcount/dep/CountUp.ts
new file mode 100644
index 00000000..c857d589
--- /dev/null
+++ b/src/Wcount/dep/CountUp.ts
@@ -0,0 +1,298 @@
+export interface CountUpOptions { // (default)
+ startVal?: number; // number to start at (0)
+ decimalPlaces?: number; // number of decimal places (0)
+ duration?: number; // animation duration in seconds (2)
+ useGrouping?: boolean; // example: 1,000 vs 1000 (true)
+ useEasing?: boolean; // ease animation (true)
+ smartEasingThreshold?: number; // smooth easing for large numbers above this if useEasing (999)
+ smartEasingAmount?: number; // amount to be eased for numbers above threshold (333)
+ separator?: string; // grouping separator (,)
+ decimal?: string; // decimal (.)
+ // easingFn: easing function for animation (easeOutExpo)
+ easingFn?: (t: number, b: number, c: number, d: number) => number;
+ formattingFn?: (n: number) => string; // this function formats result
+ prefix?: string; // text prepended to result
+ suffix?: string; // text appended to result
+ numerals?: string[]; // numeral glyph substitution
+ placeholder?: string,//非数据时的替换
+}
+
+// playground: stackblitz.com/edit/countup-typescript
+export class CountUp {
+
+ version = '2.0.7';
+ private defaults: CountUpOptions = {
+ startVal: 0,
+ decimalPlaces: 0,
+ duration: 2,
+ useEasing: true,
+ useGrouping: true,
+ smartEasingThreshold: 999,
+ smartEasingAmount: 333,
+ separator: ',',
+ decimal: '.',
+ prefix: '',
+ suffix: ''
+ };
+ private el: HTMLElement | HTMLInputElement;
+ private rAF: any;
+ private startTime: number;
+ private remaining: number;
+ private finalEndVal: number = null; // for smart easing
+ private useEasing = true;
+ private countDown = false;
+ private throttle: number;
+ formattingFn: (num: number) => string;
+ easingFn?: (t: number, b: number, c: number, d: number) => number;
+ callback: (args?: any) => any;
+ error = '';
+ startVal = 0;
+ duration: number;
+ paused = true;
+ frameVal: number;
+
+ constructor(
+ target: string | HTMLElement | HTMLInputElement,
+ public endVal: number,
+ public options?: CountUpOptions
+ ) {
+ this.options = {
+ ...this.defaults,
+ ...options
+ };
+ this.formattingFn = (this.options.formattingFn) ?
+ this.options.formattingFn : this.formatNumber;
+ this.easingFn = (this.options.easingFn) ?
+ this.options.easingFn : this.easeOutExpo;
+
+ this.startVal = this.validateValue(this.options.startVal);
+ this.frameVal = this.startVal;
+ this.endVal = this.validateValue(endVal);
+ this.options.decimalPlaces = Math.max(0 || this.options.decimalPlaces);
+ this.resetDuration();
+ this.options.separator = String(this.options.separator);
+ this.useEasing = this.options.useEasing;
+ if (this.options.separator === '') {
+ this.options.useGrouping = false;
+ }
+ this.el = (typeof target === 'string') ? document.getElementById(target) : target;
+ if (this.el) {
+ this.printValue(this.startVal);
+ } else {
+ this.error = '[CountUp] target is null or undefined';
+ }
+ }
+
+ // determines where easing starts and whether to count down or up
+ private determineDirectionAndSmartEasing() {
+ const end = (this.finalEndVal) ? this.finalEndVal : this.endVal;
+ this.countDown = (this.startVal > end);
+ const animateAmount = end - this.startVal;
+ if (Math.abs(animateAmount) > this.options.smartEasingThreshold) {
+ this.finalEndVal = end;
+ const up = (this.countDown) ? 1 : -1;
+ this.endVal = end + (up * this.options.smartEasingAmount);
+ this.duration = this.duration / 2;
+ } else {
+ this.endVal = end;
+ this.finalEndVal = null;
+ }
+ if (this.finalEndVal) {
+ this.useEasing = false;
+ } else {
+ this.useEasing = this.options.useEasing;
+ }
+ }
+
+ // start animation
+ start(callback?: (args?: any) => any) {
+ if (this.error) {
+ return;
+ }
+ this.callback = callback;
+ if (this.duration > 0) {
+ this.determineDirectionAndSmartEasing();
+ this.paused = false;
+ this.rAF = requestAnimationFrame(this.count);
+ } else {
+ this.printValue(this.endVal);
+ }
+ }
+
+ // pause/resume animation
+ pauseResume() {
+ if (!this.paused) {
+ cancelAnimationFrame(this.rAF);
+ } else {
+ this.startTime = null;
+ this.duration = this.remaining;
+ this.startVal = this.frameVal;
+ this.determineDirectionAndSmartEasing();
+ this.rAF = requestAnimationFrame(this.count);
+ }
+ this.paused = !this.paused;
+ }
+
+ // reset to startVal so animation can be run again
+ reset() {
+ cancelAnimationFrame(this.rAF);
+ this.paused = true;
+ this.resetDuration();
+ this.startVal = this.validateValue(this.options.startVal);
+ this.frameVal = this.startVal;
+ this.printValue(this.startVal);
+ }
+
+ // pass a new endVal and start animation
+ update(newEndVal: string | number) {
+ cancelAnimationFrame(this.rAF);
+ this.startTime = null;
+ this.endVal = this.validateValue(newEndVal);
+ if (this.endVal === this.frameVal) {
+ return;
+ }
+ this.startVal = this.frameVal;
+ if (!this.finalEndVal) {
+ this.resetDuration();
+ }
+ this.finalEndVal = null;
+ this.determineDirectionAndSmartEasing();
+ this.rAF = requestAnimationFrame(this.count);
+ }
+
+ count = (timestamp: number) => {
+ if (!this.startTime) {
+ this.throttle = 0;
+ this.startTime = timestamp;
+ }
+
+ const progress = timestamp - this.startTime;
+ this.remaining = this.duration - progress;
+
+ // 性能优化,偶数次渲染,或者最后一次才会渲染dom
+ if (this.throttle % 2 === 0 || progress >= this.duration) {
+ // to ease or not to ease
+ if (this.useEasing) {
+ if (this.countDown) {
+ this.frameVal = this.startVal - this.easingFn(progress, 0, this.startVal - this.endVal, this.duration);
+ } else {
+ this.frameVal = this.easingFn(progress, this.startVal, this.endVal - this.startVal, this.duration);
+ }
+ } else {
+ if (this.countDown) {
+ this.frameVal = this.startVal - ((this.startVal - this.endVal) * (progress / this.duration));
+ } else {
+ this.frameVal = this.startVal + (this.endVal - this.startVal) * (progress / this.duration);
+ }
+ }
+
+ // don't go past endVal since progress can exceed duration in the last frame
+ if (this.countDown) {
+ this.frameVal = (this.frameVal < this.endVal) ? this.endVal : this.frameVal;
+ } else {
+ this.frameVal = (this.frameVal > this.endVal) ? this.endVal : this.frameVal;
+ }
+
+ // decimal
+ this.frameVal = Number(this.frameVal.toFixed(this.options.decimalPlaces));
+
+ // format and print value
+ this.printValue(this.frameVal);
+ }
+
+ this.throttle = this.throttle + 1;
+
+ // whether to continue
+ if (progress < this.duration) {
+ this.rAF = requestAnimationFrame(this.count);
+ } else if (this.finalEndVal !== null) {
+ // smart easing
+ this.update(this.finalEndVal);
+ } else {
+ if (this.callback) {
+ this.callback();
+ }
+ }
+ }
+
+ printValue(val: number) {
+ const result = this.ensureNumber(val) ? this.formattingFn(val) : this.options.placeholder;
+
+ if (this.el.tagName === 'INPUT') {
+ const input = this.el as HTMLInputElement;
+ input.value = result;
+ } else if (this.el.tagName === 'text' || this.el.tagName === 'tspan') {
+ this.el.textContent = result;
+ } else {
+ // 自定义渲染标签
+ let html = '';
+ for (let i = 0; i < result.length; i++) {
+ const s = result.charAt(i);
+ if (s === this.options.separator) {
+ html += '
' + s + '';
+ } else if (s === this.options.decimal) {
+ html += '
' + s + '';
+ } else {
+ html += '
' + s + '';
+ }
+ }
+ this.el.innerHTML = html;
+ }
+ }
+
+ ensureNumber(n: any) {
+ return (typeof n === 'number' && !isNaN(n));
+ }
+
+ validateValue(value: string | number): number {
+ const newValue = Number(value);
+ if (!this.ensureNumber(newValue)) {
+ this.error = `[CountUp] invalid start or end value: ${value}`;
+ return null;
+ } else {
+ return newValue;
+ }
+ }
+
+ private resetDuration() {
+ this.startTime = null;
+ this.duration = Number(this.options.duration) * 1000;
+ this.remaining = this.duration;
+ }
+
+ // default format and easing functions
+
+ formatNumber = (num: number): string => {
+ const neg = (num < 0) ? '-' : '';
+ let result: string,
+ x: string[],
+ x1: string,
+ x2: string,
+ x3: string;
+ result = Math.abs(num).toFixed(this.options.decimalPlaces);
+ result += '';
+ x = result.split('.');
+ x1 = x[0];
+ x2 = x.length > 1 ? this.options.decimal + x[1] : '';
+ if (this.options.useGrouping) {
+ x3 = '';
+ for (let i = 0, len = x1.length; i < len; ++i) {
+ if (i !== 0 && (i % 3) === 0) {
+ x3 = this.options.separator + x3;
+ }
+ x3 = x1[len - i - 1] + x3;
+ }
+ x1 = x3;
+ }
+ // optional numeral substitution
+ if (this.options.numerals && this.options.numerals.length) {
+ x1 = x1.replace(/[0-9]/g, (w) => this.options.numerals[+w]);
+ x2 = x2.replace(/[0-9]/g, (w) => this.options.numerals[+w]);
+ }
+ return neg + this.options.prefix + x1 + x2 + this.options.suffix;
+ }
+
+ easeOutExpo = (t: number, b: number, c: number, d: number): number =>
+ c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b
+
+}
diff --git a/components/Wcount/index.scss b/src/Wcount/index.scss
similarity index 100%
rename from components/Wcount/index.scss
rename to src/Wcount/index.scss
diff --git a/components/Wcount/index.jsx b/src/Wcount/index.tsx
similarity index 65%
rename from components/Wcount/index.jsx
rename to src/Wcount/index.tsx
index dfd35496..3cabe60b 100644
--- a/components/Wcount/index.jsx
+++ b/src/Wcount/index.tsx
@@ -1,18 +1,19 @@
'use strict';
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
import classNames from 'classnames';
-import CountUp from './lib/CountUp';
+import { CountUp } from './dep/CountUp';
import { filterKey } from "../common/common";
+import { Types } from '../common/types';
import './index.scss';
import chartLog from "../common/log";
+import { FullCrossName, PrefixName } from '../constants';
-const prefix = 'cloud-wcount';
+const prefix = `${PrefixName}-wcount`;
const checkKey = ['start', 'decimals', 'duration', 'useEasing', 'useGrouping', 'separator', 'decimal', 'placeholder'];
// 检查 a, b 两个对象中某些key是否有变化
-function configChange(a, b) {
+function configChange(a: Types.LooseObject, b: Types.LooseObject) {
return checkKey.some((key) => {
return a[key] !== b[key];
});
@@ -26,10 +27,10 @@ function configChange(a, b) {
* @param {number} clipNum 切片数
* @param {number} slipScale 幅度数组
*
- * @return {array} 切片后的数值数组
+ * @return {number[]} 切片后的数值数组
* */
-function clipValue(start, end, clipNum, slipScale) {
- const result = [];
+function clipValue(start: number, end: number, clipNum: number, slipScale: number[]) {
+ const result: number[] = [];
const delta = end - start;
const step = delta / clipNum;
@@ -49,10 +50,42 @@ function clipValue(start, end, clipNum, slipScale) {
return result;
}
-export default class Wcount extends React.Component {
+interface WcountProps {
+ className?: string;
+ style?: React.CSSProperties;
+ // 切片配置
+ /** 切片更新数量,大于1时生效 */
+ clipNum?: number;
+ /** 切片更新周期,默认 5 秒 */
+ clipPeriod?: number;
+ /** 切片幅度数组,默认平均切片 */
+ slipScale?: number[];
+ // 数据配置
+ /** 开始翻牌数值 */
+ start?: number;
+ /** 结束翻牌数值 */
+ end?: number;
+ /** 小数位数,默认 0 */
+ decimals?: number;
+ /** 翻牌持续时间,默认 1.5 秒 */
+ duration?: number;
+ // 额外配置
+ /** 是否缓动函数翻牌 */
+ useEasing?: boolean; // toggle easing
+ /** 是否显示千分位 */
+ useGrouping?: boolean; // 1,000,000 vs 1000000
+ /** 千分位字符 */
+ separator?: string; // character to use as a separator
+ /** 小数点字符 */
+ decimal?: string; // character to use as a decimal
+ /** 无数据时字符 */
+ placeholder?: string; // 非数据时的替换
+}
+
+export default class Wcount extends React.Component
{
static displayName = 'Wcount';
- static defaultProps = {
+ static defaultProps: WcountProps = {
// 切片配置
clipNum: 1,
clipPeriod: 5,
@@ -71,15 +104,15 @@ export default class Wcount extends React.Component {
placeholder: "-", // 非数据时的替换
};
- constructor(props) {
+ constructor(props: WcountProps) {
super(props);
// 图表初始化时记录日志
chartLog('Wcount', 'init');
}
- dom = null;
- countUp = null;
+ dom: HTMLSpanElement = null;
+ countUp: CountUp = null;
componentDidMount() {
if (!this.dom) {
@@ -89,7 +122,7 @@ export default class Wcount extends React.Component {
this.createCountUp(this.props);
}
- componentDidUpdate(prevProps) {
+ componentDidUpdate(prevProps: WcountProps) {
const { /*start: newStart,*/ end: newEnd, /*decimals: newDecimals, duration: newDuration,*/ ...newOptions } = this.props;
const { /*start: oldStart,*/ end: oldEnd, /*decimals: oldDecimals, duration: oldDuration,*/ ...oldOptions } = prevProps;
@@ -112,8 +145,8 @@ export default class Wcount extends React.Component {
}
}
- clipTimer = null;
- clipNumber(props, newEnd) {
+ clipTimer: any = null;
+ clipNumber(props: WcountProps, newEnd: number) {
const { clipNum, clipPeriod, slipScale } = props;
// 清空定时器
@@ -140,9 +173,14 @@ export default class Wcount extends React.Component {
}
}
- createCountUp(props) {
+ createCountUp(props: WcountProps) {
const { start, end, decimals, duration, ...options } = props;
- const countUp = new CountUp(this.dom, start, end, decimals, duration, options);
+ const countUp = new CountUp(this.dom, end, {
+ startVal: start,
+ decimalPlaces: decimals,
+ duration,
+ ...options,
+ });
if (!countUp.error) {
countUp.start();
} else {
@@ -156,7 +194,7 @@ export default class Wcount extends React.Component {
const { className, ...otherProps } = this.props;
const mainClasses = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
[prefix]: true,
[className]: !!className
});
@@ -166,18 +204,3 @@ export default class Wcount extends React.Component {
);
}
}
-
-Wcount.propTypes = {
- clipNum: PropTypes.number,
- clipPeriod: PropTypes.number,
- slipScale: PropTypes.arrayOf(PropTypes.number),
- start: PropTypes.number,
- end: PropTypes.number,
- decimals: PropTypes.number,
- duration: PropTypes.number,
- useEasing: PropTypes.bool,
- useGrouping: PropTypes.bool,
- separator: PropTypes.string,
- decimal: PropTypes.string,
- placeholder: PropTypes.string,
-};
diff --git a/components/Wcount/scss/mixin.scss b/src/Wcount/scss/mixin.scss
similarity index 100%
rename from components/Wcount/scss/mixin.scss
rename to src/Wcount/scss/mixin.scss
diff --git a/components/Wdashboard/scss/variable.scss b/src/Wcount/scss/variable.scss
similarity index 80%
rename from components/Wdashboard/scss/variable.scss
rename to src/Wcount/scss/variable.scss
index d7f40b6c..eeed6ca8 100644
--- a/components/Wdashboard/scss/variable.scss
+++ b/src/Wcount/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wcount-prefix: '.cloud-wdashboard';
+$wcount-prefix: '.#{$base-prefix}-wcount';
$font-family: getVar(widgets-font-family-txd-m-number, $widgets-font-family-txd-m-number);
$color: getVar(widgets-color-text-1, $widgets-color-text-1);
diff --git a/components/Wdashboard/dashboard.jsx b/src/Wdashboard/dashboard.jsx
similarity index 99%
rename from components/Wdashboard/dashboard.jsx
rename to src/Wdashboard/dashboard.jsx
index 7f9acf28..d6750c1a 100755
--- a/components/Wdashboard/dashboard.jsx
+++ b/src/Wdashboard/dashboard.jsx
@@ -349,4 +349,4 @@ class DashBoard {
}
-module.exports = DashBoard;
+export default DashBoard;
diff --git a/components/Wdashboard/index.jsx b/src/Wdashboard/index.jsx
similarity index 92%
rename from components/Wdashboard/index.jsx
rename to src/Wdashboard/index.jsx
index 85d07fd8..10568504 100644
--- a/components/Wdashboard/index.jsx
+++ b/src/Wdashboard/index.jsx
@@ -1,13 +1,13 @@
'use strict';
import React from 'react';
-import PropTypes from 'prop-types';
import classNames from 'classnames';
import Dashboard from './dashboard';
import './index.scss';
import chartLog from "../common/log";
+import { FullCrossName, PrefixName } from '../constants';
-const prefix = 'cloud-wdashboard';
+const prefix = `${PrefixName}-wdashboard`;
export default class Wdashboard extends React.Component {
static displayName = 'Wdashboard';
@@ -50,7 +50,7 @@ export default class Wdashboard extends React.Component {
const { className, ...otherProps } = this.props;
const mainClasses = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
[prefix]: true,
[className]: !!className
});
diff --git a/components/Wdashboard/index.scss b/src/Wdashboard/index.scss
similarity index 100%
rename from components/Wdashboard/index.scss
rename to src/Wdashboard/index.scss
diff --git a/components/Wdashboard/scss/mixin.scss b/src/Wdashboard/scss/mixin.scss
similarity index 100%
rename from components/Wdashboard/scss/mixin.scss
rename to src/Wdashboard/scss/mixin.scss
diff --git a/components/Wcount/scss/variable.scss b/src/Wdashboard/scss/variable.scss
similarity index 79%
rename from components/Wcount/scss/variable.scss
rename to src/Wdashboard/scss/variable.scss
index 4dfe019d..85b6bd01 100644
--- a/components/Wcount/scss/variable.scss
+++ b/src/Wdashboard/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wcount-prefix: '.cloud-wcount';
+$wcount-prefix: '.#{$base-prefix}-wdashboard';
$font-family: getVar(widgets-font-family-txd-m-number, $widgets-font-family-txd-m-number);
$color: getVar(widgets-color-text-1, $widgets-color-text-1);
diff --git a/components/Wfunnel/gui.schema.json b/src/Wfunnel/gui.schema.json
similarity index 100%
rename from components/Wfunnel/gui.schema.json
rename to src/Wfunnel/gui.schema.json
diff --git a/components/Whierarchy/G2Hierarchy.scss b/src/Wfunnel/index.scss
similarity index 100%
rename from components/Whierarchy/G2Hierarchy.scss
rename to src/Wfunnel/index.scss
diff --git a/src/Wfunnel/index.tsx b/src/Wfunnel/index.tsx
new file mode 100644
index 00000000..2d7c3660
--- /dev/null
+++ b/src/Wfunnel/index.tsx
@@ -0,0 +1,382 @@
+'use strict';
+
+import { Chart, Types, BaseChartConfig, ChartData, Colors } from '../common/types';
+import Base from '../common/Base';
+import errorWrap from '../common/errorWrap';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import { GuideConfig } from '../common/guide';
+import { LabelConfig } from '../common/label';
+import themes from '../themes/index';
+import { pxToNumber, numberDecimal } from '../common/common';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import './index.scss';
+
+// 3.x代码
+export interface WfunnelConfig extends BaseChartConfig {
+ colors?: Colors;
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ guide?: GuideConfig;
+ pyramid?: boolean;
+ label?: LabelConfig | boolean;
+ direction?: string;
+ align?: string;
+ percent?: Types.LooseObject | boolean;
+ geomStyle?: GeomStyleConfig;
+}
+
+export class Funnel extends Base {
+ chartName = 'G2Funnel';
+
+ getDefaultConfig(): WfunnelConfig {
+ return {
+ colors: themes.order_10,
+ legend: {
+ position: 'top',
+ align: '',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ label: false,
+ pyramid: false,
+ // 主方向,从上到下(vertical)、从左到右(horizontal)
+ direction: 'vertical',
+ // 排列位置 start,center,end
+ align: 'center',
+ // 尖顶漏斗图
+ percent: true,
+ };
+ }
+ init(chart: Chart, config: WfunnelConfig, data: any) {
+ const defs: Record = {
+ type: {
+ type: 'cat',
+ },
+ };
+
+ chart.scale(defs);
+ chart.interaction('element-active');
+ chart.axis(false);
+ chart.data(data);
+
+ // 设置图例
+ rectLegend(this, chart, config, null, true);
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ null,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ );
+
+ // 根据传入的 direction 和 align 设置坐标系,并绘制图形
+ const drawType = `${config.direction}-${config.align}`;
+ let geom = null;
+ const fontSize1 = pxToNumber(themes['widgets-font-size-1']);
+ let percentOffsetX = 0;
+ let percentOffsetY = 0;
+ const funnelShape = config.align === 'center' && config.pyramid ? 'pyramid' : 'funnel';
+
+ switch (drawType) {
+ case 'vertical-left':
+ case 'vertical-start':
+ chart.coordinate('rect').transpose().scale(1, -1);
+ geom = chart.interval()
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors);
+ percentOffsetX = 3 * fontSize1;
+ break;
+ case 'vertical-center':
+ chart.coordinate('rect').transpose().scale(1, -1);
+ geom = chart.interval()
+ .adjust([{
+ type: 'symmetric',
+ }])
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors);
+ break;
+ case 'vertical-right':
+ case 'vertical-end':
+ chart.coordinate('rect').transpose().scale(-1, -1);
+ geom = chart.interval()
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors);
+ percentOffsetX = -3 * fontSize1;
+ break;
+ case 'horizontal-top':
+ case 'horizontal-start':
+ chart.coordinate('rect').reflect('y');
+ geom = chart.interval()
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors);
+ percentOffsetY = 3 * fontSize1;
+ break;
+ case 'horizontal-center':
+ geom = chart.interval()
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors)
+ .adjust([{
+ type: 'symmetric',
+ }]);
+ break;
+ // case 'horizontal-bottom':
+ // case 'horizontal-end':
+ // 和 default 时相同
+ default:
+ geom = chart.interval()
+ .position('x*y')
+ .shape(funnelShape)
+ .color('x', config.colors);
+ percentOffsetY = -3 * fontSize1;
+ }
+
+ geomStyle(geom, config.geomStyle);
+
+ // TODO 自定义label
+ if(config.label) {
+ let temp = {};
+ temp = config.label || {};
+ geom.label('y',
+ {
+ offset: pxToNumber(themes['widgets-font-size-1']),
+ labelLine: {
+ style: {
+ lineWidth: 1,
+ stroke: themes['widgets-axis-line'],
+ },
+ },
+ ...temp,
+ });
+ }
+
+ // 绘制辅助线,辅助背景区域
+ renderGuide(chart, config, data, percentOffsetX, percentOffsetY);
+ }
+}
+
+function renderGuide(chart: Chart, config: WfunnelConfig, data: ChartData, percentOffsetX: number, percentOffsetY: number) {
+ // 中间标签文本
+ chart.annotation().clear(true);
+ let configPercent = config.percent;
+
+ if (!configPercent) {
+ return;
+ }
+
+ if (configPercent === true) {
+ configPercent = {};
+ }
+
+ const {
+ labelFormatter,
+ offsetX = 0,
+ offsetY = 0,
+ top = true,
+ style = {}
+ } = configPercent;
+ const positionY = config.align === 'center' ? 'median' : 'start';
+
+ data.forEach((d: { y: any; x: any; }, i: any) => {
+ let content = `${numberDecimal(100 * d.y / data[0].y)}%`;
+ if (labelFormatter) {
+ content = labelFormatter(d.y / data[0].y, d, i);
+ }
+ chart.annotation().text({
+ top,
+ position: [
+ d.x,
+ positionY,
+ ],
+ offsetX: percentOffsetX + offsetX,
+ offsetY: percentOffsetY + offsetY,
+ content: content, // 显示的文本内容
+ style: {
+ fill: themes['widgets-label-text'],
+ fontSize: pxToNumber(themes['widgets-font-size-1']),
+ textAlign: 'center',
+ shadowBlur: 2,
+ shadowColor: 'rgba(255, 255, 255, .3)',
+ ...style,
+ },
+ });
+ });
+}
+
+const Wfunnel: typeof Funnel = errorWrap(Funnel);
+
+export default Wfunnel;
+
+// export default /*#__PURE__*/ errorWrap(g2Factory('G2Funnel', {
+// getDefaultConfig() {
+// return {
+// colors: themes.order_10,
+// padding: ['auto', 0, 'auto', 0],
+// legend: {
+// align: 'left',
+// nameFormatter: null, // 可以强制覆盖,手动设置label
+// },
+// tooltip: {
+// nameFormatter: null,
+// valueFormatter: null,
+// },
+// // 主方向,从上到下(vertical)、从左到右(horizontal)
+// direction: 'vertical',
+// // 排列位置 start,center,end
+// align: 'center',
+// // 尖顶漏斗图
+// pyramid: false,
+// label: false,
+// percent: false,
+// };
+// },
+// beforeInit(props) {
+// const { config } = props;
+// const newConfig = merge({}, this.defaultConfig, config);
+
+// // TODO 处理padding
+// return Object.assign({}, props, {
+// padding: defaultPadding(props.padding || config.padding, newConfig, ...this.defaultConfig.padding),
+// config: newConfig,
+// });
+// },
+// init(chart, userConfig, data) {
+// const config = userConfig;
+
+// // 设置数据度量
+// const defs = {
+// type: {
+// type: 'cat',
+// },
+// };
+
+// chart.source(data, defs);
+
+// // 漏斗图目前看没有轴
+// chart.axis(false);
+
+// // 设置图例
+// rectLegend(this, chart, config, null, true);
+
+// // tooltip
+// rectTooltip(this, chart, config, {
+// showTitle: false,
+// crosshairs: null,
+// });
+
+// // 根据传入的 direction 和 align 设置坐标系,并绘制图形
+// const drawType = `${config.direction}-${config.align}`;
+// let geom = null;
+// const fontSize1 = pxToNumber(themes['widgets-font-size-1']);
+// let percentOffsetX = 0;
+// let percentOffsetY = 0;
+
+// switch (drawType) {
+// case 'vertical-left':
+// case 'vertical-start':
+// chart.coord('rect').transpose().scale(1, -1);
+// geom = chart.interval();
+// percentOffsetX = 3 * fontSize1;
+// break;
+// case 'vertical-center':
+// chart.coord('rect').transpose().scale(1, -1);
+// geom = chart.intervalSymmetric();
+// break;
+// case 'vertical-right':
+// case 'vertical-end':
+// chart.coord('rect').transpose().scale(-1, -1);
+// geom = chart.interval();
+// percentOffsetX = -3 * fontSize1;
+// break;
+// case 'horizontal-top':
+// case 'horizontal-start':
+// chart.coord('rect').reflect('y');
+// geom = chart.interval();
+// percentOffsetY = 3 * fontSize1;
+// break;
+// case 'horizontal-center':
+// geom = chart.intervalSymmetric();
+// break;
+// // case 'horizontal-bottom':
+// // case 'horizontal-end':
+// // 和 default 时相同
+// default:
+// geom = chart.interval();
+// percentOffsetY = -3 * fontSize1;
+// }
+
+// const funnelShape = (config.align === 'center' && config.pyramid) ? 'pyramid' : 'funnel';
+
+// geom.position('x*y').shape(funnelShape).color('x', config.colors);
+
+// label(geom, config, 'y', {
+// offset: pxToNumber(themes['widgets-font-size-1']),
+// labelLine: {
+// lineWidth: 1,
+// stroke: themes['widgets-axis-line'],
+// },
+// });
+
+// const geomStyle = config.geomStyle || {};
+// geom.style('x*y*type*extra', {
+// ...geomStyle,
+// });
+
+// renderGuide(chart, config, data, percentOffsetX, percentOffsetY);
+
+// chart.render();
+// },
+// changeData(chart, config, data) {
+// chart.changeData(data);
+
+// const drawType = `${config.direction}-${config.align}`;
+// const fontSize1 = pxToNumber(themes['widgets-font-size-1']);
+// let percentOffsetX = 0;
+// let percentOffsetY = 0;
+
+// switch (drawType) {
+// case 'vertical-left':
+// case 'vertical-start':
+// percentOffsetX = 3 * fontSize1;
+// break;
+// case 'vertical-center':
+// break;
+// case 'vertical-right':
+// case 'vertical-end':
+// percentOffsetX = -3 * fontSize1;
+// break;
+// case 'horizontal-top':
+// case 'horizontal-start':
+// percentOffsetY = 3 * fontSize1;
+// break;
+// case 'horizontal-center':
+// break;
+// // case 'horizontal-bottom':
+// // case 'horizontal-end':
+// // 和 default 时相同
+// default:
+// percentOffsetY = -3 * fontSize1;
+// }
+// renderGuide(chart, config, data, percentOffsetX, percentOffsetY);
+// },
+// }));
diff --git a/components/Wicon/scss/function.scss b/src/Wheatmap/index.scss
similarity index 100%
rename from components/Wicon/scss/function.scss
rename to src/Wheatmap/index.scss
diff --git a/src/Wheatmap/index.tsx b/src/Wheatmap/index.tsx
new file mode 100644
index 00000000..bf80f2db
--- /dev/null
+++ b/src/Wheatmap/index.tsx
@@ -0,0 +1,284 @@
+'use strict';
+import { Chart, Types, BaseChartConfig, Colors } from '../common/types';
+import Base from '../common/Base';
+import errorWrap from '../common/errorWrap';
+import rectXAxis, { XAxisConfig } from '../common/rectXAxis';
+import rectYAxis, { YAxisConfig } from '../common/rectYAxis';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import guide, { GuideConfig } from '../common/guide';
+import label, { LabelConfig } from '../common/label';
+import themes from '../themes/index';
+import { propertyAssign, propertyMap } from '../common/common';
+import legendFilter from '../common/legendFilter';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import './index.scss';
+
+// 3.x代码
+export interface WheatmapConfig extends BaseChartConfig {
+ colors?: Colors;
+ xAxis?: Types.ScaleOption & XAxisConfig | false,
+ yAxis?: Types.ScaleOption & YAxisConfig | false,
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ guide?: GuideConfig;
+ label?: LabelConfig | boolean;
+ geomStyle?: GeomStyleConfig;
+ coordinate?: Types.LooseObject;
+}
+
+export class Heatmap extends Base {
+ chartName = 'G2Heatmap';
+
+ getDefaultConfig(): WheatmapConfig {
+ return {
+ colors: themes.category_12,
+ // padding: ['auto', 'auto', 'auto', 'auto'],
+ xAxis: {
+ type: 'cat',
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ categories: null,
+ autoRotate: false,
+ },
+ yAxis: {
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ max: null,
+ min: null,
+ },
+ legend: {
+ align: 'left',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ // grid: false,
+ label: false,
+ coordinate: null,
+ };
+ }
+ init(chart: Chart, config: WheatmapConfig, data: any) {
+ const defs: Record = {
+ x: propertyAssign(
+ propertyMap.axis,
+ {
+ type: 'cat',
+ },
+ config.xAxis,
+ ),
+ y: propertyAssign(
+ propertyMap.axis,
+ {
+ type: 'cat',
+ },
+ config.yAxis,
+ ),
+ type: {
+ type: 'cat',
+ },
+ };
+
+ chart.scale(defs);
+
+ chart.data(data);
+
+ if (config.coordinate) {
+ const { type = 'rect', reflect } = config.coordinate;
+ const coord = chart.coordinate(type);
+ if (reflect) {
+ coord.reflect(reflect);
+ }
+ }
+
+ // 设置单个Y轴
+ rectYAxis(this, chart, config, undefined, {
+ grid: null,
+ });
+
+ // 设置X轴
+ rectXAxis(this, chart, config);
+
+ chart.legend('x', false);
+ chart.legend('y', false);
+ // 设置图例
+ rectLegend(this, chart, config, {}, false, 'type');
+
+ legendFilter(this, chart);
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ null,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ );
+
+ // 绘制辅助线,辅助背景区域
+ guide(chart, config);
+
+ const geom = chart
+ .polygon()
+ .position('x*y')
+ .color('type', config.colors)
+ .tooltip('x*y*extra', (x, y, extra) => {
+ return {
+ name: `${x} - ${y}`,
+ value: (Array.isArray(extra) ? extra[0] : extra.value) || '-',
+ };
+ });
+
+ geomStyle(geom, config.geomStyle, {
+ lineWidth: 1,
+ stroke: themes['widgets-map-area-border'],
+ });
+
+ label(geom, config, 'y', {}, null, true, {
+ position: 'middle',
+ offset: 0,
+ content(data, item, i) {
+ if (!config.label) {
+ return;
+ }
+ let result = (Array.isArray(data.extra) ? data.extra[0] : data.extra.value) || '-';
+ if (typeof config.label === 'object' && config.label.labelFormatter) {
+ result = config.label.labelFormatter(result, item, i);
+ }
+ return result;
+ }
+ });
+ }
+}
+const Wheatmap: typeof Heatmap = errorWrap(Heatmap);
+
+export default Wheatmap;
+
+// export default /*#__PURE__*/ errorWrap(g2Factory('G2Heatmap', {
+// getDefaultConfig() {
+// return {
+// colors: themes.category_12,
+// padding: ['auto', 'auto', 'auto', 'auto'],
+// xAxis: {
+// type: 'cat',
+// labelFormatter: null, // 可以强制覆盖,手动设置label
+// categories: null,
+// autoRotate: false,
+// },
+// yAxis: {
+// labelFormatter: null, // 可以强制覆盖,手动设置label
+// max: null,
+// min: null,
+// },
+// legend: {
+// align: 'left',
+// nameFormatter: null, // 可以强制覆盖,手动设置label
+// },
+// tooltip: {
+// titleFormatter: null,
+// nameFormatter: null,
+// valueFormatter: null,
+// },
+// // grid: false,
+// // label: false,
+// coordinate: null,
+// };
+// },
+// beforeInit(props) {
+// const { config } = props;
+// const newConfig = merge({}, this.defaultConfig, config);
+
+// // TODO 处理padding
+// return Object.assign({}, props, {
+// padding: defaultPadding(props.padding || config.padding, newConfig, ...this.defaultConfig.padding),
+// config: newConfig,
+// });
+// },
+// init(chart, userConfig, data) {
+// const config = userConfig;
+
+// // 设置数据度量
+// const defs = {
+// x: propertyAssign(propertyMap.axis, {
+// type: 'cat',
+// }, config.xAxis),
+// y: propertyAssign(propertyMap.axis, {
+// type: 'cat',
+// }, config.yAxis),
+// type: {
+// type: 'cat',
+// // sync: true,
+// },
+// };
+
+// chart.source(data, defs);
+
+// if (config.coordinate) {
+// const { type = 'rect', reflect } = config.coordinate;
+// const coord = chart.coord(type);
+// if (reflect) {
+// coord.reflect(reflect);
+// }
+// }
+
+// // 设置单个Y轴
+// rectYAxis(this, chart, config, undefined, {
+// grid: null,
+// });
+
+// // 设置X轴
+// rectXAxis(this, chart, config);
+
+// chart.legend('x', false);
+// chart.legend('y', false);
+// // 设置图例
+// rectLegend(this, chart, config);
+
+// legendFilter(this, chart, config);
+
+// // tooltip
+// rectTooltip(this, chart, config, {
+// showTitle: false,
+// crosshairs: null,
+// });
+
+// // 绘制辅助线,辅助背景区域
+// guide(chart, config);
+
+// const geomStyle = config.geomStyle || {};
+
+// chart.polygon()
+// .position('x*y')
+// .color('type', config.colors)
+// .tooltip('x*y*extra', (x, y, extra) => {
+// return {
+// name: `${x} - ${y}`,
+// value: (Array.isArray(extra) ? extra[0] : extra.value) || '-',
+// };
+// })
+// .style('x*y*type*extra', {
+// lineWidth: 1,
+// stroke: themes['widgets-map-area-border'],
+// ...geomStyle,
+// });
+
+// // label(geom, config, 'extra');
+
+// chart.render();
+// },
+// // changeData(chart, config, data) {
+// // chart.changeData(data);
+// // },
+// // destroy() {
+// // },
+// }));
+
diff --git a/components/Wminicontainer/scss/function.scss b/src/Whierarchy/index.scss
similarity index 100%
rename from components/Wminicontainer/scss/function.scss
rename to src/Whierarchy/index.scss
diff --git a/src/Whierarchy/index.tsx b/src/Whierarchy/index.tsx
new file mode 100644
index 00000000..6047f3b2
--- /dev/null
+++ b/src/Whierarchy/index.tsx
@@ -0,0 +1,169 @@
+'use strict';
+import { View } from '@antv/data-set/lib/view';
+import '@antv/data-set/lib/transform/hierarchy/treemap';
+import { Chart, Types, BaseChartConfig, Colors } from '../common/types';
+import Base from "../common/Base";
+import { XAxisConfig } from '../common/rectXAxis';
+import { YAxisConfig } from '../common/rectYAxis';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import { LegendConfig } from '../common/rectLegend';
+import { GuideConfig } from '../common/guide';
+import { LabelConfig } from "../common/label";
+
+import errorWrap from '../common/errorWrap';
+import themes from '../themes/index';
+import './index.scss';
+
+interface WhierarchyConfig extends BaseChartConfig {
+ colors?: Colors;
+ xAxis?: Types.ScaleOption & XAxisConfig | boolean,
+ yAxis?: Types.ScaleOption & YAxisConfig | boolean,
+ legend?: LegendConfig | boolean,
+ tooltip?: TooltipConfig | boolean,
+ guide?: GuideConfig,
+ label?: LabelConfig | boolean,
+ polar: boolean,
+ innerRadius?: number;
+ borderStyle: any;
+ labelRender: any;
+}
+
+
+export class Hierarchy extends Base {
+ // 原 g2Factory 的第一个参数,改为类的属性。
+ chartName = 'G2Hierarchy';
+ convertData= false;
+
+ getDefaultConfig(): WhierarchyConfig {
+ return {
+ colors: themes.category_12,
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ label: {
+ offset: 0,
+ // textStyle: {
+ // fill: '#fff',
+ // shadowBlur: 2,
+ // shadowColor: 'rgba(0,0,0,0.6)',
+ // },
+ },
+ // label 文本展示的策略
+ labelRender: (depth: any, name: any, value: any, xRange: number[], yRange: number[]) => {
+ // 根据矩形大小判断是否渲染 label
+ if (xRange[1] - xRange[0] > 0.03 && yRange[1] - yRange[0] > 0.05) {
+ return name;
+ }
+ return;
+ },
+ innerRadius: 0,
+ polar: false,
+ // 区块的 border 样式,包含 lineWidth lineDash stroke 等属性
+ borderStyle: {},
+ };
+ }
+ init(chart: Chart, config: WhierarchyConfig, data: any) {
+
+ const dataView = processDataView(data);
+ const nodes = parseDataView(dataView);
+ chart.data(nodes);
+
+ // tooltip
+ rectTooltip(this, chart, config, {}, null, {
+ showMarkers: false,
+ showCrosshairs: false,
+ shared: false,
+ });
+
+ drawHierarchy(chart, config, config.colors);
+
+ // chart.render();
+ }
+ changeData(chart: Chart, config: WhierarchyConfig, data: any) {
+ const dataView = processDataView(data);
+ const nodes = parseDataView(dataView);
+ chart && chart.changeData(nodes);
+ }
+ // Chart 内容,方法名称与入参和原来一致
+}
+
+const Whierarchy: typeof Hierarchy = errorWrap(Hierarchy);
+
+export default Whierarchy;
+
+
+// 将 DataSet 处理后的结果转换为 G2 接受的数据
+function parseDataView(dv: any) {
+ const nodes = [];
+
+ for (const node of dv.getAllNodes()) {
+ const eachNode = {
+ name: node.data.name,
+ value: node.value,
+ depth: node.depth,
+ x: node.x,
+ y: node.y,
+ path: getNodePath(node).join('/'),
+ };
+
+ nodes.push(eachNode);
+ }
+
+ return nodes;
+}
+
+// 简单矩形树图
+function drawHierarchy(chart: Chart, config: WhierarchyConfig, colors: Colors, field = 'name') {
+ // 设置坐标系:极坐标/直角坐标
+ if (config.polar) {
+ chart.coordinate('polar', {
+ innerRadius: config.innerRadius || 0,
+ });
+ } else {
+ chart.coordinate();
+ }
+
+ chart.axis(false);
+ chart.legend(false);
+
+ chart
+ .polygon()
+ .position('x*y')
+ .color(field, colors)
+ .tooltip('name*value*path', (name, value, path) => ({
+ name,
+ value,
+ title: path,
+ }))
+ .style(config.borderStyle)
+ .label(
+ 'depth*name*value*x*y',
+ (depth, name, value, xs, ys) =>
+ config.labelRender(
+ depth,
+ name,
+ value,
+ [Math.min(...xs), Math.max(...xs)],
+ [Math.min(...ys), Math.max(...ys)],
+ ),
+ // config.label,
+ );
+}
+
+// 数据分箱
+function processDataView( data: any) {
+ return new View().source(data, { type: 'hierarchy' }).transform({
+ type: 'hierarchy.partition',
+ as: ['x', 'y'],
+ });
+}
+
+// 获取节点的路径
+function getNodePath(n: any): any {
+ if (!n.parent) {
+ return [n.data.name];
+ }
+ return [...getNodePath(n.parent), n.data.name];
+}
diff --git a/src/Whistogram/index.tsx b/src/Whistogram/index.tsx
new file mode 100644
index 00000000..7db0138a
--- /dev/null
+++ b/src/Whistogram/index.tsx
@@ -0,0 +1,322 @@
+'use strict';
+import { View } from '@antv/data-set/lib/view';
+import '@antv/data-set/lib/transform/bin/histogram';
+
+import { Chart, Types, BaseChartConfig, ChartData, Colors } from '../common/types';
+import Base from '../common/Base';
+import errorWrap from '../common/errorWrap';
+import themes from '../themes/index';
+import { propertyAssign, propertyMap } from '../common/common';
+
+import rectXAxis, { XAxisConfig } from '../common/rectXAxis';
+import rectYAxis, { YAxisConfig } from '../common/rectYAxis';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import guide, { GuideConfig } from '../common/guide';
+import label, { LabelConfig } from '../common/label';
+import legendFilter from '../common/legendFilter';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+
+// 3.x代码
+export interface WhistogramConfig extends BaseChartConfig {
+ colors?: Colors;
+ xAxis?: Types.ScaleOption & XAxisConfig | false,
+ yAxis?: Types.ScaleOption & YAxisConfig | false,
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ guide?: GuideConfig;
+ label?: LabelConfig | boolean;
+ bin?: any;
+ grid?: boolean;
+ geomStyle?: GeomStyleConfig;
+ normalize?: boolean;
+ polar?: boolean;
+ innerRadius?: number;
+ column?: boolean;
+}
+
+export class Histogram extends Base {
+ chartName = 'G2Histogram';
+
+ getDefaultConfig(): WhistogramConfig {
+ return {
+ colors: themes.category_12,
+ xAxis: {
+ // type: "cat",
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ categories: null,
+ autoRotate: false,
+ // 坐标轴粒度
+ // tickInterval: 1,
+ },
+ yAxis: {
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ max: null,
+ min: null
+ },
+ legend: {
+ align: "left",
+ nameFormatter: null // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null
+ },
+ grid: false,
+ label: false,
+ // 分箱粒度
+ bin: {
+ // bins: 10, // 分箱个数
+ binWidth: 1, // 分箱步长(会覆盖bins的配置)
+ offset: 0,
+ },
+ column: true,
+ // 是否归一化
+ normalize: false
+ };
+ }
+ init(chart: Chart, config: WhistogramConfig, data: any) {
+ const defs: Record = {
+ x: propertyAssign(propertyMap.axis, {
+ range: [0, 1],
+ }, config.xAxis),
+ y: propertyAssign(propertyMap.axis, {
+ type: 'linear',
+ nice: true,
+ // tickCount: 5,
+ }, config.yAxis),
+ type: {
+ type: 'cat',
+ },
+ };
+
+ const dataView = computerData(config, data);
+
+ chart.scale(defs);
+
+ chart.data(dataView.rows);
+
+
+ // 设置X轴
+ rectXAxis(this, chart, config);
+
+ // 设置单个Y轴
+ rectYAxis(this, chart, config);
+
+ // 设置图例
+ rectLegend(this, chart, config, null, false, "type");
+
+ legendFilter(this, chart);
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ position: 'top',
+ shared: true,
+ showMarkers: false,
+ },
+ null,
+ {
+ position: 'top',
+ shared: true,
+ showMarkers: false,
+ },
+ );
+
+ // 绘制辅助线,辅助背景区域
+ guide(chart, config);
+
+ // 设置坐标系:极坐标/直角坐标
+ const chartCoord = config.polar
+ ? chart.coordinate("polar", {
+ innerRadius: config.innerRadius || 0
+ })
+ : chart.coordinate();
+
+ // 横向柱状图
+ if (!config.column) {
+ chartCoord.transpose();
+ }
+
+ chart.interaction('active-region');
+
+ drawHist(chart, config);
+ }
+ changeData(chart: Chart, config: WhistogramConfig, data: any) {
+ const dataView = computerData(config, data);
+ chart && chart.changeData(dataView.rows);
+ }
+}
+
+function drawHist(chart: Chart, config: WhistogramConfig, field = "type") {
+ const { colors } = config;
+ const geom = chart
+ .interval()
+ .position('x*y')
+ .color(field, colors)
+ .adjust('stack');
+
+ geomStyle(geom, config.geomStyle);
+
+ label(geom, config);
+}
+
+function computerData(config: WhistogramConfig, data: ChartData) {
+ const { bins, binWidth, offset } = config.bin;
+
+ const dv = new View().source(data);
+ dv.transform({
+ type: 'bin.histogram',
+ field: 'x',
+ bins,
+ binWidth,
+ offset,
+ groupBy: ['type', 'visible'],
+ as: ['x', 'y'],
+ });
+
+ if (config.normalize) {
+ const total = dv.rows.reduce((acc, cur) => acc + cur.y, 0);
+ dv.transform({
+ type: 'map',
+ callback(row) {
+ row.y = row.y / total;
+ return row;
+ },
+ });
+ }
+
+ return dv;
+}
+
+const Whistogram: typeof Histogram = errorWrap(Histogram);
+
+export default Whistogram;
+
+// export default /*#__PURE__*/ errorWrap(g2Factory('G2Histogram', {
+// // convertData: false,
+// getDefaultConfig() {
+// return {
+// colors: themes.category_12,
+// padding: ['auto', 'auto', 'auto', 'auto'],
+// xAxis: {
+// // type: "cat",
+// labelFormatter: null, // 可以强制覆盖,手动设置label
+// categories: null,
+// autoRotate: false,
+// // 坐标轴粒度
+// // tickInterval: 1,
+// },
+// yAxis: {
+// labelFormatter: null, // 可以强制覆盖,手动设置label
+// max: null,
+// min: null
+// },
+// legend: {
+// align: "left",
+// nameFormatter: null // 可以强制覆盖,手动设置label
+// },
+// tooltip: {
+// titleFormatter: null,
+// nameFormatter: null,
+// valueFormatter: null
+// },
+// column: true,
+// grid: false,
+// size: null,
+// label: false,
+// innerRadius: 0,
+// // 分箱粒度
+// bin: {
+// // bins: 10, // 分箱个数
+// binWidth: 1, // 分箱步长(会覆盖bins的配置)
+// offset: 0,
+// },
+// // 是否归一化
+// normalize: false
+// };
+// },
+// beforeInit(props) {
+// const { config } = props;
+// const newConfig = merge({}, this.defaultConfig, config);
+
+// // TODO 处理padding
+// return Object.assign({}, props, {
+// padding: defaultPadding(
+// props.padding || config.padding,
+// newConfig,
+// ...this.defaultConfig.padding
+// ),
+// config: newConfig
+// });
+// },
+// init(chart, userConfig, data) {
+// const config = userConfig;
+
+// // 设置数据度量
+// const defs = {
+// x: propertyAssign(propertyMap.axis, {
+// // 折线图X轴的范围默认覆盖全部区域,保证没有空余
+// // range: [0, 1],
+// }, config.xAxis),
+// y: propertyAssign(propertyMap.axis, {
+// type: 'linear',
+// // tickCount: 5,
+// }, config.yAxis),
+// type: {
+// type: 'cat',
+// },
+// };
+
+// const dataView = computerData(config, data);
+// this.dataView = dataView;
+
+// chart.source(dataView, defs);
+
+// // 设置Y轴
+// rectYAxis(this, chart, config);
+
+// // 设置X轴
+// rectXAxis(this, chart, config);
+
+// // 设置图例
+// rectLegend(this, chart, config, null, false, "type");
+
+// legendFilter(this, chart, config);
+
+// // tooltip
+// rectTooltip(this, chart, config, {
+// crosshairs: config.polar ? undefined : {}
+// });
+
+// // 绘制辅助线,辅助背景区域
+// guide(chart, config);
+
+// // 设置坐标系:极坐标/直角坐标
+// const chartCoord = config.polar
+// ? chart.coord("polar", {
+// innerRadius: config.innerRadius || 0
+// })
+// : chart.coord();
+
+// // 横向柱状图
+// if (!config.column) {
+// chartCoord.transpose();
+// }
+
+// drawHist(chart, config, config.colors);
+
+// chart.render();
+// },
+// changeData(chart, config, data) {
+// if (this.dataView) {
+// this.dataView.source(data);
+// }
+// // chart.changeData(data);
+// },
+// }));
+
diff --git a/src/Wicon/cdn.scss b/src/Wicon/cdn.scss
new file mode 100644
index 00000000..6ea553a1
--- /dev/null
+++ b/src/Wicon/cdn.scss
@@ -0,0 +1,3 @@
+$icon-font-path: '//cdn.jsdelivr.net/npm/@alicloud/cloud-charts@1.0.0/build/font_180585_2frjb4evzia';
+
+@import "./index.scss";
diff --git a/src/Wicon/cdn.tsx b/src/Wicon/cdn.tsx
new file mode 100644
index 00000000..6c74613d
--- /dev/null
+++ b/src/Wicon/cdn.tsx
@@ -0,0 +1,55 @@
+'use strict';
+
+import * as React from 'react';
+import classNames from 'classnames';
+import { getStatusColorName } from '../common/common';
+import chartLog from "../common/log";
+import { FullCrossName, PrefixName } from '../constants';
+import './cdn.scss';
+import { Status } from '../common/types';
+
+const prefix = `${PrefixName}-wicon`;
+
+interface WiconProps {
+ className?: string;
+ style?: React.CSSProperties;
+ type?: string;
+ size?: string;
+ status?: Status | string;
+ reverse?: boolean;
+}
+
+export default class Wicon extends React.Component {
+ static displayName = 'Wicon';
+
+ static defaultProps = {
+ size: 'big',
+ type: 'monitor',
+ status: 'none'
+ };
+
+ constructor(props: WiconProps) {
+ super(props);
+
+ // 图表初始化时记录日志
+ chartLog('Wicon', 'init');
+ }
+
+ render() {
+ const { type, size, className, status, reverse, ...other } = this.props;
+ const classes = classNames({
+ [FullCrossName]: true,
+ // [`next-icon`]: true,
+ [`${prefix}-${type}`]: !!type,
+ [`${prefix}`]: true,
+ [`${prefix}-${size}`]: !!size,
+ [`${prefix}-${getStatusColorName(status)}`]: !!status,
+ [`${prefix}-reverse`]: !!reverse,
+ [className]: !!className
+ });
+
+ return (
+
+ );
+ }
+}
diff --git a/components/Wicon/font_180585_2frjb4evzia.eot b/src/Wicon/font_180585_2frjb4evzia.eot
similarity index 100%
rename from components/Wicon/font_180585_2frjb4evzia.eot
rename to src/Wicon/font_180585_2frjb4evzia.eot
diff --git a/components/Wicon/font_180585_2frjb4evzia.svg b/src/Wicon/font_180585_2frjb4evzia.svg
similarity index 100%
rename from components/Wicon/font_180585_2frjb4evzia.svg
rename to src/Wicon/font_180585_2frjb4evzia.svg
diff --git a/components/Wicon/font_180585_2frjb4evzia.ttf b/src/Wicon/font_180585_2frjb4evzia.ttf
similarity index 100%
rename from components/Wicon/font_180585_2frjb4evzia.ttf
rename to src/Wicon/font_180585_2frjb4evzia.ttf
diff --git a/components/Wicon/font_180585_2frjb4evzia.woff b/src/Wicon/font_180585_2frjb4evzia.woff
similarity index 100%
rename from components/Wicon/font_180585_2frjb4evzia.woff
rename to src/Wicon/font_180585_2frjb4evzia.woff
diff --git a/components/Wicon/font_180585_2frjb4evzia.woff2 b/src/Wicon/font_180585_2frjb4evzia.woff2
similarity index 100%
rename from components/Wicon/font_180585_2frjb4evzia.woff2
rename to src/Wicon/font_180585_2frjb4evzia.woff2
diff --git a/components/Wicon/index.scss b/src/Wicon/index.scss
similarity index 100%
rename from components/Wicon/index.scss
rename to src/Wicon/index.scss
diff --git a/components/Wicon/index.jsx b/src/Wicon/index.tsx
similarity index 64%
rename from components/Wicon/index.jsx
rename to src/Wicon/index.tsx
index c8561543..f09b7cb1 100644
--- a/components/Wicon/index.jsx
+++ b/src/Wicon/index.tsx
@@ -1,15 +1,25 @@
'use strict';
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
import classNames from 'classnames';
import { getStatusColorName } from '../common/common';
import chartLog from "../common/log";
+import { FullCrossName, PrefixName } from '../constants';
import './index.scss';
+import { Status } from '../common/types';
-const prefix = 'cloud-wicon';
+const prefix = `${PrefixName}-wicon`;
-export default class Wicon extends React.Component {
+interface WiconProps {
+ className?: string;
+ style?: React.CSSProperties;
+ type?: string;
+ size?: string;
+ status?: Status | string;
+ reverse?: boolean;
+}
+
+export default class Wicon extends React.Component {
static displayName = 'Wicon';
static defaultProps = {
@@ -18,7 +28,7 @@ export default class Wicon extends React.Component {
status: 'none'
};
- constructor(props) {
+ constructor(props: WiconProps) {
super(props);
// 图表初始化时记录日志
@@ -28,7 +38,7 @@ export default class Wicon extends React.Component {
render() {
const { type, size, className, status, reverse, ...other } = this.props;
const classes = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
// [`next-icon`]: true,
[`${prefix}-${type}`]: !!type,
[`${prefix}`]: true,
@@ -43,8 +53,3 @@ export default class Wicon extends React.Component {
);
}
}
-
-Wicon.propTypes = {
- type: PropTypes.string,
-};
-
diff --git a/components/Wnumber/scss/function.scss b/src/Wicon/scss/function.scss
similarity index 100%
rename from components/Wnumber/scss/function.scss
rename to src/Wicon/scss/function.scss
diff --git a/components/Wicon/scss/mixin.scss b/src/Wicon/scss/mixin.scss
similarity index 100%
rename from components/Wicon/scss/mixin.scss
rename to src/Wicon/scss/mixin.scss
diff --git a/components/Wicon/scss/variable.scss b/src/Wicon/scss/variable.scss
similarity index 99%
rename from components/Wicon/scss/variable.scss
rename to src/Wicon/scss/variable.scss
index 5b363c5b..19973498 100644
--- a/components/Wicon/scss/variable.scss
+++ b/src/Wicon/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wicon-prefix: '.cloud-wicon';
+$wicon-prefix: '.#{$base-prefix}-wicon';
$white: getVar(widgets-color-background, $widgets-color-background);
$blue: getVar(widgets-color-blue, $widgets-color-blue);
@@ -14,7 +14,7 @@ $icon-font-path: "./font_180585_2frjb4evzia" !default;
$icon-font-name: "icon" !default;
$icon-font-family: WidgetsIcon !default;
-$icon-prefix: 'cloud-wicon' !default;
+$icon-prefix: '#{$base-prefix}-wicon' !default;
$icon-size-1: getVar(s1, $s1);
diff --git a/components/Wline/gui.schema.json b/src/Wline/gui.schema.json
similarity index 100%
rename from components/Wline/gui.schema.json
rename to src/Wline/gui.schema.json
diff --git a/components/Wnumber/scss/mixin.scss b/src/Wline/index.scss
similarity index 100%
rename from components/Wnumber/scss/mixin.scss
rename to src/Wline/index.scss
diff --git a/src/Wline/index.tsx b/src/Wline/index.tsx
new file mode 100644
index 00000000..e8fee00a
--- /dev/null
+++ b/src/Wline/index.tsx
@@ -0,0 +1,209 @@
+'use strict';
+
+import { Chart, Types, BaseChartConfig } from '../common/types';
+import Base from "../common/Base";
+import errorWrap from '../common/errorWrap';
+import themes from '../themes';
+import { getDataIndexColor, propertyAssign, propertyMap } from '../common/common';
+import guide, { GuideConfig } from '../common/guide';
+import rectXAxis, { XAxisConfig } from '../common/rectXAxis';
+import rectYAxis, { YAxisConfig } from '../common/rectYAxis';
+import autoTimeMask from '../common/autoTimeMask';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import legendFilter from '../common/legendFilter';
+import rectZoom, { ZoomConfig } from "../common/rectZoom";
+import rectSlider, { SliderConfig } from '../common/rectSlider';
+import drawLine, { DrawLineConfig } from '../common/drawLine';
+import './index.scss';
+
+export interface WlineConfig extends BaseChartConfig, DrawLineConfig, ZoomConfig, SliderConfig {
+ /** X轴配置项 */
+ xAxis?: Types.ScaleOption & XAxisConfig | false;
+ /** Y轴配置项 */
+ yAxis?: Types.ScaleOption & YAxisConfig | false;
+ /** 图例配置项 */
+ legend?: LegendConfig | boolean;
+ /** 提示信息配置项 */
+ tooltip?: TooltipConfig | boolean;
+ /** 辅助标记配置项 */
+ guide?: GuideConfig;
+ /** 显示网格线 */
+ grid?: boolean;
+}
+
+export class Line extends Base {
+ chartName = 'G2Line';
+
+ getDefaultConfig(): WlineConfig {
+ return {
+ colors: themes.category_12,
+ areaColors: [],
+ xAxis: {
+ type: 'time', // 默认为线性
+ mask: 'auto', // 上述type为time时,此字段生效
+ },
+ yAxis: {
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ max: null,
+ min: null,
+ },
+ legend: {
+ align: 'left',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ area: false,
+ stack: false, // 仅Area有效
+ spline: false,
+ grid: false,
+ symbol: false,
+ zoom: false,
+ label: false,
+ step: null,
+ // TODO
+ // mini: false,
+ // dataConfig: {
+ // nameKey: 'name',
+ // valueKey: 'value',
+ // // valueKey: ['value1', 'value2'],
+ // typeKey: 'type'
+ // }
+ };
+ }
+ init(chart: Chart, config: WlineConfig, data: any) {
+ const defs: Record = {
+ x: propertyAssign(propertyMap.axis, {
+ type: 'time',
+ // 折线图X轴的范围默认覆盖全部区域,保证没有空余
+ range: [0, 1],
+ }, config.xAxis),
+ type: {
+ type: 'cat',
+ },
+ };
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((axis, yIndex) => {
+ defs[`y${yIndex}`] = propertyAssign(propertyMap.axis, {
+ type: 'linear',
+ tickCount: 5,
+ nice: true,
+ }, axis);
+ });
+ } else {
+ defs.y = propertyAssign(propertyMap.axis, {
+ type: 'linear',
+ tickCount: 5,
+ nice: true,
+ }, config.yAxis);
+ }
+
+ autoTimeMask(defs, this.rawData);
+
+ // rectAutoTickCount(chart, config, defs, false);
+
+ chart.scale(defs);
+
+ chart.data(data);
+
+ // 设置X轴
+ rectXAxis(this, chart, config);
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((axis, yIndex) => {
+ const yAxisConfig: Types.AxisCfg = {
+ line: {
+ style: {
+ stroke: getDataIndexColor(config.colors, this.rawData, yIndex) || themes['widgets-axis-line'],
+ },
+ },
+ };
+ if (yIndex !== 0) {
+ yAxisConfig.grid = null;
+ }
+
+ rectYAxis(this, chart, { ...config, yAxis: axis }, `y${yIndex}`, yAxisConfig);
+ });
+ } else {
+ // 设置单个Y轴
+ rectYAxis(this, chart, config);
+ }
+
+ // 设置图例
+ rectLegend(this, chart, config, null, false, 'type');
+
+ legendFilter(this, chart);
+
+ // tooltip
+ rectTooltip(this, chart, config);
+
+ // 绘制辅助线,辅助背景区域
+ guide(chart, config);
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((asix, yIndex) => {
+ drawLine(chart, config, `y${yIndex}`);
+ });
+ } else {
+ drawLine(chart, config);
+ }
+
+ // 拖拽缩放
+ rectZoom(chart, config, this.language);
+
+ // 缩略轴
+ rectSlider(chart, config);
+ }
+}
+
+/** Wline 折线图 */
+const Wline: typeof Line = errorWrap(Line);
+
+export default Wline;
+
+// /*#__PURE__*/errorWrap(g2Factory('G2Line', {
+// beforeInit(props) {
+// const { config } = props;
+// const newConfig = merge({}, this.defaultConfig, config);
+//
+// // // TODO 处理padding
+// // let defaultPaddingTop = defaultConfig.padding[0];
+// // let defaultPaddingRight = defaultConfig.padding[1];
+// // const defaultPaddingBottom = defaultConfig.padding[2];
+// // const defaultPaddingLeft = defaultConfig.padding[3];
+// // if (defaultPaddingRight !== 'auto' && Array.isArray(newConfig.yAxis)) {
+// // defaultPaddingRight = 44;
+// // }
+// // if (defaultPaddingTop !== 'auto' && !newConfig.legend) {
+// // defaultPaddingTop = 16;
+// // }
+// return Object.assign({}, props, {
+// // padding: props.padding || config.padding || [defaultPaddingTop, defaultPaddingRight, defaultPaddingBottom, defaultPaddingLeft],
+// padding: defaultPadding(props.padding || config.padding, newConfig, ...this.defaultConfig.padding),
+// config: newConfig,
+// });
+// },
+// changeData(chart, config, data) {
+// chart.changeData(data);
+//
+// // 更新 brush 的 scale 实例,fix 数据更新后拖动缩放失效的问题。
+// if (config.zoom && this.brush) {
+// this.brush.xScale = chart.getXScale();
+// this.brush.yScale = chart.getYScales()[0];
+// }
+// },
+// destroy() {
+// // 销毁时需要额外销毁缩放重置按钮
+// if (this.brush) {
+// this.brush.destroy();
+// }
+// if (this.resetButton) {
+// this.resetButton.destroy();
+// }
+// },
+// }));
diff --git a/components/Wlinebar/gui.schema.json b/src/Wlinebar/gui.schema.json
similarity index 100%
rename from components/Wlinebar/gui.schema.json
rename to src/Wlinebar/gui.schema.json
diff --git a/components/Wplaceholder/scss/function.scss b/src/Wlinebar/index.scss
similarity index 100%
rename from components/Wplaceholder/scss/function.scss
rename to src/Wlinebar/index.scss
diff --git a/src/Wlinebar/index.tsx b/src/Wlinebar/index.tsx
new file mode 100644
index 00000000..1fb8f368
--- /dev/null
+++ b/src/Wlinebar/index.tsx
@@ -0,0 +1,693 @@
+'use strict';
+
+import { Chart, View, Geometry, Types, BaseChartConfig, ChartData, Colors } from '../common/types';
+import Base, { ChartProps } from "../common/Base";
+import { MarkerSymbols } from "@antv/g2/esm/util/marker";
+import { getShapeFactory } from "@antv/g2/esm/core";
+import errorWrap from '../common/errorWrap';
+import themes from '../themes/index';
+import { propertyAssign, getDataIndexColor, propertyMap } from '../common/common';
+import highchartsDataToG2Data, { DataAdapterConfig, DataAdapterData } from '../common/dataAdapter';
+import { drawGuideArea, drawGuideLine, drawGuideFilter, GuideConfig, GuideLineConfig, GuideAreaConfig, GuideFilterConfig } from '../common/guide';
+import rectXAxis, { XAxisConfig } from '../common/rectXAxis';
+import rectYAxis, { YAxisConfig } from '../common/rectYAxis';
+import autoTimeMask from '../common/autoTimeMask';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import legendFilter from '../common/legendFilter';
+import label, { LabelConfig } from '../common/label';
+import geomSize, { GeomSizeConfig } from '../common/geomSize';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import './index.scss';
+import { warn } from '../common/log';
+
+interface WlinebarConfig extends BaseChartConfig, BarConfig, LineConfig {
+ xAxis?: Types.ScaleOption & XAxisConfig | false,
+ yAxis?: Types.ScaleOption & YAxisConfig | false,
+ legend?: LegendConfig | boolean,
+ tooltip?: TooltipConfig | boolean,
+ guide?: GuideConfig,
+ grid?: boolean,
+}
+
+function getLegendItems(
+ lineData: DataAdapterData[],
+ barData: DataAdapterData[],
+ lineGeom: Geometry,
+ barGeom: Geometry,
+ config: WlinebarConfig
+) {
+ const result: any[] = [];
+ const reMap: { [key: string]: boolean } = {};
+ const { lineColors, barColors } = config;
+ function getItems(
+ data: DataAdapterData[],
+ geom: Geometry,
+ shapeType: string,
+ colors: Colors,
+ style?: Types.LooseObject,
+ ) {
+ data.forEach((d, i) => {
+ const { name, visible, data } = d;
+ if (reMap[name] || !data || data.length === 0) {
+ return;
+ } else {
+ reMap[name] = true;
+ }
+ let marker;
+ const shapeFactory = getShapeFactory(geom.shapeType);
+ if (shapeFactory) {
+ marker = shapeFactory.getMarker(shapeType, {
+ color: typeof colors === 'string' ? colors : (Array.isArray(colors) ? colors[i % colors.length] : colors(name)),
+ isInPolar: false,
+ });
+
+ const symbol = marker.symbol;
+ // @ts-ignore
+ if (typeof symbol === 'string' && MarkerSymbols[symbol]) {
+ // @ts-ignore
+ marker.symbol = MarkerSymbols[symbol];
+ }
+ }
+ if (style) {
+ Object.assign(marker.style, style);
+ }
+ result.push({
+ id: name,
+ name,
+ value: name,
+ marker,
+ unchecked: visible === false,
+ });
+ });
+ }
+ getItems(barData, barGeom, 'point', barColors);
+ const { area, spline } = config;
+ let lineShapeType = 'line';
+ const lineStyle: Types.LooseObject = {};
+ if (area) {
+ lineShapeType = 'area';
+ }
+ if (spline) {
+ lineShapeType = 'smooth';
+ }
+ if (!area && spline) {
+ lineStyle.fill = null;
+ }
+ getItems(lineData, lineGeom, lineShapeType, lineColors, lineStyle);
+ // lineData.forEach((d, i) => {
+ // const { name, visible } = d;
+ // if (reMap[name]) {
+ // return;
+ // }
+ // let marker;
+ // const shapeFactory = getShapeFactory(lineGeom.shapeType);
+ // if (shapeFactory) {
+ // marker = shapeFactory.getMarker('point', {
+ // color: lineColors[i % lineColors.length],
+ // isInPolar: false,
+ // });
+ // // lineGeom.getShapeMarker
+ //
+ // const symbol = marker.symbol;
+ // // @ts-ignore
+ // if (typeof symbol === 'string' && MarkerSymbols[symbol]) {
+ // // @ts-ignore
+ // marker.symbol = MarkerSymbols[symbol];
+ // }
+ // }
+ //
+ // result.push({
+ // id: name,
+ // name,
+ // value: name,
+ // marker,
+ // unchecked: visible === false,
+ // });
+ // reMap[name] = true;
+ // });
+ // barData.forEach((d, i) => {
+ // const { name, visible } = d;
+ // if (reMap[name]) {
+ // return;
+ // }
+ // let marker;
+ // const shapeFactory = getShapeFactory(barGeom.shapeType);
+ // if (shapeFactory) {
+ // marker = shapeFactory.getMarker('point', {
+ // color: barColors[i % barColors.length],
+ // isInPolar: false,
+ // });
+ //
+ // const symbol = marker.symbol;
+ // // @ts-ignore
+ // if (typeof symbol === 'string' && MarkerSymbols[symbol]) {
+ // // @ts-ignore
+ // marker.symbol = MarkerSymbols[symbol];
+ // }
+ // }
+ //
+ // result.push({
+ // id: name,
+ // name,
+ // value: name,
+ // marker,
+ // unchecked: visible === false,
+ // });
+ // reMap[name] = true;
+ // });
+ return result;
+}
+
+export class Linebar extends Base {
+ chartName = 'G2LineBar';
+
+ convertData = false;
+
+ getDefaultConfig(): WlinebarConfig {
+ return {
+ lineColors: themes.category_12.slice(1),
+ barColors: themes.linear_10,
+ padding: 'auto',
+ xAxis: {
+ type: 'timeCat', // 默认为线性
+ mask: 'YYYY-MM-DD HH:mm:ss', // 上述type为time时,此字段生效
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ categories: null,
+ // autoRotate: false,
+ max: null,
+ min: null,
+ },
+ yAxis: {
+ labelFormatter: null, // 可以强制覆盖,手动设置label
+ max: null,
+ min: null,
+ },
+ legend: {
+ align: 'left',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ titleFormatter: null,
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ area: false,
+ dodgeStack: false,
+ stack: false, // 仅Area有效
+ stackReverse: true,
+ marginRatio: 0,
+ spline: false,
+ grid: false,
+ symbol: false,
+ // lineLabel: undefined,
+ // barLabel: undefined,
+ // TODO
+ // zoom: false,
+ // mini: false,
+ // dataConfig: {
+ // nameKey: 'name',
+ // valueKey: 'value',
+ // // valueKey: ['value1', 'value2'],
+ // typeKey: 'type'
+ // }
+ }
+ }
+
+ beforeInit(props: ChartProps): ChartProps {
+ return {
+ syncViewPadding: true,
+ ...props,
+ }
+ }
+
+ rawLineData: DataAdapterData[] = [];
+ lineView: View;
+
+ rawBarData: DataAdapterData[] = [];
+ barView: View;
+
+ init(chart: Chart, config: WlinebarConfig, data: ChartData) {
+ const rawLineData: DataAdapterData[] = [];
+ this.rawLineData = rawLineData;
+ const rawBarData: DataAdapterData[] = [];
+ this.rawBarData = rawBarData;
+ (data || []).forEach((d: DataAdapterData) => {
+ if (d.type === 'line') {
+ rawLineData.push(d);
+ } else if (d.type === 'bar') {
+ rawBarData.push(d);
+ }
+ });
+
+ const lineData = highchartsDataToG2Data(rawLineData, config as DataAdapterConfig, {
+ // type: 'lineType',
+ });
+ const barData = highchartsDataToG2Data(rawBarData, config as DataAdapterConfig, {
+ // type: 'barType',
+ });
+
+ const defs: Record = {
+ x: propertyAssign(propertyMap.axis, {
+ type: 'cat',
+ // fix 更新数据时x轴无法清除数据
+ // sync: 'x',
+ }, config.xAxis),
+ type: {
+ type: 'cat',
+ },
+ };
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((axis, yIndex) => {
+ defs[`y${yIndex}`] = propertyAssign(propertyMap.axis, {
+ type: 'linear',
+ tickCount: 5,
+ nice: true,
+ }, axis);
+ });
+ } else {
+ defs.y = propertyAssign(propertyMap.axis, {
+ type: 'linear',
+ tickCount: 5,
+ // 单轴时,必须同步度量,否则会两个度量叠加在一起
+ sync: true,
+ nice: true,
+ }, config.yAxis);
+ }
+
+ autoTimeMask(defs, this.rawData);
+
+ chart.scale(defs);
+
+ // 设置X轴
+ rectXAxis(this, chart, config);
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((axis, yIndex) => {
+ const axisColor = getDataIndexColor(config.lineColors, rawLineData, yIndex) || getDataIndexColor(config.barColors, rawBarData, yIndex) || themes['widgets-axis-line'];
+ const yAxisConfig: Types.AxisCfg = {
+ line: {
+ style: {
+ stroke: axisColor,
+ }
+ },
+ };
+ if (yIndex !== 0) {
+ yAxisConfig.grid = null;
+ // 因为是多个view组成的图表,所以这里需要移动位置
+ yAxisConfig.position = 'right';
+ }
+
+ rectYAxis(this, chart, { ...config, yAxis: axis }, `y${yIndex}`, yAxisConfig);
+ });
+ } else {
+ // 设置单个Y轴
+ rectYAxis(this, chart, config);
+ }
+
+ // 设置图例
+ // const legendStyle = {
+ // ...legendHtmlContainer,
+ // display: 'inline-block',
+ // position: 'relative',
+ // };
+ // // const legendItemStyle = {
+ // // ...legendHtmlListItem,
+ // // };
+ // if (config.legend !== false) {
+ // const { position, align } = config.legend || {};
+ //
+ // // if (position === 'top') {
+ // // legendStyle.top = themes['widgets-font-size-1'];
+ // // }
+ //
+ // if (align === 'right') {
+ // legendStyle.marginLeft = themes['widgets-font-size-1'];
+ // } else if (align === 'left') {
+ // legendStyle.marginRight = themes['widgets-font-size-1'];
+ // } else if (align === 'center') {
+ // legendStyle.marginRight = themes['widgets-font-size-1'];
+ // } else {
+ // // 默认放到左边
+ // legendStyle.marginRight = themes['widgets-font-size-1'];
+ // }
+ //
+ // if (position === 'bottom') {
+ // legendStyle.top = '100%';
+ // legendStyle.transform = 'translate(0, -100%)';
+ // legendStyle.overflow = 'visible';
+ // legendStyle.verticalAlign = 'top';
+ //
+ // // legendItemStyle.marginBottom = 0;
+ // // legendItemStyle.marginTop = themes['widgets-font-size-1'];
+ // }
+ // }
+
+
+ // tooltip
+ rectTooltip(this, chart, config, {}, null, {
+ showCrosshairs: false,
+ showMarkers: false
+ });
+
+ // 正式开始绘图,创建两个不同的view
+ const barView = chart.createView({
+ padding: config.padding === 'auto' ? 'auto' : 0,
+ });
+ barView.data(barData);
+ this.barView = barView;
+
+ // Tooltip 背景区域
+ barView.interaction('active-region');
+
+ const lineView = chart.createView({
+ padding: config.padding === 'auto' ? 'auto' : 0,
+ });
+ lineView.data(lineData);
+ this.lineView = lineView;
+ // 关闭一个View的X轴,避免重叠字体变粗
+ lineView.axis('x', false);
+
+ if (Array.isArray(config.yAxis)) {
+ config.yAxis.forEach((asix, yIndex) => {
+ if (getDataIndexColor(config.barColors, rawBarData, yIndex)) {
+ drawBar(barView, config, `y${yIndex}`, 'type');
+ }
+ if (getDataIndexColor(config.lineColors, rawLineData, yIndex)) {
+ drawLine(lineView, config, `y${yIndex}`, 'type');
+ }
+ });
+ } else {
+ // 单Y轴时同时关闭一个View的Y轴,避免重叠字体变粗
+ lineView.axis('y', false);
+
+ drawBar(barView, config, 'y', 'type');
+ drawLine(lineView, config, 'y', 'type');
+ }
+
+ // 绘制辅助线,辅助背景区域
+ viewGuide(config, lineView, rawLineData, barView, rawBarData);
+
+ legendFilter(this, barView, 'rawBarData');
+ legendFilter(this, lineView, 'rawLineData');
+
+ rectLegend(this, chart, config, {
+ items: getLegendItems(rawLineData, rawBarData, lineView.geometries[0], barView.geometries[0], config),
+ }, false);
+
+ // chart.on('afterrender', () => {
+ // // chart.getLegendAttributes()
+ // // console.log('getLegendAttributes', barView.geometries[0].getAttribute('shape'));
+ // // console.log('getLegendAttributes', lineView.geometries[0].getAttribute('shape'));
+ // lineView.geometries.forEach((geom) => {
+ // const shapeAttr = geom.getAttribute('shape');
+ //
+ // const shape = getMappingValue(shapeAttr, '机房3', 'point');
+ // let marker = geom.getShapeMarker(shape, {
+ // color: 'red',
+ // isInPolar: false,
+ // });
+ //
+ // console.log(marker);
+ // })
+ // // console.log(getLegendItems(rawLineData, rawBarData, lineView.geometries[0], barView.geometries[0], config));
+ //
+ // // console.log(chart.getController('legend'));
+ // })
+ }
+
+ changeData(chart: Chart, config: WlinebarConfig, data: ChartData) {
+ const rawLineData: DataAdapterData[] = [];
+ this.rawLineData = rawLineData;
+ const rawBarData: DataAdapterData[] = [];
+ this.rawBarData = rawBarData;
+ (data || []).forEach((d: DataAdapterData) => {
+ if (d.type === 'line') {
+ rawLineData.push(d);
+ } else if (d.type === 'bar') {
+ rawBarData.push(d);
+ }
+ });
+
+ const lineData = highchartsDataToG2Data(rawLineData, config as DataAdapterConfig, {
+ // type: 'lineType',
+ });
+ const barData = highchartsDataToG2Data(rawBarData, config as DataAdapterConfig, {
+ // type: 'barType',
+ });
+
+ this.barView && this.barView.data(barData);
+ this.lineView && this.lineView.data(lineData);
+
+ if (this.barView && this.lineView) {
+ const chartOptions = chart.getOptions();
+ const legend = chart.getController('legend');
+ const legendCos = legend.getComponents();
+ // 图例项可见,更新图例项
+ if (legend.visible && legendCos.length > 0 && typeof chartOptions.legends === 'object') {
+ chartOptions.legends.items = getLegendItems(
+ rawLineData,
+ rawBarData,
+ this.lineView.geometries[0],
+ this.barView.geometries[0],
+ config
+ );
+ // chart.legend({
+ // items: newItems
+ // });
+ }
+ }
+
+ // 更新数据后再次render,保证 padding 能正确计算。
+ chart.render(true);
+ }
+}
+
+const Wlinebar: typeof Linebar = errorWrap(Linebar);
+
+export default Wlinebar;
+
+interface BarConfig {
+ barColors?: Colors;
+ stack?: boolean;
+ stackReverse?: boolean;
+ marginRatio?: number;
+ dodgeStack?: boolean;
+ lineLabel?: LabelConfig | boolean,
+ barGeomStyle?: GeomStyleConfig;
+}
+function drawBar(chart: View, config: WlinebarConfig, yAxisKey = 'y', legendKey = 'type') {
+ const { stack, stackReverse, marginRatio, dodgeStack } = config;
+
+ let intervalGeom = null;
+ if (dodgeStack) {
+ intervalGeom = chart.interval()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.barColors)
+ .adjust([
+ {
+ type: 'dodge',
+ marginRatio: marginRatio || 0, // 数值范围为 0 至 1,用于调整分组中各个柱子的间距
+ dodgeBy: 'dodge',
+ },
+ {
+ type: 'stack',
+ reverseOrder: !stackReverse, // 层叠顺序倒序
+ },
+ ]);
+ } else if (stack) {
+ intervalGeom = chart.interval()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.barColors)
+ .adjust([{
+ type: 'stack',
+ reverseOrder: !stackReverse, // 层叠顺序倒序
+ }]);
+ } else {
+ intervalGeom = chart.interval()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.barColors)
+ .adjust([{
+ type: 'dodge',
+ marginRatio: marginRatio || 0, // 数值范围为 0 至 1,用于调整分组中各个柱子的间距
+ }]);
+ }
+
+ geomStyle(intervalGeom, config.barGeomStyle, {}, `x*${yAxisKey}*${legendKey}*extra`);
+
+ label(intervalGeom, config, yAxisKey, null, 'barLabel');
+
+ return intervalGeom;
+}
+
+interface LineConfig {
+ // colors?: string[];
+ // areaColors?: string[];
+ lineColors?: Colors;
+ area?: boolean,
+ stack?: boolean, // 仅Area有效
+ spline?: boolean,
+ step?: string | boolean,
+ symbol?: {
+ size?: GeomSizeConfig;
+ geomStyle?: GeomStyleConfig;
+ } | boolean,
+ lineLabel?: LabelConfig | boolean,
+ lineWidth?: number;
+ lineGeomStyle?: GeomStyleConfig;
+}
+function drawLine(chart: View, config: WlinebarConfig, yAxisKey = 'y', legendKey = 'type') {
+ let lineGeom = null;
+ const { lineWidth } = config;
+ // const geomStyle = config.lineGeomStyle || {};
+ // if (lineWidth !== undefined) {
+ // geomStyle.lineWidth = lineWidth;
+ // }
+
+ // 区域、堆叠、平滑曲线
+ const lineShape = config.spline ? 'smooth' : 'line';
+ const areaShape = config.spline ? 'smooth' : 'area';
+
+ const stack = config.stack || config.dodgeStack;
+
+ if (config.area && stack) {
+ chart.area()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape(areaShape)
+ .adjust('stack');
+ lineGeom = chart.line()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape(lineShape)
+ .adjust('stack');
+ // .style({
+ // lineJoin: 'round',
+ // ...geomStyle,
+ // });
+ } else if (config.area && !stack) {
+ chart.area()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape(areaShape)
+ lineGeom = chart.line()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape(lineShape);
+ // .style({
+ // lineJoin: 'round',
+ // ...geomStyle,
+ // });
+ } else {
+ lineGeom = chart.line()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape(lineShape);
+ // .style({
+ // lineJoin: 'round',
+ // ...geomStyle,
+ // });
+ }
+
+ geomStyle(lineGeom, config.lineGeomStyle, {
+ lineWidth,
+ lineJoin: 'round',
+ }, `x*${yAxisKey}*${legendKey}*extra`);
+
+ label(lineGeom, config, yAxisKey, null, 'lineLabel');
+
+ // 曲线默认点
+ if (config.symbol) {
+ let pointGeom = null;
+
+ if (config.area && stack) {
+ pointGeom = chart.point()
+ .adjust('stack')
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape('circle')
+ .size(3)
+ } else {
+ pointGeom = chart.point()
+ .position(['x', yAxisKey])
+ .color(legendKey, config.lineColors)
+ .shape('circle')
+ .size(3)
+ }
+
+ if (typeof config.symbol === 'object') {
+ geomSize(pointGeom, config.symbol.size, 3, yAxisKey, legendKey);
+
+ if (config.symbol.geomStyle) {
+ geomStyle(pointGeom, config.symbol.geomStyle, {}, `x*${yAxisKey}*${legendKey}*extra`);
+ }
+ }
+ }
+
+ return lineGeom;
+}
+
+function viewGuide(config: WlinebarConfig, lineView: View, rawLineData: DataAdapterData[], barView: View, rawBarData: DataAdapterData[]) {
+ const { guide } = config;
+ if (!guide) {
+ return;
+ }
+
+ const { line: guideLine, area: guideArea, filter: guideFilter, ...other } = guide;
+
+ if (guideLine) {
+ if (Array.isArray(guideLine)) {
+ guideLine.forEach((line) => {
+ drawGuideLine(getGuideView(config, line, lineView, rawLineData, barView, rawBarData), line);
+ });
+ } else {
+ drawGuideLine(getGuideView(config, guideLine, lineView, rawLineData, barView, rawBarData), guideLine);
+ }
+ }
+
+ if (guideArea) {
+ if (Array.isArray(guideArea)) {
+ guideArea.forEach((area) => {
+ drawGuideArea(getGuideView(config, area, lineView, rawLineData, barView, rawBarData), area);
+ });
+ } else {
+ drawGuideArea(getGuideView(config, guideArea, lineView, rawLineData, barView, rawBarData), guideArea);
+ }
+ }
+
+ if (guideFilter) {
+ if (Array.isArray(guideFilter)) {
+ guideFilter.forEach((filter) => {
+ drawGuideFilter(getGuideView(config, filter, lineView, rawLineData, barView, rawBarData), filter);
+ });
+ } else {
+ drawGuideFilter(getGuideView(config, guideFilter, lineView, rawLineData, barView, rawBarData), guideFilter);
+ }
+ }
+
+ if (!guideLine && !guideArea && !guideFilter && Object.keys(other).length > 0) {
+ warn('config.guide', '配置异常,请使用 guide.line、guide.area、guide.filter');
+ }
+}
+
+type SimpleGuideConfig = { target?: string; } & ( GuideLineConfig | GuideAreaConfig | GuideFilterConfig );
+function getGuideView(config: WlinebarConfig, guide: SimpleGuideConfig, lineView: View, rawLineData: DataAdapterData[], barView: View, rawBarData: DataAdapterData[]) {
+ const { target, axis, value } = guide;
+
+ // 如果用户指定了绘制目标,直接使用
+ if (target === 'line') {
+ return lineView;
+ } else if (target === 'bar') {
+ return barView;
+ }
+
+ if (axis && (value || value === 0) && /y\d/.test(axis)) {
+ const yIndex = Number(axis.replace(/^y/, ''));
+ if (getDataIndexColor(config.barColors, rawBarData, yIndex)) {
+ return barView;
+ }
+ }
+
+ return lineView;
+}
diff --git a/src/Wmap/child.tsx b/src/Wmap/child.tsx
new file mode 100644
index 00000000..bde7c025
--- /dev/null
+++ b/src/Wmap/child.tsx
@@ -0,0 +1,120 @@
+import { VoidFunctionComponent, ReactNode } from 'react';
+import { Types, ChartData } from '../common/types';
+// import Wmap, { WmapConfig } from "./index";
+// import { provinceName } from "./mapData/chinaGeoInfo";
+// import * as React from "react";
+
+export interface MapChildProps {
+ data?: ChartData;
+ config?: Types.LooseObject;
+}
+
+// class ChildBase {
+// parent: Wmap = null;
+//
+// init (ctx: Wmap, config: WmapConfig, data: ChartData) {
+// this.parent = ctx;
+// }
+//
+// changeData(data: ChartData) {}
+// }
+
+export const AREA_NAME = 'MapArea';
+export const MapArea: VoidFunctionComponent = () => { return null; };
+MapArea.displayName = AREA_NAME;
+
+// class Area extends ChildBase {
+// init (ctx: Wmap, config: WmapConfig, data: ChartData) {
+// super.init(ctx, config, data);
+//
+// const { chart, ds } = ctx;
+//
+// const areaMapDataView = ds
+// .createView()
+// .source(data)
+// .transform({
+// type: 'map',
+// callback(obj) {
+// const { name, type, ...others } = obj;
+// return {
+// // @ts-ignore 将省份全称转化为简称
+// name: provinceName[name] ? provinceName[name] : name,
+// type: String(type),
+// ...others,
+// };
+// },
+// })
+// .transform({
+// geoDataView: ctx.bgMapDataView,
+// field: 'name',
+// type: 'geo.region',
+// as: ['x', 'y'],
+// });
+//
+// const areaMapView = chart.createView({
+// padding: 0,
+// });
+// areaMapView.data(areaMapDataView.rows);
+// /*const areaGeom = */areaMapView
+// .polygon()
+// .position('x*y')
+// // 如果用连续型颜色,需要对数组倒序,否则颜色对应的数值会从小开始
+// .color('type', config.areaColors.join('-'))
+// // .opacity('value')
+// .tooltip('name*value', (name, value) => ({
+// name,
+// value,
+// }));
+//
+// if (config.geomStyle) {
+// // areaGeom.style('name*value', config.geomStyle);
+// }
+//
+// ctx.areaMapDataView = areaMapDataView;
+// ctx.areaMapView = areaMapView;
+// }
+//
+// // changeConfig(config) {
+// //
+// // }
+//
+// changeData(data: ChartData) {
+// const { areaMapDataView } = this.parent;
+// if (areaMapDataView.origin !== data) {
+// areaMapDataView.source(data);
+// }
+// }
+// }
+
+export const POINT_NAME = 'MapPoint';
+export const MapPoint: VoidFunctionComponent = () => { return null; };
+MapPoint.displayName = POINT_NAME;
+
+export const HEAT_MAP_NAME = 'MapHeatMap';
+export const MapHeatMap: VoidFunctionComponent = () => { return null; };
+MapHeatMap.displayName = HEAT_MAP_NAME;
+
+export const SHOOT_NAME = 'MapShoot';
+export const MapShoot: VoidFunctionComponent = () => { return null; };
+MapShoot.displayName = SHOOT_NAME;
+
+interface CustomMapChildProps extends MapChildProps {
+ render?(data: any, index: number): ReactNode;
+}
+export const CUSTOM_NAME = 'MapCustom';
+export const MapCustom: VoidFunctionComponent = () => { return null; };
+MapCustom.displayName = CUSTOM_NAME;
+
+export type MapChild = typeof MapArea | typeof MapPoint | typeof MapHeatMap | typeof MapShoot | typeof MapCustom;
+
+// function reactMapChild(child: Area) {
+// return class ReactMapChild extends React.Component {
+// static displayName = '';
+//
+//
+//
+// render(): null {
+// return null;
+// }
+// }
+// }
diff --git a/components/Wmap/G2Map.scss b/src/Wmap/index.scss
similarity index 71%
rename from components/Wmap/G2Map.scss
rename to src/Wmap/index.scss
index f32fcaaa..028400f1 100644
--- a/components/Wmap/G2Map.scss
+++ b/src/Wmap/index.scss
@@ -1,11 +1,13 @@
-.cloud-charts.G2Map {
+@import "../themes/index";
+
+.#{$base-name}.G2Map {
position: relative;
// 使缩放后的地图居中
display: flex;
justify-content: center;
align-items: center;
- .cloud-charts-map-south-china-sea {
+ .#{$base-name}-map-south-china-sea {
position: absolute;
right: 0;
bottom: 0;
@@ -15,19 +17,19 @@
min-height: 88px;
}
- .cloud-charts-map-legend {
- position: absolute;
- left: 0;
- bottom: 0;
-
- z-index: 1;
-
- .g2-legend:last-child .g2-legend-list-item:last-child {
- margin-bottom: 0 !important;
- }
- }
+ //.#{$base-name}-map-legend {
+ // position: absolute;
+ // left: 0;
+ // bottom: 0;
+ //
+ // z-index: 1;
+ //
+ // .g2-legend:last-child .g2-legend-list-item:last-child {
+ // margin-bottom: 0 !important;
+ // }
+ //}
- .cloud-charts-map-custom-container {
+ .#{$base-name}-map-custom-container {
position: absolute;
top: 0;
left: 0;
@@ -36,14 +38,14 @@
z-index: 1;
pointer-events: none;
}
- .cloud-charts-map-custom-point {
+ .#{$base-name}-map-custom-point {
position: absolute;
// 将元素中心位置对齐到坐标点
transform: translate(-50%, -50%);
pointer-events: auto;
}
- .cloud-charts-map-shoot {
+ .#{$base-name}-map-shoot {
position: absolute;
top: 0;
left: 0;
diff --git a/src/Wmap/index.tsx b/src/Wmap/index.tsx
new file mode 100644
index 00000000..02a044d9
--- /dev/null
+++ b/src/Wmap/index.tsx
@@ -0,0 +1,1014 @@
+'use strict';
+
+import * as React from 'react';
+// DataSet
+import { DataSet } from '@antv/data-set/lib/data-set';
+import { View as DataView } from '@antv/data-set/lib/view';
+import '@antv/data-set/lib/api/statistics';
+import '@antv/data-set/lib/api/geo';
+import '@antv/data-set/lib/connector/geojson';
+import '@antv/data-set/lib/transform/map';
+import '@antv/data-set/lib/transform/filter';
+import '@antv/data-set/lib/transform/geo/projection';
+import '@antv/data-set/lib/transform/geo/region';
+import { Chart, View, Types, BaseChartConfig, ChartData, Colors } from '../common/types';
+import Base, { ChartProps, rootClassName } from "../common/Base";
+import errorWrap from '../common/errorWrap';
+// @ts-ignore
+import chinaGeo from './mapData/chinaGeo.json';
+import SouthChinaSea from './mapData/southChinaSea';
+import { provinceName, positionMap } from './mapData/chinaGeoInfo';
+import themes from '../themes/index';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import label, { LabelConfig } from "../common/label";
+import geomSize, { GeomSizeConfig } from '../common/geomSize';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import {
+ MapChild,
+ MapArea,
+ MapPoint,
+ MapHeatMap,
+ MapShoot,
+ MapCustom
+} from './child';
+import './index.scss';
+import Wshoot, { ShootProps } from "../Wshoot";
+import { FullCrossName } from '../constants';
+import { warn } from '../common/log';
+import { merge } from '../common/common';
+
+// 这几个地点太小,需要特殊处理边框颜色
+const minArea = ['钓鱼岛', '赤尾屿', '香港', '澳门'];
+// 这几个地点需要特殊处理标签的文字大小
+const minLabel = ['钓鱼岛', '赤尾屿'];
+
+// 特殊处理一些地区的label
+const fixLngLatMap = {
+ 甘肃: [104.4948862, 35.0248462],
+ 河北: [115.5193875, 38.3062153],
+ 天津: [118.2141694, 38.8206246],
+ 澳门: [113.2573035, 21.7906005],
+ 香港: [114.9040905, 21.9265955],
+ 陕西: [108.5133047, 33.8799429],
+ 上海: [122.2818331, 31.0480268],
+};
+
+
+
+interface WmapConfig extends BaseChartConfig {
+ background?: {
+ fill?: string;
+ stroke?: string;
+ };
+ areaColors?: Colors;
+ pointColors?: Colors;
+ heatColors?: Colors;
+ showSouthChinaSea?: boolean;
+ type?: string;
+ projection?: Function;
+
+ legend?: LegendConfig | boolean,
+ tooltip?: TooltipConfig | boolean,
+ /** @deprecated labels 已废弃,请使用 label */
+ labels?: LabelConfig | boolean;
+ label?: LabelConfig | boolean;
+ size?: GeomSizeConfig;
+ geomStyle?: GeomStyleConfig;
+}
+
+export interface MapProps extends ChartProps {
+ geoData?: any;
+ children?: MapChild;
+}
+
+interface MapState {
+ customPointLayer: CustomProps[];
+ shootLayer: ShootProps[];
+ southChinaSeaKey: number;
+}
+
+interface CustomProps {
+ data: MapData;
+ render(data: Types.LooseObject, index: number, otherProps: any): React.ReactNode;
+}
+
+export class Map extends Base {
+ public static Area = MapArea;
+ public static Point = MapPoint;
+ public static HeatMap = MapHeatMap;
+ public static Shoot = MapShoot;
+ public static Custom = MapCustom;
+
+ // 元数据
+ public static chinaGeoData = chinaGeo;
+ public static provinceName = provinceName;
+ public static positionMap = positionMap;
+
+ public static getGeoProjection = DataSet.View.prototype.getGeoProjection;
+
+ state: MapState = {
+ customPointLayer: [],
+ shootLayer: [],
+ southChinaSeaKey: 0,
+ };
+
+ componentDidMount() {
+ super.componentDidMount();
+
+ this.convertChildren(this.props.children, this.props.config, true);
+ }
+
+ componentDidUpdate(prevProps: MapProps) {
+ if (!this.isReRendering && this.props.children !== prevProps.children) {
+ this.convertChildren(this.props.children, this.props.config);
+ }
+
+ super.componentDidUpdate(prevProps);
+ }
+
+ shouldComponentUpdate() {
+ return !(this.isReRendering || !this.chart);
+ }
+
+ rerender() {
+ super.rerender();
+
+ const config = this.props.config || {};
+ // fix: 动态切换主题后南海诸岛地图没有更新
+ if (config.showSouthChinaSea === undefined || config.showSouthChinaSea) {
+ this.setState({
+ southChinaSeaKey: this.state.southChinaSeaKey + 1,
+ });
+ }
+ }
+
+ convertPosition = (d: Types.LooseObject) => {
+ if (!d) {
+ return undefined;
+ }
+ let point = convertPointPosition(this, d);
+ return this.bgMapView.getXY(point);
+ };
+
+ convertChildren(children = this.props.children, config = this.props.config, isInit = false) {
+ const customPointLayer: CustomProps[] = [];
+ const shootLayer: ShootProps[] = [];
+ React.Children.forEach(children, (child) => {
+ if (!child) {
+ return;
+ }
+ // @ts-ignore
+ const { props, type } = child;
+
+ if (type.displayName === MapCustom.displayName) {
+ let newData = props.data;
+ if (Array.isArray(newData)) {
+ newData = newData.map((d) => {
+ const position = this.convertPosition(d ? { ...d } : null);
+ if (!position) {
+ return null;
+ }
+ return { ...d, x: position.x, y: position.y };
+ });
+ }
+ customPointLayer.push({ ...props, data: newData });
+ return;
+ }
+ if (type.displayName === MapShoot.displayName) {
+ // 数据转换在 Shoot 内部完成
+ shootLayer.push(props);
+ return;
+ }
+
+ if (!isInit) {
+ const { data, ...propsConfig } = props;
+ const layerConfig = Object.assign({}, config, propsConfig);
+
+ this.changeChildData(this.chart, layerConfig, type.displayName, data);
+ }
+ });
+ if (!isInit) {
+ this.chart.render(true);
+ }
+ this.setState({
+ customPointLayer,
+ shootLayer,
+ });
+ }
+
+ renderCustomPointLayer(layer: CustomProps, layerIndex: number) {
+ if (!this.chart) {
+ return null;
+ }
+ const { data, render, ...otherProps } = layer;
+
+ return (
+
+ {
+ Array.isArray(data) && data.map((d, i) => {
+ if (!d) {
+ return null;
+ }
+
+ const pointStyle = {
+ left: d.x,
+ top: d.y,
+ };
+ return (
+
+ {render && render(d, i, otherProps)}
+
+ );
+ })
+ }
+
+ );
+ }
+
+ renderShootLayer(shootProps: ShootProps, shootIndex: number) {
+ if (!this.chart) {
+ return null;
+ }
+ const { className, style, ...otherShootProps } = shootProps;
+ const { width: chartWidth, height: chartHeight } = this.chart;
+ // const [width, height] = this.bgMapSize;
+ // const layerStyle = {
+ // left: (chartWidth - width) / 2,
+ // top: (chartHeight - height) / 2,
+ // width,
+ // height,
+ // ...(style || {})
+ // };
+
+ return (
+
+ );
+ }
+
+ renderSouthChinaSea(rootConfig: WmapConfig) {
+ const config = merge({}, this.defaultConfig, rootConfig || {});
+ if (config.showSouthChinaSea === undefined || config.showSouthChinaSea) {
+ const { southChinaSeaKey } = this.state;
+ const { fill } = config.background || {};
+ const mapColor = fill || themes['widgets-map-area-bg'];
+
+ return ;
+ } else {
+ return null;
+ }
+ }
+
+ render() {
+ const { className = '', style, children, data, width, height, padding, geoData, config, language, event, getChartInstance, enableFunctionUpdate, renderer, animate, ...otherProps } = this.props;
+ const { customPointLayer, shootLayer } = this.state;
+ return (
+ this.chartDom = dom} id={this.chartId} className={rootClassName + 'G2Map ' + className} style={style} {...otherProps}>
+ {this.renderSouthChinaSea(config)}
+ {
+ shootLayer.length > 0 && shootLayer.map((shoot, i) => {
+ return this.renderShootLayer(shoot, i);
+ })
+ }
+ {
+ customPointLayer.length > 0 && customPointLayer.map((layer, i) => {
+ return this.renderCustomPointLayer(layer, i);
+ })
+ }
+
+ );
+ }
+
+ chartName = 'G2Map';
+
+ convertData = false;
+
+ getDefaultConfig(): WmapConfig {
+ return {
+ padding: [20, 20, 20, 20],
+ background: {
+ fill: themes['widgets-map-area-bg'],
+ stroke: themes['widgets-map-area-border'],
+ },
+ areaColors: themes.order_10,
+ pointColors: themes.category_12,
+ heatColors: 'rgb(0,0,255)-rgb(0,255,0)-rgb(255,255,0)-rgb(255,0,0)',
+ type: 'china',
+ showSouthChinaSea: true,
+ projection: null,
+ legend: {
+ position: 'left',
+ align: 'bottom',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ },
+ tooltip: {
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ labels: false,
+ label: false,
+ };
+ }
+
+ beforeInit(props: MapProps) {
+ const { geoData } = props;
+ if (geoData) {
+ this.geoData = geoData;
+ }
+
+ return props;
+ }
+
+ geoData: any = null;
+
+ ds: DataSet = null;
+
+ projection: Function = null;
+
+ bgMapDataView: DataView = null;
+ bgMapView: View = null;
+
+ areaMapDataView: DataView = null;
+ areaMapView: View = null;
+
+ pointMapDataView: DataView = null;
+ pointMapView: View = null;
+
+ heatMapDataView: DataView = null;
+ heatMapView: View = null;
+
+ labelMapView: View = null;
+
+ init(chart: Chart, config: WmapConfig) {
+ // 同步度量
+ chart.scale({
+ longitude: {
+ sync: true,
+ },
+ latitude: {
+ sync: true,
+ },
+ x: {
+ nice: false,
+ sync: true,
+ },
+ y: {
+ nice: false,
+ sync: true,
+ },
+ });
+
+ // 设置了 geo.projection 变换后,几何体的坐标系和图表的坐标系(从左下角到右上角)上下相反,所以设置镜像使地图的坐标正确。
+ chart.coordinate().reflect('y');
+
+ chart.axis(false);
+
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showTitle: false,
+ },
+ (ev: any) => {
+ if (typeof config.tooltip === 'boolean') {
+ return;
+ }
+ const { nameFormatter, valueFormatter } = config.tooltip;
+ const { items } = ev.data;
+ items.forEach((item: any, index: number) => {
+ const raw = item.data || {};
+
+ if (valueFormatter) {
+ item.value = valueFormatter(item.value, raw, index, items);
+ }
+ if (nameFormatter) {
+ item.name = nameFormatter(item.name, raw, index, items);
+ }
+ });
+ },
+ {
+ showTitle: false,
+ showCrosshairs: false,
+ // crosshairs: null,
+ showMarkers: false,
+ }
+ );
+
+ // 设置图例
+ rectLegend(this, chart, config, {}, false);
+
+ const ds = new DataSet();
+ this.ds = ds;
+
+ drawMapBackground(this, chart, ds, config);
+
+ React.Children.forEach(this.props.children, (child: MapChild) => {
+ if (!child) {
+ return;
+ }
+ // @ts-ignore
+ const { props, type } = child;
+ const layerConfig = Object.assign({}, config, props.config);
+ // G2 图层需要转化数据格式
+ let { data } = props;
+ if (layerConfig.dataType !== 'g2') {
+ data = convertMapData(data, type.displayName);
+ }
+ if (type.displayName === MapArea.displayName) {
+ drawMapArea(this, chart, ds, layerConfig, data);
+ }
+ if (type.displayName === MapPoint.displayName) {
+ drawMapPoint(this, chart, ds, layerConfig, data);
+ }
+ if (type.displayName === MapHeatMap.displayName) {
+ drawHeatMap(this, chart, ds, layerConfig, data);
+ }
+ });
+
+ if (config.labels || config.label) {
+ drawMapLabel(this, chart, config);
+ }
+
+ // chart.render();
+ }
+
+ // addLayer(child: MapChild) {
+ // if (child && child.addParent) {
+ // child.addParent(this);
+ // }
+ // }
+
+ /** 地图正确的长宽比 */
+ bgMapRatio: number = 1;
+
+ /** 地图正确的尺寸 */
+ bgMapSize: [number, number] = [0, 0];
+
+ changeSize(chart: Chart, config: WmapConfig, chartWidth: number, chartHeight: number) {
+ const chartRatio = chartWidth / chartHeight;
+ const ratio = this.bgMapRatio || chartRatio;
+
+ let width = chartWidth;
+ let height = chartHeight;
+ if (chartRatio > ratio) {
+ width = chartHeight * ratio;
+ } else if (chartRatio < ratio) {
+ height = chartWidth / ratio;
+ }
+ if (width !== chartWidth || height !== chartHeight) {
+ const p1 = (chartWidth - width) / 2;
+ const p2 = (chartHeight - height) / 2;
+ chart.appendPadding = [p2, p1, p2, p1];
+ }
+
+ this.bgMapSize = [width, height];
+
+ chart.changeSize(chartWidth, chartHeight);
+
+ // React 版方法
+ this.convertChildren(this.props.children, this.props.config, true);
+ }
+
+ changeChildData(chart: Chart, config: WmapConfig, viewName: string, newData: ChartData) {
+ const { ds } = this;
+ let data = newData;
+ if (config.dataType !== 'g2') {
+ data = convertMapData(newData, viewName);
+ }
+ if (viewName === MapArea.displayName) {
+ drawMapArea(this, chart, ds, config, data);
+ }
+ if (viewName === MapPoint.displayName) {
+ drawMapPoint(this, chart, ds, config, data);
+ }
+ if (viewName === MapHeatMap.displayName) {
+ drawHeatMap(this, chart, ds, config, data);
+ }
+ }
+
+ /** @override Map 使用自定义 changeData 方法,覆盖原方法逻辑 */
+ changeData() {}
+
+ // 销毁时需要清空 dataView,否则切换主题时,更新会进入到旧的图表实例中
+ destroy() {
+ this.bgMapDataView = null;
+ this.areaMapDataView = null;
+ this.pointMapDataView = null;
+ this.heatMapDataView = null;
+ }
+}
+
+// 绘制地图背景
+function drawMapBackground(ctx: Map, chart: Chart, ds: DataSet, config: WmapConfig) {
+ let geoData = null;
+ if (ctx.geoData) {
+ // 如果用户有传geoData,优先使用
+ geoData = ctx.geoData;
+ } else if (config.type === 'china') {
+ // 自带中国地图数据
+ geoData = chinaGeo;
+ } else {
+ warn('Wmap', 'no geo data, can\'t draw the map!');
+ }
+
+ const bgMapDataView = ds.createView('bgMap').source(geoData, {
+ type: 'GeoJSON',
+ });
+
+ let { projection } = config;
+
+ if (!projection) {
+ projection = bgMapDataView.getGeoProjection('geoConicEqualArea');
+ projection
+ // @ts-ignore
+ .center([0, 36.4])
+ .parallels([25, 47])
+ .scale(1000)
+ .rotate([-105, 0])
+ .translate([0, 0]);
+ }
+
+ bgMapDataView.transform({
+ type: 'geo.projection',
+ // 因为G2的投影函数不支持设置投影参数,这里使用自定义的投影函数设置参数
+ // @ts-ignore
+ projection() {
+ return projection;
+ },
+ as: ['x', 'y', 'cX', 'cY'],
+ });
+
+ if (config.type === 'china') {
+ // 过滤掉南海诸岛
+ bgMapDataView.transform({
+ type: 'filter',
+ callback(row) {
+ return row.properties.name !== '南海诸岛';
+ },
+ });
+ }
+
+ // start: 按照投影后尺寸比例调整图表的真实比例
+ const longitudeRange = bgMapDataView.range('x');
+ const latitudeRange = bgMapDataView.range('y');
+ const ratio =
+ (longitudeRange[1] - longitudeRange[0]) /
+ (latitudeRange[1] - latitudeRange[0]);
+ ctx.bgMapRatio = ratio;
+ const { width: chartWidth, height: chartHeight } = chart;
+ const chartRatio = chartWidth / chartHeight;
+
+ let width = chartWidth;
+ let height = chartHeight;
+ if (chartRatio > ratio) {
+ width = chartHeight * ratio;
+ } else if (chartRatio < ratio) {
+ height = chartWidth / ratio;
+ }
+ if (width !== chartWidth || height !== chartHeight) {
+ const p1 = (chartWidth - width) / 2;
+ const p2 = (chartHeight - height) / 2;
+ // 不设置尺寸,通过padding控制地图形状
+ chart.appendPadding = [p2, p1, p2, p1];
+ }
+ ctx.bgMapSize = [width, height];
+ // end: 按照投影后尺寸比例调整图表的真实比例
+
+ const { fill: bgFill, stroke: bgStroke, ...otherBgStyle } =
+ config.background || {};
+
+ const bgMapView = chart.createView({
+ padding: 0,
+ });
+ bgMapView.data(bgMapDataView.rows);
+ bgMapView.tooltip(false);
+ bgMapView
+ .polygon()
+ .position('x*y')
+ .style('name', function(name) {
+ const result = {
+ fill: bgFill || themes['widgets-map-area-bg'],
+ stroke: bgStroke || themes['widgets-map-area-border'],
+ lineWidth: 1,
+ ...otherBgStyle,
+ };
+ // 对一些尺寸非常小的形状特殊处理,以显示出来。
+ if (minArea.indexOf(name) > -1) {
+ result.stroke = bgFill || themes['widgets-map-area-bg'];
+ }
+ return result;
+ });
+
+ ctx.bgMapDataView = bgMapDataView;
+ ctx.bgMapView = bgMapView;
+
+ ctx.projection = projection;
+}
+
+// 绘制分级统计地图
+function drawMapArea(ctx: Map, chart: Chart, ds: DataSet, config: WmapConfig, data: MapData) {
+ let { areaMapDataView, areaMapView } = ctx;
+ if (areaMapDataView) {
+ if (areaMapDataView.origin !== data) {
+ areaMapDataView.source(data);
+ areaMapView.data(areaMapDataView.rows);
+ }
+ } else {
+ areaMapDataView = ds
+ .createView()
+ .source(data)
+ .transform({
+ type: 'map',
+ callback(obj) {
+ const { name, type, ...others } = obj;
+ return {
+ // @ts-ignore 将省份全称转化为简称
+ name: provinceName[name] ? provinceName[name] : name,
+ type: String(type),
+ ...others,
+ };
+ },
+ })
+ .transform({
+ geoDataView: ctx.bgMapDataView,
+ field: 'name',
+ type: 'geo.region',
+ as: ['x', 'y'],
+ });
+
+ const areaMapView = chart.createView({
+ padding: 0,
+ });
+ areaMapView.data(areaMapDataView.rows);
+ const areaGeom = areaMapView
+ .polygon()
+ .position('x*y')
+ // 如果用连续型颜色,需要对数组倒序,否则颜色对应的数值会从小开始
+ .color('areaType', getMapContinuousColor(config.areaColors))
+ // .opacity('value')
+ .tooltip('name*value', (name, value) => ({
+ name,
+ value,
+ }));
+
+ geomStyle(areaGeom, config.geomStyle);
+
+ ctx.areaMapDataView = areaMapDataView;
+ ctx.areaMapView = areaMapView;
+ }
+}
+
+// 绘制散点图
+function drawMapPoint(ctx: Map, chart: Chart, ds: DataSet, config: WmapConfig, data: MapData) {
+ let { pointMapDataView, pointMapView } = ctx;
+ if (pointMapDataView) {
+ if (pointMapDataView.origin !== data) {
+ pointMapDataView.source(data);
+ pointMapView.data(pointMapDataView.rows);
+ }
+ } else {
+ pointMapDataView = ds
+ .createView()
+ .source(data)
+ .transform({
+ type: 'map',
+ callback: point => {
+ const newPoint = Object.assign({}, point);
+ newPoint.type = String(newPoint.type);
+ return convertPointPosition(ctx, newPoint);
+ },
+ });
+
+ const pointMapView = chart.createView({
+ padding: 0,
+ });
+ pointMapView.data(pointMapDataView.rows);
+ const pointGeom = pointMapView
+ .point()
+ .position('x*y')
+ .shape('circle')
+ .color('pointType', config.pointColors)
+ .tooltip('name*value', (name, value) => ({
+ name,
+ value,
+ }))
+ // .active(false);
+
+ geomSize(pointGeom, config.size, 4, 'value', 'name*value');
+
+ geomStyle(pointGeom, config.geomStyle);
+
+ if (config.labels) {
+ warn('config.labels', '属性已废弃,请使用 config.label');
+ }
+
+ label(pointGeom, config, 'name', {
+ // FIXME 默认的动画会导致部分label不显示,暂时关闭动画
+ animate: false,
+ });
+ if (config.labels || config.label) {
+ // let labelConfig = {};
+ // if (typeof config.labels === 'object') {
+ // labelConfig = config.labels;
+ // } else if (typeof config.label === 'object') {
+ // labelConfig = config.label;
+ // }
+ //
+ // const { offset = 0, textStyle = {}, formatter } = labelConfig;
+ // pointGeom.label('name', {
+ // FIXME 默认的动画会导致部分label不显示,暂时关闭动画
+ // animate: false,
+ // offset: `${offset - Number(themes['widgets-font-size-1'].replace('px', ''))}`,
+ // textStyle: {
+ // fill: themes['widgets-map-label'],
+ // // 需要去掉 px 的字符串
+ // fontSize: themes['widgets-font-size-1'].replace('px', ''),
+ // textBaseline: 'middle',
+ // ...textStyle,
+ // },
+ // formatter: formatter || null,
+ // });
+ }
+
+ ctx.pointMapDataView = pointMapDataView;
+ ctx.pointMapView = pointMapView;
+ }
+}
+
+// 绘制热力图
+function drawHeatMap(ctx: Map, chart: Chart, ds: DataSet, config: WmapConfig, data: MapData) {
+ let { heatMapDataView, heatMapView } = ctx;
+ if (heatMapDataView) {
+ if (heatMapDataView.origin !== data) {
+ heatMapDataView.source(data);
+ heatMapView.data(heatMapDataView.rows);
+ }
+ } else {
+ heatMapDataView = ds
+ .createView()
+ .source(data)
+ .transform({
+ type: 'map',
+ callback: point => {
+ const newPoint = Object.assign({}, point);
+ newPoint.type = String(newPoint.type);
+ return convertPointPosition(ctx, newPoint);
+ },
+ });
+
+ const heatMapView = chart.createView({
+ padding: 0,
+ });
+ heatMapView.data(heatMapDataView.rows);
+ chart.legend('value', false);
+
+ const heatGeom = heatMapView
+ .heatmap()
+ .position('x*y')
+ .color('value', config.heatColors)
+ .tooltip('name*value', (name, value) => ({
+ name,
+ value,
+ }))
+
+ geomSize(heatGeom, config.size, 16, 'value', 'name*value');
+
+ ctx.heatMapDataView = heatMapDataView;
+ ctx.heatMapView = heatMapView;
+ }
+}
+
+// 绘制背景地图标签
+function drawMapLabel(ctx: Map, chart: Chart, config: WmapConfig) {
+ const labelConfig = config.labels || config.label;
+
+ // 将背景数据集中的中心点坐标(cX, cY)映射为新数据中的x, y。保证scale可以同步这个view的度量。
+ const labelData = ctx.bgMapDataView.rows.map(row => {
+ const label = {
+ name: row.name,
+ x: row.cX,
+ y: row.cY,
+ };
+
+ // @ts-ignore fix 某些地区label位置不好,需要重新定位
+ const fixLngLat = fixLngLatMap[row.name];
+ if (fixLngLat) {
+ // @ts-ignore 第二个参数支持函数
+ const position = ctx.bgMapDataView.geoProjectPosition(fixLngLat, ctx.projection, true);
+ label.x = position[0];
+ label.y = position[1];
+ }
+
+ return label;
+ });
+
+ // @ts-ignore label 需要函数处理,无法放到 label 工具函数中
+ const { offset = 0, textStyle = {}, labelFormatter } =
+ typeof labelConfig === 'object' ? labelConfig : {};
+
+ const labelMapView = chart.createView({
+ padding: 0,
+ });
+ labelMapView.data(labelData);
+ labelMapView
+ .point()
+ .position('x*y')
+ .size(0)
+ .label('name', function (name) {
+ let fontSize = themes['widgets-font-size-1'].replace('px', '');
+ // 对一些尺寸非常小的形状特殊处理,以显示出来。
+ if (minLabel.indexOf(name) > -1) {
+ fontSize = String(Number(fontSize) * 2 / 3);
+ }
+ const labelStyle = {
+ fill: themes['widgets-map-label'],
+ // 需要去掉 px 的字符串
+ fontSize: fontSize,
+ textBaseline: 'middle',
+ ...textStyle,
+ }
+ const result: Types.GeometryLabelCfg = {
+ offset,
+ style: labelStyle,
+ // FIXME 默认的动画会导致部分label不显示,暂时关闭动画
+ animate: false,
+ };
+ if (labelFormatter) {
+ result.content = (v, item, index) => {
+ return labelFormatter(v['name'], item, index);
+ }
+ }
+ return result;
+ })
+ .tooltip(false)
+ // .active(false);
+
+ ctx.labelMapView = labelMapView;
+}
+
+
+type MapData = Types.LooseObject[];
+interface RawMapData {
+ name: string;
+ data: MapData;
+}
+
+// 转换地图数据结构,因为和默认结构不同,需要特殊处理。
+function convertMapData(data: RawMapData[], viewName: string) {
+ if (!Array.isArray(data)) {
+ return [];
+ }
+ let typeName = 'type';
+ if (viewName === MapArea.displayName) {
+ typeName = 'areaType';
+ }
+ if (viewName === MapPoint.displayName) {
+ typeName = 'pointType';
+ }
+ // if (viewName === MapHeatMap.displayName) {
+ // typeName = 'heatmapType';
+ // }
+ const result: MapData = [];
+ data.forEach(item => {
+ const { name = '', data: itemData } = item;
+ if (!Array.isArray(itemData)) {
+ return;
+ }
+ itemData.forEach(d => {
+ result.push({
+ ...d,
+ [typeName]: d.type || name,
+ });
+ });
+ });
+
+ return result;
+}
+
+// 计算数据的坐标点
+export function convertPointPosition(ctx: Map, point: Types.LooseObject) {
+ if (point.x && point.y) {
+ return point;
+ }
+ if (!ctx.bgMapDataView) {
+ return point;
+ }
+
+ const { projection } = ctx;
+ if (point.lng && point.lat) {
+ return getProjectionPosition(
+ point,
+ ctx.bgMapDataView,
+ projection,
+ Number(point.lng),
+ Number(point.lat)
+ );
+ }
+ if (point.name) {
+ let { name } = point;
+ if (!/^\w/.test(name)) {
+ if (/^\u963F\u62C9/.test(name) || /^\u5F20\u5BB6/.test(name)) {
+ // 阿拉、张家 两个开头的需要截取三个字符
+ name = name.slice(0, 3);
+ } else if (!/\u7701$/.test(name) && !/\u81ea\u6cbb\u533a$/.test(name)) {
+ // 以"省" / "自治区"结尾的不截断
+ name = name.slice(0, 2);
+ }
+ }
+ // @ts-ignore
+ const position = positionMap[name];
+ if (position) {
+ return getProjectionPosition(
+ point,
+ ctx.bgMapDataView,
+ projection,
+ position.lng,
+ position.lat
+ );
+ }
+ }
+ if (!point.x || !point.y) {
+ warn('Wmap', '无法定位地点', point);
+ }
+ return point;
+}
+
+function getProjectionPosition(point: Types.LooseObject, view: DataView, projection: Function, lng: number, lat: number) {
+ // @ts-ignore
+ const projectedCoord = view.geoProjectPosition([lng, lat], projection, true);
+ point.x = projectedCoord[0];
+ point.y = projectedCoord[1];
+ return point;
+}
+
+// // 地图的tooltip逻辑
+// function mapTooltip(chart, config) {
+// // tooltip
+// if (config.tooltip !== false) {
+// const { nameFormatter, valueFormatter, customConfig } =
+// config.tooltip || {};
+//
+// const tooltipCfg = {
+// showTitle: false,
+// crosshairs: null,
+// itemTpl:
+// '' +
+// '' +
+// '{name}:{value}',
+// };
+//
+// if (customConfig) {
+// merge(tooltipCfg, customConfig);
+// }
+//
+// chart.tooltip(tooltipCfg);
+//
+// if (nameFormatter || valueFormatter) {
+// chart.on('tooltip:change', ev => {
+// ev.items.forEach((item, index) => {
+// const raw = item.point._origin || {};
+//
+// if (valueFormatter) {
+// item.value = valueFormatter(item.value, raw, index, ev.items);
+// }
+// if (nameFormatter) {
+// item.name = nameFormatter(item.name, raw, index, ev.items);
+// }
+// });
+// });
+// }
+// } else {
+// chart.tooltip(false);
+// }
+// }
+
+function getMapContinuousColor(color: Colors) {
+ if (Array.isArray(color)) {
+ return color.join('-');
+ } else {
+ return color;
+ }
+}
+
+const Wmap: typeof Map = errorWrap(Map);
+
+Wmap.Area = Map.Area;
+Wmap.Point = Map.Point;
+Wmap.HeatMap = Map.HeatMap;
+Wmap.Shoot = Map.Shoot;
+Wmap.Custom = Map.Custom;
+Wmap.chinaGeoData = Map.chinaGeoData;
+Wmap.provinceName = Map.provinceName;
+Wmap.positionMap = Map.positionMap;
+Wmap.getGeoProjection = Map.getGeoProjection;
+
+export default Wmap;
diff --git a/components/Wmap/mapData/chinaGeo.json b/src/Wmap/mapData/chinaGeo.json
similarity index 100%
rename from components/Wmap/mapData/chinaGeo.json
rename to src/Wmap/mapData/chinaGeo.json
diff --git a/components/Wmap/mapData/chinaGeoInfo.js b/src/Wmap/mapData/chinaGeoInfo.ts
similarity index 100%
rename from components/Wmap/mapData/chinaGeoInfo.js
rename to src/Wmap/mapData/chinaGeoInfo.ts
diff --git a/components/Wmap/mapData/southChinaSea.jsx b/src/Wmap/mapData/southChinaSea.jsx
similarity index 100%
rename from components/Wmap/mapData/southChinaSea.jsx
rename to src/Wmap/mapData/southChinaSea.jsx
diff --git a/components/Wminicontainer/index.scss b/src/Wminicontainer/index.scss
similarity index 100%
rename from components/Wminicontainer/index.scss
rename to src/Wminicontainer/index.scss
diff --git a/components/Wminicontainer/index.jsx b/src/Wminicontainer/index.tsx
similarity index 56%
rename from components/Wminicontainer/index.jsx
rename to src/Wminicontainer/index.tsx
index 199c526f..ca3db638 100644
--- a/components/Wminicontainer/index.jsx
+++ b/src/Wminicontainer/index.tsx
@@ -1,23 +1,32 @@
'use strict';
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
import classNames from 'classnames';
import { getStatusColorName } from '../common/common';
import chartLog from "../common/log";
-import { isMobileWithProps } from "../common/platform";
+import { isMobileWithProps, MobileProps } from "../common/platform";
+import { Status } from '../common/types';
+import { FullCrossName, PrefixName } from '../constants';
import './index.scss';
-const prefix = 'cloud-wminicontainer';
+const prefix = `${PrefixName}-wminicontainer`;
-export default class Wminicontainer extends React.Component {
+interface WminicontainerProps extends MobileProps {
+ className?: string;
+ style?: React.CSSProperties;
+ width?: string | number;
+ height?: string | number;
+ status?: Status | string;
+}
+
+export default class Wminicontainer extends React.Component {
static displayName = 'Wminicontainer';
static defaultProps = {
status: ''
};
- constructor(props) {
+ constructor(props: WminicontainerProps) {
super(props);
// 图表初始化时记录日志
@@ -27,9 +36,9 @@ export default class Wminicontainer extends React.Component {
render() {
const { height = 80, className, status, style, isMobile, ...otherProps } = this.props;
const mainClasses = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
[`${prefix}`]: true,
- [`${prefix}-mobile`]: isMobileWithProps(otherProps, isMobile),
+ [`${prefix}-mobile`]: isMobileWithProps(this.props),
[`${prefix}-${getStatusColorName(status)}`]: !!status,
[className]: !!className
});
@@ -47,8 +56,3 @@ export default class Wminicontainer extends React.Component {
);
}
}
-
-Wminicontainer.propTypes = {
- height: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
-};
-
diff --git a/components/Wplaceholder/scss/mixin.scss b/src/Wminicontainer/scss/function.scss
similarity index 100%
rename from components/Wplaceholder/scss/mixin.scss
rename to src/Wminicontainer/scss/function.scss
diff --git a/components/Wminicontainer/scss/mixin.scss b/src/Wminicontainer/scss/mixin.scss
similarity index 100%
rename from components/Wminicontainer/scss/mixin.scss
rename to src/Wminicontainer/scss/mixin.scss
diff --git a/components/Wminicontainer/scss/variable.scss b/src/Wminicontainer/scss/variable.scss
similarity index 88%
rename from components/Wminicontainer/scss/variable.scss
rename to src/Wminicontainer/scss/variable.scss
index 75827819..c43088a3 100644
--- a/components/Wminicontainer/scss/variable.scss
+++ b/src/Wminicontainer/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wminicontainer-prefix: '.cloud-wminicontainer';
+$wminicontainer-prefix: '.#{$base-prefix}-wminicontainer';
$wminicontainer-bg-color: getVar(widgets-container-background, $widgets-container-background);
diff --git a/components/Wrectangle/index.en-US.md b/src/Wminiline/index.scss
similarity index 100%
rename from components/Wrectangle/index.en-US.md
rename to src/Wminiline/index.scss
diff --git a/src/Wminiline/index.tsx b/src/Wminiline/index.tsx
new file mode 100644
index 00000000..54357120
--- /dev/null
+++ b/src/Wminiline/index.tsx
@@ -0,0 +1,34 @@
+'use strict';
+
+import { Line, WlineConfig } from '../Wline';
+import errorWrap from '../common/errorWrap';
+
+export class Miniline extends Line {
+ chartName = 'G2MiniLine';
+
+ getDefaultConfig(): WlineConfig {
+ return {
+ padding: [0, 0, 0, 0],
+ xAxis: {
+ visible: false,
+ type: 'time', // 默认为线性
+ mask: 'auto', // 上述type为time时,此字段生效
+ },
+ yAxis: {
+ visible: false,
+ max: null,
+ min: null,
+ },
+ legend: false,
+ tooltip: false,
+ area: false,
+ spline: false,
+ symbol: false,
+ label: false,
+ };
+ }
+}
+
+const Wminiline: typeof Miniline = errorWrap(Miniline)
+
+export default Wminiline;
diff --git a/src/Wmultipie/index.scss b/src/Wmultipie/index.scss
new file mode 100644
index 00000000..2d997995
--- /dev/null
+++ b/src/Wmultipie/index.scss
@@ -0,0 +1,45 @@
+@import "../themes/index";
+
+.#{$base-name}.G2MultiPie {
+ position: relative;
+ text-align: center;
+ box-sizing: border-box;
+
+ .#{$base-name}-children {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ text-align: center;
+ max-width: 100%;
+ max-height: 100%;
+ transform: translate(-50%, -50%);
+ //overflow: auto;
+ }
+
+ //& > div {
+ // height: 100%;
+ // display: inline-flex;
+ // justify-content: center;
+ // align-items: center;
+ // text-align: left;
+ //
+ // & > canvas {
+ // position: static;
+ // flex: none;
+ // }
+ //
+ // // hack掉图例的高度限制,比用legend.maxLength逻辑要简单
+ // .g2-legend {
+ // max-width: none !important;
+ // max-height: 100% !important;
+ // }
+ //
+ // .g2-tooltip-list > li:first-child {
+ // margin-top: 0 !important;
+ // }
+ //
+ // .g2-legend-list-item:last-child {
+ // margin-bottom: 1px !important;
+ // }
+ //}
+}
diff --git a/src/Wmultipie/index.tsx b/src/Wmultipie/index.tsx
new file mode 100644
index 00000000..533de14a
--- /dev/null
+++ b/src/Wmultipie/index.tsx
@@ -0,0 +1,267 @@
+'use strict';
+
+import { View as DataView } from '@antv/data-set/lib/view';
+import '@antv/data-set/lib/api/hierarchy';
+import '@antv/data-set/lib/connector/hierarchy';
+import '@antv/data-set/lib/transform/hierarchy/partition'
+import { Chart, Types, BaseChartConfig, ChartData, Colors } from '../common/types';
+import Base from "../common/Base";
+import themes from '../themes/index';
+import { numberDecimal } from '../common/common';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import polarLegendLayout from '../common/polarLegendLayout';
+import updateChildrenPosition from '../common/updateChildrenPosition';
+import errorWrap from '../common/errorWrap';
+import './index.scss';
+
+interface WmultipieConfig extends BaseChartConfig {
+ colors?: Colors;
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ autoSort?: boolean;
+ cycle?: boolean;
+ innerRadius?: number;
+ outerRadius?: number;
+ geomStyle?: GeomStyleConfig;
+}
+
+function getParentList(node: Types.LooseObject, target: Types.LooseObject[] = []): Types.LooseObject[] {
+ const parentNode = node.parent;
+ // 需要存储根节点,所以一直到 parentNode===null(此时在根节点上)
+ if (!parentNode) {
+ return target;
+ }
+
+ target.unshift({
+ name: parentNode.data.name,
+ value: parentNode.value,
+ rawValue: parentNode.data.value,
+ depth: parentNode.depth,
+ });
+
+ return getParentList(parentNode, target);
+}
+
+function computeData(ctx: MultiPie, data: ChartData) {
+ let dv = null;
+ if (ctx.dataView) {
+ dv = ctx.dataView;
+ dv.source(data, {
+ type: 'hierarchy',
+ });
+ } else {
+ dv = new DataView();
+ ctx.dataView = dv;
+
+ dv.source(data, {
+ type: 'hierarchy',
+ }).transform({
+ type: 'hierarchy.partition', // 根据树形数据生成相邻层次图 Adjacency Diagram 布局
+ as: ['x', 'y'],
+ });
+ }
+
+ const source: Types.Data = [];
+
+ dv.getAllNodes().forEach((node) => {
+ if (node.depth === 0) {
+ // 父节点不展示
+ return;
+ }
+ // var obj = {};
+ // obj.name = node.data.name;
+ // obj.rawValue = node.data.value;
+ // obj.value = node.value;
+ // obj.x = node.x;
+ // obj.y = node.y;
+ source.push({
+ name: node.data.name,
+ value: node.value,
+ rawValue: node.data.value,
+ depth: node.depth,
+ parent: getParentList(node),
+ x: node.x,
+ y: node.y,
+ });
+ return node;
+ });
+
+ // 挂载转换后的数据
+ ctx.data = source;
+
+ return source;
+}
+
+export class MultiPie extends Base {
+ chartName = 'G2MultiPie';
+
+ convertData = false;
+
+ getDefaultConfig(): WmultipieConfig {
+ return {
+ colors: themes.category_12,
+ // padding: [20, 20, 20, 20],
+ legend: {
+ position: 'right',
+ align: '',
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ valueFormatter: null,
+ },
+ tooltip: {
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ cycle: false,
+ innerRadius: 0.6, // 内环半径大小,仅cycle为true时可用
+ outerRadius: 0.8, // 饼图半径大小,初始化时可用
+ // drawPadding: [10, 10, 10, 10],
+ };
+ }
+
+ dataView: DataView = null;
+
+ data: Types.Data = [];
+
+ init(chart: Chart, config: WmultipieConfig, data: ChartData) {
+ const source = computeData(this, data);
+
+ chart.data(source);
+
+ const thetaConfig: Types.CoordinateCfg = {
+ radius: Math.max(Math.min(config.outerRadius, 1), 0.01),
+ };
+ if (config.cycle) {
+ thetaConfig.innerRadius = Math.max(Math.min(config.innerRadius, 1), 0);
+ }
+
+ chart.coordinate('polar', thetaConfig);
+
+ chart.axis(false);
+
+ rectLegend(this, chart, config, {}, true, null, true);
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ shared: false,
+ },
+ (ev: any) => {
+ const { items } = ev.data;
+ items.forEach((item: any, index: number) => {
+ if (typeof config.tooltip === 'boolean') {
+ return;
+ }
+
+ const pointData = item.data;
+ const rootNode = pointData.parent[0];
+ const percent = numberDecimal(item.value / rootNode.value, 4);
+
+ if (config.tooltip.valueFormatter) {
+ item.value = config.tooltip.valueFormatter(item.value, {
+ percent,
+ ...pointData,
+ }, index, items);
+ }
+ if (config.tooltip.nameFormatter) {
+ item.name = config.tooltip.nameFormatter(item.name, {
+ percent,
+ ...pointData,
+ }, index, items);
+ }
+ });
+ },
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ shared: false,
+ }
+ );
+
+ const geom = chart.polygon()
+ .position('x*y')
+ .color('name', config.colors)
+ .tooltip('name*value*rawValue*depth', (name, value) => {
+ return {
+ name,
+ value,
+ };
+ });
+
+ geomStyle(geom, config.geomStyle, undefined, 'name*value*rawValue*depth');
+
+ polarLegendLayout(chart);
+
+ chart.on('afterrender', () => {
+ updateChildrenPosition(chart, this.chartDom);
+ });
+ }
+
+ changeData(chart: Chart, config: WmultipieConfig, data: ChartData) {
+ const source = computeData(this, data);
+
+ chart.changeData(source);
+ }
+}
+
+const WmultiPie: typeof MultiPie = errorWrap(MultiPie);
+
+export default WmultiPie;
+
+// export default /*#__PURE__*/ errorWrap(g2Factory('G2MultiPie', Object.assign({}, G2PieBase, {
+// convertData: false,
+// getDefaultConfig() {
+// return {
+// colors: themes.category_12,
+// padding: [20, 20, 20, 20],
+// legend: {
+// // position: 'right',
+// nameFormatter: null, // 可以强制覆盖,手动设置label
+// valueFormatter: null,
+// },
+// tooltip: {
+// nameFormatter: null,
+// valueFormatter: null,
+// },
+// innerRadius: null, // 内环半径大小,仅cycle为true时可用
+// outerRadius: 0.8, // 饼图半径大小,初始化时可用
+// drawPadding: [10, 10, 10, 10],
+// };
+// },
+// init(chart, userConfig, data) {
+// const config = merge({}, this.defaultConfig, userConfig);
+//
+// const { source, maxDepth } = computeData.call(this, data);
+//
+// chart.source(source);
+//
+// // if (config.cycle) {
+// // thetaConfig.innerRadius = Math.max(Math.min(config.innerRadius, 1), 0);
+// // }
+//
+// chart.coord('polar', {
+// innerRadius: getInnerRadius(maxDepth, config.innerRadius), // 用于空心部分的半径设置
+// });
+//
+// chart.axis(false);
+//
+// const drawPadding = getDrawPadding(config.drawPadding, config.label, this.defaultConfig.drawPadding);
+//
+//
+//
+// chart.render();
+// },
+// changeData(chart, config, data) {
+// const { source } = computeData.call(this, data);
+//
+// chart.changeData(source);
+// },
+// })));
diff --git a/components/Wnightingale/gui.schema.json b/src/Wnightingale/gui.schema.json
similarity index 100%
rename from components/Wnightingale/gui.schema.json
rename to src/Wnightingale/gui.schema.json
diff --git a/src/Wnightingale/index.scss b/src/Wnightingale/index.scss
new file mode 100644
index 00000000..6c411ca9
--- /dev/null
+++ b/src/Wnightingale/index.scss
@@ -0,0 +1,24 @@
+@import "../themes/index";
+
+.#{$base-name}.G2Nightingale {
+ position: relative;
+ box-sizing: border-box;
+
+ .#{$base-name}-children {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ }
+
+ //& > div {
+ // .g2-tooltip-list > li:first-child {
+ // margin-top: 0 !important;
+ // }
+ //
+ // .g2-legend-list-item:last-child {
+ // margin-bottom: 1px !important;
+ // }
+ //}
+}
diff --git a/src/Wnightingale/index.tsx b/src/Wnightingale/index.tsx
new file mode 100644
index 00000000..51b5ea8d
--- /dev/null
+++ b/src/Wnightingale/index.tsx
@@ -0,0 +1,220 @@
+'use strict';
+
+import { Chart, Types, BaseChartConfig, Colors } from '../common/types';
+import Base from '../common/Base';
+import errorWrap from '../common/errorWrap';
+import rectXAxis, { XAxisConfig } from '../common/rectXAxis';
+import rectYAxis, { YAxisConfig } from '../common/rectYAxis';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import { GuideConfig } from '../common/guide';
+import label, { LabelConfig } from '../common/label';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import polarLegendLayout from '../common/polarLegendLayout';
+import updateChildrenPosition from '../common/updateChildrenPosition';
+import themes from '../themes/index';
+import './index.scss';
+import { warn } from '../common/log';
+
+// 3.x代码
+export interface WnightingaleConfig extends BaseChartConfig {
+ /** X轴配置项 */
+ xAxis?: Types.ScaleOption & XAxisConfig | false,
+ /** Y轴配置项 */
+ yAxis?: Types.ScaleOption & YAxisConfig | false,
+ /** @deprecated axis 属性已废弃,请使用 xAxis 属性 */
+ axis?: boolean;
+ colors?: Colors;
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ guide?: GuideConfig;
+ label?: LabelConfig | boolean;
+ cycle?: boolean;
+ innerRadius?: number;
+ outerRadius?: number;
+ geomStyle?: GeomStyleConfig;
+}
+
+export class Nightingale extends Base {
+ chartName = 'G2Nightingale';
+
+ getDefaultConfig(): WnightingaleConfig {
+ return {
+ // padding: [20, 20, 20, 20],
+ colors: themes.category_12,
+ xAxis: false,
+ yAxis: false,
+ cycle: false,
+ innerRadius: 0.5, // 内环半径大小,仅cycle为true时可用
+ outerRadius: 1,
+ label: {
+ offset: -15
+ },
+ legend: {
+ position: 'bottom',
+ align: 'center',
+ nameFormatter: null,
+ },
+ tooltip: {
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ };
+ }
+ init(chart: Chart, config: WnightingaleConfig, data: any) {
+ const defs: Record = {
+ type: {
+ type: 'cat',
+ },
+ };
+
+ chart.scale(defs);
+
+ chart.data(data);
+ chart.coordinate('polar', {
+ innerRadius: config.cycle ? Math.max(Math.min(config.innerRadius, 1), 0) : 0,
+ radius: Math.max(Math.min(config.outerRadius, 1), 0.01),
+ });
+
+ // 设置图例
+ rectLegend(this, chart, config, null, true);
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ null,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ },
+ );
+
+ if (config.axis) {
+ warn('config.axis', '属性已废弃,请使用 config.xAxis 属性');
+ }
+
+ rectXAxis(this, chart, config);
+
+ rectYAxis(this, chart, config);
+
+ const geom = chart
+ .interval()
+ .position('x*y')
+ .color('x', config.colors);
+
+ geomStyle(geom, config.geomStyle, {
+ lineWidth: 1,
+ stroke: themes['widgets-color-background'],
+ });
+
+ label(geom, config, 'x', {});
+
+ polarLegendLayout(chart);
+
+ chart.on('afterrender', () => {
+ updateChildrenPosition(chart, this.chartDom);
+ });
+ }
+}
+const Wnightingale: typeof Nightingale = errorWrap(Nightingale);
+
+export default Wnightingale;
+
+// 对外暴露一个对象,除了init方法必选外,其余均为可选项,按组件需要选择性使用。
+// 方法运行时的this指向图表实例,所以可以在this上挂载需要保留的数据。
+// export default /*#__PURE__*/ errorWrap(g2Factory('G2Nightingale', {
+// getDefaultConfig() {
+// return {
+// padding: [20, 20, 20, 20],
+// colors: themes.category_12,
+// cycle: false,
+// innerRadius: 0.5, // 内环半径大小,仅cycle为true时可用
+// label: {
+// key: 'x',
+// },
+// legend: {
+// position: 'bottom',
+// align: 'center',
+// nameFormatter: null,
+// },
+// tooltip: {
+// nameFormatter: null,
+// valueFormatter: null,
+// },
+// };
+// },
+// // 初始化前对props的预处理函数
+// beforeInit(props) {
+// const { config } = props;
+// // TODO 处理padding
+// return Object.assign({}, props, {
+// padding: props.padding || config.padding || this.defaultConfig.padding,
+// });
+// },
+// // 图表绘制主函数,必选
+// init(chart, userConfig, data) {
+// const config = merge({}, this.defaultConfig, userConfig);
+// chart.source(data);
+// chart.coord('polar', {
+// innerRadius: config.cycle ? Math.max(Math.min(config.innerRadius, 1), 0) : 0,
+// });
+
+// // 设置图例
+// rectLegend(this, chart, config, null, true);
+
+// // tooltip
+// rectTooltip(this, chart, config, {
+// showTitle: false,
+// crosshairs: null,
+// });
+
+// if (config.axis) {
+// chart.axis('x', {
+// grid: {
+// align: 'center',
+// hideFirstLine: false,
+// hideLastLine: false,
+// },
+// label: {
+// offset: 10,
+// autoRotate: true,
+// textStyle: {
+// textAlign: 'center',
+// },
+// },
+// });
+
+// chart.axis('y', {
+// tickLine: null,
+// label: null,
+// line: null,
+// });
+// } else {
+// chart.axis(false);
+// }
+
+// const geomStyle = config.geomStyle || {};
+// const geom = chart
+// .interval()
+// .position('x*y')
+// .color('x', config.colors)
+// .style('x*y*extra', {
+// lineWidth: 1,
+// stroke: themes['widgets-color-background'],
+// ...geomStyle
+// });
+
+// label(geom, config, config.label.key || 'x', {
+// offset: -15,
+// });
+
+// chart.render();
+// },
+// }));
diff --git a/components/Wnumber/index.scss b/src/Wnumber/index.scss
similarity index 100%
rename from components/Wnumber/index.scss
rename to src/Wnumber/index.scss
diff --git a/components/Wnumber/index.jsx b/src/Wnumber/index.tsx
similarity index 70%
rename from components/Wnumber/index.jsx
rename to src/Wnumber/index.tsx
index efb07519..35df940b 100644
--- a/components/Wnumber/index.jsx
+++ b/src/Wnumber/index.tsx
@@ -1,24 +1,41 @@
'use strict';
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
import classNames from 'classnames';
import { getStatusColorName } from '../common/common';
import Warrow from '../common/arrow';
import chartLog from "../common/log";
+import { Status, Trend } from '../common/types';
+import { FullCrossName, PrefixName } from '../constants';
import './index.scss';
-const prefix = 'cloud-wnumber';
+const prefix = `${PrefixName}-wnumber`;
-function getTrendIcon(trend) {
+function getTrendIcon(trend: Trend) {
if(trend === 'raise'){
return
- }else if( trend === 'drop'){
+ } else if( trend === 'drop'){
return
+ } else {
+ return null;
}
}
-export default class Wnumber extends React.Component {
+interface WnumberProps {
+ className?: string;
+ style?: React.CSSProperties;
+ status?: Status | string;
+ unit?: React.ReactNode;
+ numberTrend?: Trend;
+ rightRatioTrend?: Trend;
+ rightTitle?: React.ReactNode;
+ rightRatio?: React.ReactNode;
+ rightRatioStatus?: Status | string;
+ trend?: () => React.ReactNode;
+ bottomTitle?: React.ReactNode;
+}
+
+export default class Wnumber extends React.Component {
static displayName = 'Wnumber';
static defaultProps = {
@@ -27,22 +44,34 @@ export default class Wnumber extends React.Component {
status: ''
};
- constructor(props) {
+ constructor(props: WnumberProps) {
super(props);
// 图表初始化时记录日志
chartLog('Wnumber', 'init');
}
- renderBottom(bottomTitle) {
+ renderBottom(bottomTitle: React.ReactNode) {
if (!!bottomTitle) {
return(
{bottomTitle}
);
+ } else {
+ return null;
}
}
- renderMain(status, unit, numberTrend, rightRatioTrend, rightTitle, rightRatio, rightRatioStatus, trend, children) {
+ renderMain(
+ status: string,
+ unit: React.ReactNode,
+ numberTrend: Trend,
+ rightRatioTrend: Trend,
+ rightTitle: React.ReactNode,
+ rightRatio: React.ReactNode,
+ rightRatioStatus: string,
+ trend: () => React.ReactNode,
+ children: React.ReactNode,
+ ) {
const numberTrendIcon = getTrendIcon(numberTrend);
const numberClasses = `${prefix}-number`;
@@ -104,7 +133,7 @@ export default class Wnumber extends React.Component {
} = this.props;
const mainClasses = classNames({
- 'cloud-charts': true,
+ [FullCrossName]: true,
[`${prefix}`]: true,
[className]: !!className
});
@@ -117,9 +146,3 @@ export default class Wnumber extends React.Component {
);
}
}
-
-Wnumber.propTypes = {
- bottomTitle: PropTypes.node,
- unit: PropTypes.node,
- trend: PropTypes.func
-};
diff --git a/components/Wtreemap/G2Treemap.scss b/src/Wnumber/scss/function.scss
similarity index 100%
rename from components/Wtreemap/G2Treemap.scss
rename to src/Wnumber/scss/function.scss
diff --git a/src/Wnumber/scss/mixin.scss b/src/Wnumber/scss/mixin.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/components/Wnumber/scss/variable.scss b/src/Wnumber/scss/variable.scss
similarity index 94%
rename from components/Wnumber/scss/variable.scss
rename to src/Wnumber/scss/variable.scss
index 7c76c5f0..b2a3ea2b 100644
--- a/components/Wnumber/scss/variable.scss
+++ b/src/Wnumber/scss/variable.scss
@@ -1,5 +1,5 @@
@import "../../themes/index";
-$wnumber-prefix: '.cloud-wnumber';
+$wnumber-prefix: '.#{$base-prefix}-wnumber';
$font-family: getVar(widgets-font-family-txd-m-number, $widgets-font-family-txd-m-number);
$font-size-l: getVar(widgets-font-size-6, $widgets-font-size-6);
diff --git a/components/Wpie/gui.schema.json b/src/Wpie/gui.schema.json
similarity index 100%
rename from components/Wpie/gui.schema.json
rename to src/Wpie/gui.schema.json
diff --git a/src/Wpie/index.scss b/src/Wpie/index.scss
new file mode 100644
index 00000000..e1b30633
--- /dev/null
+++ b/src/Wpie/index.scss
@@ -0,0 +1,45 @@
+@import "../themes/index";
+
+.#{$base-name}.G2Pie {
+ position: relative;
+ text-align: center;
+ box-sizing: border-box;
+
+ .#{$base-name}-children {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ text-align: center;
+ max-width: 100%;
+ max-height: 100%;
+ transform: translate(-50%, -50%);
+ //overflow: auto;
+ }
+
+ //& > div {
+ // height: 100%;
+ // display: inline-flex;
+ // justify-content: center;
+ // align-items: center;
+ // text-align: left;
+ //
+ // & > canvas {
+ // position: static;
+ // flex: none;
+ // }
+ //
+ // // hack掉图例的高度限制,比用legend.maxLength逻辑要简单
+ // .g2-legend {
+ // max-width: none !important;
+ // max-height: 100% !important;
+ // }
+ //
+ // .g2-tooltip-list > li:first-child {
+ // margin-top: 0 !important;
+ // }
+ //
+ // .g2-legend-list-item:last-child {
+ // margin-bottom: 1px !important;
+ // }
+ //}
+}
diff --git a/src/Wpie/index.tsx b/src/Wpie/index.tsx
new file mode 100644
index 00000000..796ae1f9
--- /dev/null
+++ b/src/Wpie/index.tsx
@@ -0,0 +1,339 @@
+'use strict';
+
+import { Chart, Geometry, Types, BaseChartConfig, ChartData, G2Dependents, Colors } from '../common/types';
+import Base from "../common/Base";
+import themes from '../themes/index';
+import { /*pxToNumber,*/ numberDecimal, /*isInvalidNumber*/ } from '../common/common';
+import './index.scss';
+import rectTooltip, { TooltipConfig } from '../common/rectTooltip';
+import rectLegend, { LegendConfig } from '../common/rectLegend';
+import label, { LabelConfig } from '../common/label';
+import geomStyle, { GeomStyleConfig } from '../common/geomStyle';
+import polarLegendLayout from '../common/polarLegendLayout';
+import errorWrap from '../common/errorWrap';
+import updateChildrenPosition from '../common/updateChildrenPosition';
+
+// function transformCoord(coord, transform = {}) {
+// const { type, param } = transform;
+// if (coord[type] && Array.isArray(param)) {
+// coord[type](...param);
+// }
+// }
+//
+function selectGeom(geom: Geometry, selectKey?: string) {
+ // if (!geom || !selectKey || !Array.isArray(this.data)) {
+ if (!geom) {
+ return;
+ }
+
+ geom.elements.forEach((element) => {
+ // 清除选中效果
+ if (element.hasState('selected')) {
+ element.setState('selected', false);
+ }
+
+ // 如果selectKey为假值,则只清空选中效果。
+ if (!selectKey) {
+ return;
+ }
+
+ const d = element.getData();
+
+ if (d.x === selectKey) {
+ element.setState('selected', true);
+ }
+ });
+}
+//
+// function paddingNumber(value) {
+// return isInvalidNumber(value) ? 0 : Number(value);
+// }
+//
+// export function getDrawPadding(drawPadding, labelConfig, defaultDrawPadding) {
+// if (Array.isArray(drawPadding)) {
+// return drawPadding;
+// } else if (!isInvalidNumber(drawPadding)) {
+// return [drawPadding, drawPadding, drawPadding, drawPadding];
+// } else if (labelConfig && labelConfig.visible !== false) {
+// // 饼图使用 label 时,调整 drawPadding
+// return defaultDrawPadding.map(p => Math.max(p, 48));
+// } else {
+// return defaultDrawPadding;
+// }
+// }
+
+interface WpieConfig extends BaseChartConfig {
+ colors?: Colors;
+ legend?: LegendConfig | boolean;
+ tooltip?: TooltipConfig | boolean;
+ autoSort?: boolean;
+ cycle?: boolean;
+ select?: boolean;
+ innerRadius?: number;
+ outerRadius?: number;
+ label?: LabelConfig | boolean,
+ selectData?: string;
+ geomStyle?: GeomStyleConfig;
+}
+
+export class Pie extends Base {
+ chartName = 'G2Pie';
+
+ getDefaultConfig(): WpieConfig {
+ return {
+ colors: themes.category_12,
+ // padding: [20, 20, 20, 20],
+ legend: {
+ position: 'right',
+ align: '',
+ showData: true,
+ nameFormatter: null, // 可以强制覆盖,手动设置label
+ valueFormatter: null,
+ },
+ tooltip: {
+ nameFormatter: null,
+ valueFormatter: null,
+ },
+ // coord: null,
+ autoSort: true,
+ cycle: false,
+ select: false,
+ innerRadius: 0.8, // 内环半径大小,仅cycle为true时可用
+ outerRadius: 0.8, // 饼图半径大小,初始化时可用
+ // drawPadding: [10, 10, 10, 10],
+ label: false,
+ };
+ }
+
+ totalData = 0;
+
+ changeData(chart: Chart, config: WpieConfig, data: ChartData) {
+ // 更新数据总和值,保证百分比的正常
+ let totalData = 0;
+ data.forEach((d: { y: number; }) => {
+ totalData += d.y;
+ });
+ this.totalData = totalData;
+
+ // 不要忘记排序的状态
+ if (config.autoSort) {
+ data.sort((a: Types.LooseObject, b: Types.LooseObject) => b.y - a.y);
+ }
+ // 更新挂载的转换数据
+ // this.data = data;
+
+ chart.changeData(data);
+ }
+
+ protected geom: Geometry = null;
+
+ isChangeEqual(objValue: any, othValue: any, key: string) {
+ if (key === 'selectData' && objValue !== othValue) {
+ selectGeom(this.geom, objValue);
+ return true;
+ }
+ return undefined;
+ }
+
+ init(chart: Chart, config: WpieConfig, data: any[]) {
+ const defs: Record = {
+ type: {
+ type: 'cat',
+ },
+ };
+
+ if (config.autoSort) {
+ data.sort((a, b) => b.y - a.y);
+ }
+ // 挂载转换后的数据
+ // this.data = data;
+
+ chart.scale(defs);
+ chart.data(data);
+
+ // 重要:绘制饼图时,必须声明 theta 坐标系
+ const thetaConfig: Types.CoordinateCfg = {
+ // radius: 1, // 设置饼图的为100% 大小,具体大小改变在 beforeInit 中diameter的值,目前为0.8
+ radius: Math.max(Math.min(config.outerRadius, 1), 0.01),
+ };
+ if (config.cycle) {
+ thetaConfig.innerRadius = Math.max(Math.min(config.innerRadius, 1), 0);
+ }
+ // coordinate translate 操作会导致饼图变形,暂时换一种方式实现
+ /*const coord = */chart.coordinate('theta', thetaConfig);
+
+ // if (config.coord) {
+ // const { transform } = config.coord || {};
+ //
+ // if (Array.isArray(transform)) {
+ // transform.forEach((t) => {
+ // transformCoord(coord, t);
+ // });
+ // } else if (transform && typeof transform === 'object') {
+ // transformCoord(coord, transform);
+ // }
+ // }
+
+ // 计算得总数据
+ let totalData = 0;
+ data.forEach((d) => {
+ totalData += d.y;
+ });
+ this.totalData = totalData;
+
+ // const drawPadding = getDrawPadding(config.drawPadding, config.label, this.defaultConfig.drawPadding);
+
+ // 设置图例
+ rectLegend(this, chart, config, {
+ // autoCollapse: false,
+ // position: 'right',
+ // itemTpl: (value, itemColor, checked, index) => {
+ // const { nameFormatter, valueFormatter, showData = true } = config.legend || {};
+ //
+ // const item = (this.data && this.data[index]) || {};
+ // const raw = (this.rawData && this.rawData[0]) || {};
+ // const percent = numberDecimal(item.y / this.totalData, 4);
+ //
+ // const result = nameFormatter ? nameFormatter(value, {
+ // ...raw,
+ // percent,
+ // itemColor,
+ // checked,
+ // }, index) : value;
+ //
+ // if (showData) {
+ // const number = valueFormatter ? valueFormatter(item.y, {
+ // ...raw,
+ // percent,
+ // itemColor,
+ // checked,
+ // }, index) : item.y;
+ // return `${'' +
+ // '' +
+ // ''}${result}` + `${number}`;
+ // }
+ //
+ // return `${'' +
+ // '' +
+ // ''}${result}`;
+ // },
+ // 'g2-legend': {
+ // ...legendHtmlContainer,
+ // position: 'static',
+ // overflow: 'auto',
+ // // inline flex items 不能使用百分比的margin/padding,设置为固定大小
+ // marginLeft: `${Math.max(pxToNumber(themes['widgets-font-size-4']) - drawPadding[1], 0)}px`,
+ // },
+ // 'g2-legend-list-item': {
+ // ...legendHtmlListItem,
+ // marginRight: 0,
+ // },
+ }, true, null, true, (item: G2Dependents.ListItem, index: number) => {
+ const { name } = item;
+ const raw = (this.rawData && this.rawData[0]) || {};
+ let value = 0;
+ raw.data.forEach((r: any) => {
+ if (Array.isArray(r) && r[0] === name) {
+ value = r[1];
+ } else if (typeof r === 'object' && r.x === name) {
+ value = r.y
+ }
+ });
+ const percent = numberDecimal(value / this.totalData, 4);
+
+ return {
+ ...raw,
+ percent,
+ ...item,
+ }
+ });
+
+ // tooltip
+ rectTooltip(
+ this,
+ chart,
+ config,
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ shared: false,
+ },
+ (ev: any) => {
+ const raw = (this.rawData && this.rawData[0]) || {};
+ const { items } = ev.data;
+
+ items.forEach((item: any, index: number) => {
+ const percent = numberDecimal(item.value / this.totalData, 4);
+
+ if (typeof config.tooltip === 'boolean') {
+ return;
+ }
+
+ if (config.tooltip.valueFormatter) {
+ item.value = config.tooltip.valueFormatter(item.value, {
+ ...raw,
+ percent,
+ }, index, items);
+ }
+ if (config.tooltip.nameFormatter) {
+ item.name = config.tooltip.nameFormatter(item.name, {
+ ...raw,
+ percent,
+ }, index, items);
+ }
+ });
+ },
+ {
+ showTitle: false,
+ showMarkers: false,
+ showCrosshairs: false,
+ shared: false,
+ }
+ );
+
+ this.geom = chart.interval()
+ .position('y')
+ .color('x', config.colors)
+ .adjust('stack');
+
+ if (config.select) {
+ chart.interaction('element-single-selected');
+ }
+
+ geomStyle(this.geom, config.geomStyle);
+
+ const labelField = 'y';
+ label(this.geom, config, labelField, null, undefined, false, {
+ offset: 20,
+ content: ((v, item, index) => {
+ if (typeof config.label === 'boolean') {
+ return v[labelField];
+ }
+ if (config.label.labelFormatter) {
+ const percent = numberDecimal(v[labelField] / this.totalData, 4);
+
+ return config.label.labelFormatter(v[labelField], {
+ ...item,
+ percent,
+ } as Types.MappingDatum, index);
+ }
+ return v[labelField];
+ }) as Types.GeometryLabelContentCallback,
+ });
+
+ polarLegendLayout(chart);
+
+ chart.on('afterrender', () => {
+ // 默认选中效果
+ selectGeom(this.geom, config.selectData);
+
+ updateChildrenPosition(chart, this.chartDom);
+ });
+
+ }
+}
+
+const Wpie: typeof Pie = errorWrap(Pie);
+
+export default Wpie;
diff --git a/components/Wplaceholder/index.scss b/src/Wplaceholder/index.scss
similarity index 100%
rename from components/Wplaceholder/index.scss
rename to src/Wplaceholder/index.scss
diff --git a/components/Wplaceholder/index.jsx b/src/Wplaceholder/index.tsx
similarity index 86%
rename from components/Wplaceholder/index.jsx
rename to src/Wplaceholder/index.tsx
index 463efd79..06093089 100644
--- a/components/Wplaceholder/index.jsx
+++ b/src/Wplaceholder/index.tsx
@@ -1,12 +1,13 @@
'use strict';
-import React from 'react';
+import * as React from 'react';
import classNames from 'classnames';
import chartLog from "../common/log";
-import Locale from './locale';
+import Locale, { LocaleItem } from './locale';
import './index.scss';
+import { FullCrossName, PrefixName } from '../constants';
-const prefix = 'cloud-wplaceholder';
+const prefix = `${PrefixName}-wplaceholder`;
// 默认显示的图标
const svgWidth = 36, svgHeight = 32, itemHeight1 = 20, itemHeight2 = 26, itemHeight3 = 32;
@@ -41,7 +42,7 @@ const noDataSvg =
));
-
-stories.addDecorator(withKnobs);
+stories.add('多重环图', () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+));
diff --git a/stories/chart.pie.stories.js b/stories/chart.pie.stories.js
index cf17ab22..96ded0d9 100644
--- a/stories/chart.pie.stories.js
+++ b/stories/chart.pie.stories.js
@@ -4,7 +4,7 @@ import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { withKnobs, number, array } from "@storybook/addon-knobs";
-import { Wpie, Wnumber, Wcontainer, Wdashboard } from '@alicloud/cloud-charts';
+import { Wpie, Wnumber, Wcontainer } from '@alicloud/cloud-charts';
const data = [
{
@@ -20,25 +20,38 @@ const data = [
}
];
-function WdashboardDemo() {
- const data = number('仪表盘数字', 20);
- const arr = array('值域范围', [0, 100],);
- const [count, setCount] = useState(data);
- const [range, setRange] = useState(arr);
- useMemo(() => {
- setRange(arr.map(Number));
- setCount(data);
- }, [data, arr]);
- return
;
-}
+// function WdashboardDemo() {
+// const data = number('仪表盘数字', 20);
+// const arr = array('值域范围', [0, 100],);
+// const [count, setCount] = useState(data);
+// const [range, setRange] = useState(arr);
+// useMemo(() => {
+// setRange(arr.map(Number));
+// setCount(data);
+// }, [data, arr]);
+// return
;
+// }
const stories = storiesOf('Wpie', module);
+stories.addDecorator(withKnobs);
+
stories.add('饼图', () => (
- (
}} data={data} />
));
-stories.add('仪表盘', () => (
-
-));
-
-stories.addDecorator(withKnobs);
+// stories.add('仪表盘', () => (
+//
+// ));
diff --git a/stories/chart.radar.stories.js b/stories/chart.radar.stories.js
new file mode 100644
index 00000000..a2134c05
--- /dev/null
+++ b/stories/chart.radar.stories.js
@@ -0,0 +1,40 @@
+import React from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { linkTo } from '@storybook/addon-links';
+import { withKnobs, select } from "@storybook/addon-knobs";
+
+import { Wcontainer, Wradar } from '@alicloud/cloud-charts';
+
+const data = [
+ {
+ name: '平均水准',
+ data: [
+ ['2001', 41],
+ ['2002', 38],
+ ['2003', 33],
+ ['2004', 30],
+ ['2005', 25],
+ ['2006', 42],
+ ]
+ },
+ {
+ name: '个人水准',
+ data: [
+ ['2001', 25],
+ ['2002', 72],
+ ['2003', 35],
+ ['2004', 27],
+ ['2005', 54],
+ ['2006', 52],
+ ]
+ }
+];
+
+const stories = storiesOf('Wradar', module);
+stories.addDecorator(withKnobs);
+
+stories.add('雷达图', () => (
+
+));
diff --git a/stories/chart.rectangle.stories.js b/stories/chart.rectangle.stories.js
new file mode 100644
index 00000000..efef821a
--- /dev/null
+++ b/stories/chart.rectangle.stories.js
@@ -0,0 +1,915 @@
+import React from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { linkTo } from '@storybook/addon-links';
+import { withKnobs, select } from '@storybook/addon-knobs';
+
+import { Wcontainer, Wrectangle } from '@alicloud/cloud-charts';
+
+const defaultData = [
+ { x: 211.30367873206103, y: 374.011454046156 },
+ { x: 500.29867653719464, y: 364.0710814670023 },
+ { x: 373.72304385883353, y: 446.39571451770905 },
+ { x: 654.4950570479579, y: 636.749822123514 },
+ { x: 555.5799779483943, y: 595.4051363416937 },
+ { x: 745.2854049080454, y: 435.55263692303254 },
+ { x: 504.506365811858, y: 518.0112206116842 },
+ { x: 420.39650800042966, y: 333.86248701420817 },
+ { x: 439.2463956135431, y: 405.9698416928732 },
+ { x: 316.3492255703077, y: 575.4210776358901 },
+ { x: 546.2106696472646, y: 296.3304890710614 },
+ { x: 554.5398059654111, y: 613.1355624560277 },
+ { x: 566.8465200771166, y: 550.4512730468393 },
+ { x: 569.9861918249525, y: 584.6532046541478 },
+ { x: 535.4635805897575, y: 429.5654002924505 },
+ { x: 512.7313104093327, y: 617.8319758604068 },
+ { x: 562.4878208962938, y: 630.8185707970533 },
+ { x: 508.8841407993702, y: 434.66344300662377 },
+ { x: 437.0783792914773, y: 691.444807998203 },
+ { x: 482.2170197598377, y: 399.88600246434675 },
+ { x: 472.70124566591085, y: 467.52483144644725 },
+ { x: 513.4709032516229, y: 434.1370832831939 },
+ { x: 493.45265071748344, y: 551.7101380662735 },
+ { x: 426.9178798652837, y: 537.9716235674538 },
+ { x: 548.483329803987, y: 448.02606355101284 },
+ { x: 585.8671979481455, y: 455.93379157594563 },
+ { x: 633.2791718676401, y: 512.2580771864191 },
+ { x: 514.8691821607385, y: 592.8873617136005 },
+ { x: 470.22115836425576, y: 540.6048691723632 },
+ { x: 469.428452733005, y: 379.50853698478835 },
+ { x: 571.7799919499706, y: 520.6826469984533 },
+ { x: 571.2114599249581, y: 454.7714560473075 },
+ { x: 374.68475036451997, y: 528.4581346664601 },
+ { x: 490.69640934601483, y: 582.7292738819974 },
+ { x: 542.2157565653764, y: 461.06250272819767 },
+ { x: 394.3020616474276, y: 498.3466715017804 },
+ { x: 463.3864785083781, y: 466.25352047416357 },
+ { x: 377.61661315452227, y: 440.24869222380835 },
+ { x: 464.64664344082075, y: 383.36165428770784 },
+ { x: 462.2464750109209, y: 485.3618345117429 },
+ { x: 477.2944337465219, y: 491.82547859512 },
+ { x: 386.3370673072265, y: 641.3719956594801 },
+ { x: 530.7463765829508, y: 461.5559833714867 },
+ { x: 609.3295573498502, y: 648.4078541061333 },
+ { x: 393.9172142903677, y: 468.4755942206742 },
+ { x: 542.3975530179257, y: 520.1441217765748 },
+ { x: 675.244022342516, y: 587.0680397366147 },
+ { x: 477.220351815843, y: 430.5092169311354 },
+ { x: 442.1733471211702, y: 535.3233388387861 },
+ { x: 530.2185153476594, y: 497.09116235164777 },
+ { x: 513.0142472779673, y: 517.4273346237032 },
+ { x: 412.54801219134106, y: 502.8553704162518 },
+ { x: 351.7561155562086, y: 560.8132757721108 },
+ { x: 606.9595573037417, y: 451.81637518515305 },
+ { x: 476.6311707815392, y: 494.25167338006327 },
+ { x: 412.31797006274917, y: 456.16038810487913 },
+ { x: 518.3300684204777, y: 641.0037952790567 },
+ { x: 317.16830567167653, y: 652.4039389493006 },
+ { x: 511.88858422905724, y: 384.7451280380339 },
+ { x: 479.39047780046235, y: 526.5308384289244 },
+ { x: 632.01983549944, y: 484.7587252864994 },
+ { x: 498.04244261363624, y: 559.8170262948211 },
+ { x: 625.4038119218783, y: 420.6295128158771 },
+ { x: 432.3176947324843, y: 596.7102173808642 },
+ { x: 433.53480307930545, y: 390.91611033166043 },
+ { x: 511.41585291608345, y: 437.99524250993096 },
+ { x: 583.8822163450964, y: 367.89029954642353 },
+ { x: 436.79056011010937, y: 432.8082356569331 },
+ { x: 596.284804346587, y: 423.01770028741 },
+ { x: 567.9869431045063, y: 534.126264244781 },
+ { x: 388.916352313167, y: 502.25269262667405 },
+ { x: 406.1809723219993, y: 527.3664956093596 },
+ { x: 521.9807083119829, y: 314.3609329604307 },
+ { x: 692.3941197054453, y: 506.9636789956612 },
+ { x: 441.1874304054962, y: 508.76667068513575 },
+ { x: 554.1548631777279, y: 416.55218065901505 },
+ { x: 331.12967191887844, y: 576.6122314975863 },
+ { x: 410.68618391624346, y: 528.8140320649774 },
+ { x: 425.681122888056, y: 408.25389668728263 },
+ { x: 413.13759893446075, y: 600.2017378542101 },
+ { x: 530.7475806343792, y: 559.6422923479466 },
+ { x: 501.53134237509835, y: 312.6718509895751 },
+ { x: 585.3827340808548, y: 394.71281208515177 },
+ { x: 556.028104390894, y: 518.170318279938 },
+ { x: 459.8184937914118, y: 503.1410377550364 },
+ { x: 532.7646071896394, y: 534.5720270762408 },
+ { x: 408.31151688833324, y: 389.8784269552757 },
+ { x: 601.8246299904816, y: 496.91317182653034 },
+ { x: 515.2944302515352, y: 618.6890159233226 },
+ { x: 537.993922060343, y: 478.15416415813945 },
+ { x: 463.74583559938793, y: 474.1275164583354 },
+ { x: 551.0596654714897, y: 473.4997888982033 },
+ { x: 525.3329874293378, y: 494.77748039575437 },
+ { x: 427.16861046157396, y: 533.3520080409141 },
+ { x: 492.72419694689967, y: 569.0509336975551 },
+ { x: 518.8240739599764, y: 472.4958542849112 },
+ { x: 612.2345217870545, y: 484.99735008149196 },
+ { x: 546.6735597177873, y: 624.3221146861104 },
+ { x: 499.34685699208393, y: 465.8994351180164 },
+ { x: 411.3766847508682, y: 505.7058940390503 },
+ { x: 425.51002915227116, y: 686.2467855331919 },
+ { x: 560.2926329527725, y: 453.1944966578446 },
+ { x: 505.4552648282487, y: 473.4580316069642 },
+ { x: 402.1697700458742, y: 594.8296479989378 },
+ { x: 526.1321775684746, y: 559.511445003541 },
+ { x: 410.4277465532173, y: 497.90626919683797 },
+ { x: 463.1289430928774, y: 455.80533456802516 },
+ { x: 477.29551951605396, y: 421.12605752790034 },
+ { x: 503.20664741281684, y: 475.4074667047237 },
+ { x: 465.3992514276489, y: 603.1765203184895 },
+ { x: 517.2150952421541, y: 482.1322195304222 },
+ { x: 503.43307316036953, y: 486.24305017325537 },
+ { x: 537.400502048418, y: 388.4458360690039 },
+ { x: 626.4234440930162, y: 462.1929518464152 },
+ { x: 609.2552357324187, y: 504.1179854375893 },
+ { x: 508.2420322352633, y: 572.104152289136 },
+ { x: 496.5615405674497, y: 592.6280969072569 },
+ { x: 573.4766996714388, y: 401.05158460078553 },
+ { x: 536.2617476651686, y: 516.8042963935208 },
+ { x: 596.6878290615232, y: 502.48824686343653 },
+ { x: 680.8181487925553, y: 460.9730479096322 },
+ { x: 400.32219295560134, y: 437.6297869041185 },
+ { x: 392.0243797368176, y: 695.8802365292498 },
+ { x: 424.81199499129195, y: 527.9745024545143 },
+ { x: 550.760529935613, y: 550.235445561628 },
+ { x: 441.12269462320324, y: 561.5919924367658 },
+ { x: 673.7210347678013, y: 477.69221579432894 },
+ { x: 614.7562504156865, y: 369.34061251344764 },
+ { x: 530.4147550276533, y: 419.54287037253533 },
+ { x: 570.2404623187833, y: 378.99087944442294 },
+ { x: 439.46646710306385, y: 595.7424590490539 },
+ { x: 507.0421586817127, y: 437.4907986912324 },
+ { x: 283.08186742492387, y: 515.190154263508 },
+ { x: 564.883304852088, y: 721.8230155215433 },
+ { x: 362.90355892093237, y: 550.9074566244059 },
+ { x: 595.4901526579828, y: 620.8228754184787 },
+ { x: 450.488502055551, y: 349.2791062014405 },
+ { x: 502.22454188127296, y: 500.3261128860716 },
+ { x: 520.5790835059427, y: 484.9431589172062 },
+ { x: 605.192386539603, y: 546.9185553545011 },
+ { x: 515.8976120506509, y: 407.04021041537294 },
+ { x: 579.8483746888679, y: 429.2044676664708 },
+ { x: 328.97425997101504, y: 521.217576775235 },
+ { x: 561.1550829328887, y: 292.65193047486855 },
+ { x: 478.3978513440598, y: 449.01377573167423 },
+ { x: 446.0527467634318, y: 463.99682118743704 },
+ { x: 536.9472553923533, y: 501.91476621938887 },
+ { x: 578.8739934210504, y: 460.9092513689609 },
+ { x: 546.1260688258686, y: 636.3500400129453 },
+ { x: 435.65762875382774, y: 697.1370429406127 },
+ { x: 737.9141503410409, y: 424.91036256002155 },
+ { x: 459.44321259340836, y: 471.4262443345213 },
+ { x: 558.6631746265376, y: 420.74823670795627 },
+ { x: 505.92348772426175, y: 363.46305239009814 },
+ { x: 475.22050105937336, y: 510.35295287299016 },
+ { x: 506.0616085481746, y: 341.6919385445468 },
+ { x: 550.7139135848942, y: 368.15211969540155 },
+ { x: 326.3158707074888, y: 425.80066731555 },
+ { x: 368.3820360708652, y: 571.2959425834009 },
+ { x: 502.42259510286664, y: 471.25416134181086 },
+ { x: 540.9386679766254, y: 458.729190752289 },
+ { x: 595.5088272010596, y: 560.1465327534808 },
+ { x: 524.8847789763561, y: 503.9231528776832 },
+ { x: 358.33319191523896, y: 411.1262559546793 },
+ { x: 461.83277576987587, y: 429.6943159767158 },
+ { x: 593.154299821099, y: 546.9021751049703 },
+ { x: 530.8246093493783, y: 575.4965550814504 },
+ { x: 480.33770582253857, y: 509.2794045197598 },
+ { x: 461.7377506415799, y: 566.8859540587977 },
+ { x: 458.7845073132695, y: 356.76406466094534 },
+ { x: 590.9535767174609, y: 464.315421357811 },
+ { x: 397.4373787815846, y: 464.5129241492026 },
+ { x: 346.08304346073453, y: 403.3630637105585 },
+ { x: 604.5858444261162, y: 447.41083495956997 },
+ { x: 499.66453659673783, y: 368.3274314295995 },
+ { x: 507.6439099801658, y: 393.5480764029857 },
+ { x: 519.5906440462248, y: 402.8720326305429 },
+ { x: 421.78456876413327, y: 550.0244521976226 },
+ { x: 448.64345849841663, y: 540.2604230148237 },
+ { x: 479.95272248771613, y: 604.7301958995699 },
+ { x: 525.2029328859737, y: 453.8211583379145 },
+ { x: 548.5803825535006, y: 469.36661460928485 },
+ { x: 444.79803843393347, y: 592.3846817993119 },
+ { x: 508.80108459019857, y: 517.9240700240804 },
+ { x: 576.8337598077305, y: 419.33083438409795 },
+ { x: 476.1085899469971, y: 416.39317171497663 },
+ { x: 339.02239109684905, y: 548.1512161472713 },
+ { x: 514.7043674647291, y: 483.0052950194065 },
+ { x: 566.9908780183205, y: 293.4791084449525 },
+ { x: 578.292903412172, y: 623.887130702628 },
+ { x: 493.7716782792751, y: 453.68310895344985 },
+ { x: 654.2811473498864, y: 576.0530543110245 },
+ { x: 585.5613331767776, y: 436.75997163020577 },
+ { x: 508.81834933307266, y: 476.6276496533708 },
+ { x: 509.7791074319298, y: 423.2532697903749 },
+ { x: 442.8573214743326, y: 365.72937157489923 },
+ { x: 405.03746312623815, y: 426.59001032817565 },
+ { x: 536.3568566582842, y: 591.6454872380062 },
+ { x: 572.704643719756, y: 499.67885290660394 },
+ { x: 545.8225055750725, y: 504.745470433033 },
+ { x: 470.9729295659042, y: 684.038304134605 },
+ { x: 525.9839037047224, y: 505.2992850468933 },
+ { x: 555.9695250132587, y: 463.17576082032605 },
+ { x: 444.0643537580134, y: 671.7004555737004 },
+ { x: 561.0464866179215, y: 511.0028050500381 },
+ { x: 376.12894652296046, y: 527.7797230546386 },
+ { x: 464.0413356103739, y: 524.6452339816625 },
+ { x: 389.09989347145864, y: 536.2920691111153 },
+ { x: 493.2448626500672, y: 521.613502447107 },
+ { x: 483.8672315043852, y: 540.6057147139167 },
+ { x: 512.5430101371742, y: 448.47399700657184 },
+ { x: 564.5480642044279, y: 499.552710928433 },
+ { x: 544.9974529114636, y: 492.46923284339147 },
+ { x: 540.2747162497832, y: 539.1410969387849 },
+ { x: 470.71968112425543, y: 375.53721369335744 },
+ { x: 545.59472750607, y: 531.5214587662657 },
+ { x: 286.6239600825156, y: 369.70408560825234 },
+ { x: 529.9170977640206, y: 460.54883579819983 },
+ { x: 543.878047433643, y: 454.07265489368035 },
+ { x: 365.91394778050494, y: 446.36151936144796 },
+ { x: 505.06608506264536, y: 374.9359198112955 },
+ { x: 501.67371584676033, y: 474.9506076248796 },
+ { x: 490.7503066392119, y: 642.8242101000307 },
+ { x: 681.8251900740715, y: 562.8974978041324 },
+ { x: 449.97841290387635, y: 470.5692865639247 },
+ { x: 532.8165137661872, y: 532.6130779292821 },
+ { x: 538.6081789064931, y: 484.8850131011816 },
+ { x: 485.16062903399217, y: 273.8954171845073 },
+ { x: 571.0255019611808, y: 588.218639062889 },
+ { x: 471.5959110025587, y: 474.22675268613744 },
+ { x: 495.1079734379342, y: 511.9422792741271 },
+ { x: 408.5738243947712, y: 567.3940239441349 },
+ { x: 408.53641458759864, y: 421.6950987925324 },
+ { x: 537.1467553837775, y: 443.4412248598147 },
+ { x: 500.99187683175387, y: 458.6578299966922 },
+ { x: 480.6852858595781, y: 489.79237373523205 },
+ { x: 546.5091533357473, y: 441.5317806822812 },
+ { x: 612.388664264704, y: 578.027636982181 },
+ { x: 535.1600085738139, y: 415.0983406539739 },
+ { x: 456.25061052846445, y: 465.0865739264813 },
+ { x: 475.2180325500778, y: 434.834446182423 },
+ { x: 546.6815302527459, y: 519.0352882367044 },
+ { x: 546.7682198729765, y: 560.7275764360419 },
+ { x: 436.6957107888223, y: 503.71803159632265 },
+ { x: 481.09112411537626, y: 508.76546113740517 },
+ { x: 522.1817611061487, y: 415.2596662107072 },
+ { x: 520.5951943184549, y: 378.2975350570529 },
+ { x: 402.5988575917302, y: 471.6301399361883 },
+ { x: 493.25126510039723, y: 495.1047693433169 },
+ { x: 519.9657466395144, y: 622.8323333175266 },
+ { x: 524.9256670273479, y: 393.9646345357259 },
+ { x: 432.75182521316924, y: 505.4696944373758 },
+ { x: 345.1381209164351, y: 373.1334912815224 },
+ { x: 435.15884846039955, y: 577.891584722025 },
+ { x: 477.5865879816974, y: 421.07774242150504 },
+ { x: 479.35762278310364, y: 547.1242481097886 },
+ { x: 342.1928954705578, y: 419.4399709460257 },
+ { x: 415.1455238816245, y: 357.9835909941887 },
+ { x: 565.2642582695297, y: 426.6176952625286 },
+ { x: 422.7174744049873, y: 456.5446000019993 },
+ { x: 636.1226120276992, y: 426.65700673063276 },
+ { x: 501.30652398809167, y: 663.0998877526969 },
+ { x: 520.6510455350486, y: 511.8099392812548 },
+ { x: 569.3712843401952, y: 533.2972771418749 },
+ { x: 387.5485769901922, y: 544.2745121855029 },
+ { x: 473.1655057293149, y: 584.693915458304 },
+ { x: 678.7589757855557, y: 426.49765711540545 },
+ { x: 479.9564994803489, y: 489.72759915558254 },
+ { x: 573.7022113182504, y: 447.8406810656314 },
+ { x: 446.77011226287993, y: 405.75057278310356 },
+ { x: 393.55656543093653, y: 236.03945575850327 },
+ { x: 400.58828018763415, y: 461.59298488127587 },
+ { x: 567.7823493824532, y: 301.6833427498223 },
+ { x: 473.8526816721188, y: 535.6271569230368 },
+ { x: 527.9121097240597, y: 480.08221918644347 },
+ { x: 655.412903565764, y: 480.43833115150454 },
+ { x: 441.27131003316316, y: 449.2099304953095 },
+ { x: 438.9995085118995, y: 502.93635934374475 },
+ { x: 490.93886765796566, y: 530.9517953486413 },
+ { x: 401.6049826209749, y: 452.2178223511916 },
+ { x: 528.4664337158049, y: 576.7710037155299 },
+ { x: 522.7590895878384, y: 548.1029703985565 },
+ { x: 499.4783291875969, y: 538.4143295133285 },
+ { x: 334.092924617675, y: 470.94265652618066 },
+ { x: 657.6879979539913, y: 631.2502535510722 },
+ { x: 536.2609515009, y: 449.1213349820443 },
+ { x: 449.2994630780923, y: 387.08457538320374 },
+ { x: 419.0166391821219, y: 413.4304001456575 },
+ { x: 580.564796466822, y: 461.6681054511002 },
+ { x: 682.3728941677911, y: 538.2204505421125 },
+ { x: 429.9294231675126, y: 481.4451054451689 },
+ { x: 498.48327422900786, y: 375.5281416827156 },
+ { x: 401.05981926196716, y: 505.1020806785186 },
+ { x: 645.4382111443048, y: 519.220787956155 },
+ { x: 583.3692635848748, y: 552.9374574383362 },
+ { x: 234.24461478649857, y: 452.5022837870909 },
+ { x: 653.7793314669857, y: 456.0733632770932 },
+ { x: 438.12527889716864, y: 469.28492618575564 },
+ { x: 426.7336631805953, y: 505.5856181238134 },
+ { x: 583.2680208384265, y: 492.921222713445 },
+ { x: 493.6156718895478, y: 371.3204470597624 },
+ { x: 631.2413540855888, y: 500.41090787262016 },
+ { x: 592.425717816195, y: 414.9873095185982 },
+ { x: 471.0533167156141, y: 530.3116005209109 },
+ { x: 620.9769708967148, y: 479.1158955636709 },
+ { x: 420.3588733589064, y: 413.30313086332535 },
+ { x: 464.53237142409165, y: 588.0191092821726 },
+ { x: 533.9005910231865, y: 590.7297254744752 },
+ { x: 336.783466401133, y: 568.6209159459714 },
+ { x: 534.3848073547013, y: 456.6506112714792 },
+ { x: 586.2578785199065, y: 550.521463945985 },
+ { x: 499.66901152888323, y: 559.7529733966986 },
+ { x: 532.5626584492597, y: 733.6552348030797 },
+ { x: 497.02147156929846, y: 492.6493600270171 },
+ { x: 606.580397970732, y: 617.7814851115146 },
+ { x: 371.80388601566665, y: 537.7538408498999 },
+ { x: 462.9379981615447, y: 531.3548011476507 },
+ { x: 338.29316854630315, y: 547.0411054807645 },
+ { x: 582.8713179380296, y: 466.94360839414503 },
+ { x: 461.33461071196456, y: 501.1535871621273 },
+ { x: 581.7973386467154, y: 531.4709280550672 },
+ { x: 536.8803231304043, y: 479.73216745463947 },
+ { x: 421.3847128429275, y: 487.57859601234304 },
+ { x: 539.7449324710689, y: 489.2473764445596 },
+ { x: 448.86160702202307, y: 472.68810744279574 },
+ { x: 499.5956196044608, y: 350.8106506192257 },
+ { x: 518.0098139987305, y: 506.415904761604 },
+ { x: 446.1348303668796, y: 510.45684902815384 },
+ { x: 541.7193240961723, y: 496.7760728575743 },
+ { x: 408.7232418534397, y: 436.1613009299706 },
+ { x: 482.082654656081, y: 628.6905102567139 },
+ { x: 425.84377464511965, y: 531.9712841442458 },
+ { x: 449.72310346000125, y: 287.59922334276564 },
+ { x: 419.688906991027, y: 547.7306357827842 },
+ { x: 464.92434548381436, y: 449.7870685729045 },
+ { x: 480.47407555082543, y: 391.7719270180422 },
+ { x: 492.00208740598646, y: 447.2149382705922 },
+ { x: 425.53609501921926, y: 469.73368919129575 },
+ { x: 491.1213008850134, y: 494.3662534758912 },
+ { x: 449.40279123058576, y: 555.807871719544 },
+ { x: 565.0523154322525, y: 542.6957536427637 },
+ { x: 664.1763263894068, y: 621.3514440584214 },
+ { x: 475.81980893512815, y: 516.9940039650221 },
+ { x: 508.4481771743433, y: 444.91592916044755 },
+ { x: 463.74470490265816, y: 401.649298678607 },
+ { x: 457.17802961436774, y: 518.5923443244697 },
+ { x: 505.4886348789913, y: 465.45072901221596 },
+ { x: 465.143291768593, y: 382.5313369530992 },
+ { x: 544.2433201650409, y: 509.26660854096286 },
+ { x: 554.2268549164515, y: 452.2276213131056 },
+ { x: 550.7910288285524, y: 587.1283232502503 },
+ { x: 390.79945849972785, y: 537.8573402618811 },
+ { x: 508.17377168500565, y: 506.0345586383995 },
+ { x: 458.3305045850797, y: 523.9724859834696 },
+ { x: 211.89856480675047, y: 574.7304325217884 },
+ { x: 604.5403960926834, y: 463.8961920635836 },
+ { x: 474.65213533502936, y: 489.4379672085883 },
+ { x: 463.726164798927, y: 505.69719640335586 },
+ { x: 480.0989073286347, y: 432.20636611362954 },
+ { x: 629.4526262984357, y: 454.49378656644075 },
+ { x: 550.5097053855411, y: 499.57915897569984 },
+ { x: 484.2394635228406, y: 401.1082383413729 },
+ { x: 458.03102602949076, y: 557.2990588536151 },
+ { x: 374.7444937942013, y: 506.2569641282212 },
+ { x: 518.8239813230514, y: 545.1990821890384 },
+ { x: 410.5062950587104, y: 475.11014470265116 },
+ { x: 536.5450664232412, y: 463.2823697525272 },
+ { x: 332.3852271435554, y: 550.9907003371311 },
+ { x: 483.6989169357201, y: 607.4255515927225 },
+ { x: 588.8149056627042, y: 539.6299193365127 },
+ { x: 623.6087269720704, y: 479.8412965175789 },
+ { x: 452.88881385197624, y: 433.9407218658284 },
+ { x: 466.1688736306886, y: 593.257266912061 },
+ { x: 432.4037216704751, y: 382.70895063054036 },
+ { x: 582.0203315292996, y: 495.20992395642946 },
+ { x: 652.4064989319403, y: 474.2152623871251 },
+ { x: 474.25398009710483, y: 722.4165887132413 },
+ { x: 406.0992872295093, y: 512.2050871748296 },
+ { x: 542.5155827501541, y: 346.041159999362 },
+ { x: 643.6339126251648, y: 593.8355006087984 },
+ { x: 517.6742550974732, y: 390.0495417886605 },
+ { x: 697.2062968594304, y: 533.5319067511434 },
+ { x: 494.798843395511, y: 434.4546631552825 },
+ { x: 406.82551678968815, y: 439.01803207460244 },
+ { x: 544.6095819102176, y: 537.2833611476824 },
+ { x: 514.9556465055338, y: 527.7397162599354 },
+ { x: 477.74125476826293, y: 409.5941630286829 },
+ { x: 405.4063584745187, y: 444.821522108557 },
+ { x: 321.6884874794605, y: 361.94942319200743 },
+ { x: 521.6612945604838, y: 509.27474955785095 },
+ { x: 361.3020201968256, y: 462.74949982383475 },
+ { x: 515.4722643387136, y: 582.1661072610259 },
+ { x: 531.8452978329603, y: 528.8698402028336 },
+ { x: 469.2317318344659, y: 457.3900889866413 },
+ { x: 383.8641352789634, y: 487.51457025873685 },
+ { x: 405.65299379290025, y: 373.6486573169417 },
+ { x: 557.4553999527853, y: 481.7588066538681 },
+ { x: 558.3563208756472, y: 492.1089628616265 },
+ { x: 519.697263885083, y: 507.51214224844836 },
+ { x: 477.6245789913337, y: 437.33226389618113 },
+ { x: 386.6806999905625, y: 516.8999021096269 },
+ { x: 498.21447183175786, y: 539.6720778354381 },
+ { x: 500.4568743618031, y: 509.839377681147 },
+ { x: 396.6043280391872, y: 508.5841838024428 },
+ { x: 560.3097882390896, y: 470.4959533668516 },
+ { x: 505.8589397555764, y: 438.5331420840928 },
+ { x: 404.652426392179, y: 463.57551340532524 },
+ { x: 538.4624001397573, y: 584.4946466252921 },
+ { x: 528.961124900628, y: 593.3479262435405 },
+ { x: 510.3789470850636, y: 611.1438106898162 },
+ { x: 485.4072028087265, y: 527.2526329719045 },
+ { x: 527.6874638963251, y: 594.176158713484 },
+ { x: 551.2679026532729, y: 296.2955837922125 },
+ { x: 507.7008876340021, y: 588.4780624006426 },
+ { x: 517.6959222782743, y: 538.6391471540084 },
+ { x: 602.6096304371599, y: 498.30949021725723 },
+ { x: 413.0230721172735, y: 517.9734276203731 },
+ { x: 581.7993416070958, y: 389.77258222920926 },
+ { x: 457.8413719442926, y: 504.1555450001367 },
+ { x: 680.1688117266062, y: 580.2061039363467 },
+ { x: 529.1612084478692, y: 478.9814622596839 },
+ { x: 423.9305207496414, y: 482.5729112923247 },
+ { x: 547.2306586256943, y: 484.663041464371 },
+ { x: 571.0489407975447, y: 377.6121832800262 },
+ { x: 394.62369250834473, y: 700.0094717372975 },
+ { x: 429.03835846089385, y: 453.4181340183653 },
+ { x: 446.90223955966377, y: 456.86963482595627 },
+ { x: 500.15540240744855, y: 546.7216410183082 },
+ { x: 520.3052332461197, y: 467.5695079241376 },
+ { x: 432.70006316378596, y: 492.9405222292091 },
+ { x: 479.40985320017063, y: 310.71658613216437 },
+ { x: 317.6336673492284, y: 440.2277027835321 },
+ { x: 378.2868046135941, y: 485.4328576540941 },
+ { x: 596.059921842645, y: 670.2072255500588 },
+ { x: 426.63225177320834, y: 440.67450899526693 },
+ { x: 696.3824560788895, y: 536.2970308694265 },
+ { x: 548.9554004099568, y: 374.8675335764875 },
+ { x: 459.5356721441832, y: 531.3960310016533 },
+ { x: 474.76674155526155, y: 514.6899489869693 },
+ { x: 627.739952617811, y: 569.3648847223316 },
+ { x: 664.42231988802, y: 353.9613339431025 },
+ { x: 500.27353730413455, y: 462.7002805194931 },
+ { x: 594.6761581751309, y: 549.4804427523618 },
+ { x: 473.1200490864201, y: 637.3312546841138 },
+ { x: 604.0644769424558, y: 646.3100599742934 },
+ { x: 490.66790120775767, y: 625.7919637534566 },
+ { x: 390.49822565312934, y: 310.908468663234 },
+ { x: 566.1380025560975, y: 342.4257437965115 },
+ { x: 498.72403162570356, y: 567.8094628660455 },
+ { x: 389.2600351743589, y: 515.3763792624061 },
+ { x: 395.04512631256154, y: 566.3125526633387 },
+ { x: 453.1486017797189, y: 520.3725631692998 },
+ { x: 526.0300848562354, y: 333.1652763866988 },
+ { x: 489.3964841150009, y: 608.0114809002282 },
+ { x: 492.99705290334975, y: 440.38360401403355 },
+ { x: 508.1963544980637, y: 580.7430954565203 },
+ { x: 482.4034224893432, y: 355.06239713423156 },
+ { x: 556.3767365273534, y: 530.4636877245691 },
+ { x: 419.7644177428187, y: 495.8887038880258 },
+ { x: 626.5567326290472, y: 749.5257374778339 },
+ { x: 418.7486864666422, y: 357.662141376404 },
+ { x: 569.2789739479091, y: 496.12243817622715 },
+ { x: 387.7696228414706, y: 438.3011539284843 },
+ { x: 396.61578494623956, y: 417.6729132609761 },
+ { x: 533.0578456033197, y: 478.06745555320447 },
+ { x: 548.6819482467496, y: 461.695585816924 },
+ { x: 365.96206924856426, y: 630.9339981103036 },
+ { x: 451.83117451774604, y: 526.7430517262002 },
+ { x: 582.9047987575588, y: 441.7270782296887 },
+ { x: 490.1154498735479, y: 470.3281517148312 },
+ { x: 568.5804831067309, y: 387.047772708126 },
+ { x: 527.8016213850061, y: 562.1950823947911 },
+ { x: 594.1015443098378, y: 337.93072606735956 },
+ { x: 555.5989560907806, y: 537.4437215015128 },
+ { x: 580.9987804144716, y: 463.2444991669335 },
+ { x: 477.27812500864, y: 330.1821728794277 },
+ { x: 455.19945269488227, y: 466.0972226219533 },
+ { x: 386.3417341088935, y: 546.3536179523271 },
+ { x: 584.8508647220001, y: 392.5069023856318 },
+ { x: 535.8972955474309, y: 696.3119700836784 },
+ { x: 512.9478392541178, y: 482.09725884941054 },
+ { x: 571.0613169345261, y: 464.34405150243276 },
+ { x: 470.6582205422228, y: 519.5389288284686 },
+ { x: 449.7694170242311, y: 505.24775677432825 },
+ { x: 683.9417472319734, y: 484.3055678544799 },
+ { x: 399.9690260081697, y: 462.7083437169307 },
+ { x: 422.23721102436, y: 420.06321731733163 },
+ { x: 581.345766056873, y: 487.92889191966316 },
+ { x: 554.100245870134, y: 565.8172078613276 },
+ { x: 505.13988899871686, y: 422.13783709435006 },
+ { x: 444.44564391627125, y: 614.4513946455538 },
+ { x: 555.4208682592542, y: 514.9642299490376 },
+ { x: 525.3575027671648, y: 638.7096468709976 },
+ { x: 642.4821701257605, y: 373.74653262524174 },
+ { x: 549.9310129270682, y: 561.5262407400992 },
+ { x: 447.47329403586537, y: 531.1244276186567 },
+ { x: 476.8324194381892, y: 410.33393506104676 },
+ { x: 575.7235073554772, y: 587.7757570293226 },
+ { x: 471.11638968979366, y: 462.0653350713422 },
+ { x: 328.4426511281772, y: 382.8001294365678 },
+ { x: 557.4322151802324, y: 443.66976714351756 },
+ { x: 496.1747133116625, y: 522.8794856209539 },
+ { x: 617.9400379064762, y: 410.0130373860505 },
+ { x: 579.9678359562813, y: 511.78927778940346 },
+ { x: 580.4222256110895, y: 613.7007095833778 },
+ { x: 436.9971117313209, y: 549.8372182683136 },
+ { x: 460.0700469187102, y: 582.8430247311647 },
+ { x: 480.52549453979293, y: 550.594907124837 },
+ { x: 515.341309859586, y: 567.6904514175418 },
+ { x: 538.6951183924688, y: 407.1147758938117 },
+ { x: 544.6472783176636, y: 491.5738875685816 },
+ { x: 474.00451946290184, y: 626.1721256734905 },
+ { x: 653.1140314069249, y: 400.2304072268236 },
+ { x: 511.73184324070036, y: 424.28323696534335 },
+ { x: 456.44354384934513, y: 477.8974107043491 },
+ { x: 423.45562970783953, y: 638.0722701840896 },
+ { x: 538.6722409588642, y: 577.8492543631795 },
+ { x: 552.285508281345, y: 639.7372772829785 },
+ { x: 431.2719669756501, y: 453.1243606007722 },
+ { x: 523.9425957012721, y: 372.2471731027439 },
+ { x: 392.3939587773916, y: 420.07727210254455 },
+ { x: 352.1114149859869, y: 469.21118635606257 },
+ { x: 635.7528185124794, y: 620.1989579096139 },
+ { x: 593.6125931108892, y: 459.9032036799006 },
+ { x: 503.5400803792138, y: 352.49031571814436 },
+ { x: 483.48001318735584, y: 479.62460053432426 },
+ { x: 601.9800728341045, y: 307.1425177552605 },
+ { x: 578.5677625802014, y: 502.1555703035992 },
+ { x: 602.5469886960171, y: 516.333334149335 },
+ { x: 460.3465936399615, y: 567.5426824020806 },
+ { x: 393.3737638765459, y: 480.7465586106084 },
+ { x: 438.0492489114101, y: 362.2558547966672 },
+ { x: 490.6796053702311, y: 478.768186414496 },
+ { x: 455.8689956517157, y: 621.5002627201064 },
+ { x: 334.08514798711894, y: 438.93957781858506 },
+ { x: 617.8142646217834, y: 425.81364059915313 },
+ { x: 517.6228411262042, y: 595.7137334519729 },
+ { x: 485.0211805787605, y: 493.7670485854333 },
+ { x: 632.1068907973962, y: 340.12637634726786 },
+ { x: 373.08536359019575, y: 436.84967620421435 },
+ { x: 571.7972870271606, y: 416.1407836546993 },
+ { x: 455.2439418589584, y: 527.8137064425014 },
+ { x: 568.2591586640109, y: 468.89290450025425 },
+ { x: 646.0951604100743, y: 619.0023202878414 },
+ { x: 525.7933364638385, y: 484.9304070162185 },
+ { x: 551.798208313961, y: 506.7644521623696 },
+ { x: 450.2687336586831, y: 432.86783128016134 },
+ { x: 615.387878171927, y: 385.30066721027083 },
+ { x: 685.3415524104987, y: 483.4261028710347 },
+ { x: 449.4380469787378, y: 453.9673974793254 },
+ { x: 459.35595625269224, y: 402.4088030590528 },
+ { x: 432.6683081970933, y: 532.714904941048 },
+ { x: 440.198809949004, y: 529.3972675961419 },
+ { x: 524.455332680169, y: 446.8012248573339 },
+ { x: 526.7779076436276, y: 545.9378574755532 },
+ { x: 487.6965590409482, y: 438.33168175944235 },
+ { x: 491.7632854808359, y: 482.8846291486513 },
+ { x: 425.1777518325213, y: 582.9981238510991 },
+ { x: 463.83546978762797, y: 524.8442485549573 },
+ { x: 446.1166326000618, y: 375.5129553875806 },
+ { x: 462.05985483222184, y: 425.7411657585834 },
+ { x: 509.38855607395084, y: 492.5197179261496 },
+ { x: 430.3716067606543, y: 489.8533495682002 },
+ { x: 567.1856573423005, y: 591.0413109040437 },
+ { x: 334.82429044210573, y: 588.5349104568045 },
+ { x: 485.81202023070676, y: 574.1336636730789 },
+ { x: 473.0625078729557, y: 404.59284529710044 },
+ { x: 397.56420056369313, y: 362.22593941843274 },
+ { x: 512.4764092378841, y: 505.58088704757864 },
+ { x: 525.7379615435485, y: 528.6587672008093 },
+ { x: 572.5849585805538, y: 571.5219640354177 },
+ { x: 540.5339138507446, y: 563.7998022109335 },
+ { x: 409.2640666613289, y: 585.3775671701603 },
+ { x: 650.4025093038628, y: 444.03216972840227 },
+ { x: 473.80902730536263, y: 566.7155838133515 },
+ { x: 513.8689311941118, y: 641.2430867672864 },
+ { x: 480.4402194180348, y: 563.569450018222 },
+ { x: 465.7598266968873, y: 600.2194339533771 },
+ { x: 571.6678089928896, y: 507.5762669806091 },
+ { x: 496.13676037737116, y: 606.3637787758283 },
+ { x: 521.2509165821102, y: 356.6429291913573 },
+ { x: 477.1709109812602, y: 388.2170309481666 },
+ { x: 527.2901276344268, y: 545.5119540355945 },
+ { x: 530.7808677563178, y: 498.0853931712235 },
+ { x: 362.85297775758477, y: 376.4726957570216 },
+ { x: 604.8869090289303, y: 425.0279095021462 },
+ { x: 427.33328030577565, y: 602.2201737873148 },
+ { x: 490.45102513393533, y: 566.2346149157177 },
+ { x: 541.8127264575502, y: 564.4266795531707 },
+ { x: 422.325293295152, y: 599.8949607446589 },
+ { x: 471.6439623937621, y: 598.7909059873555 },
+ { x: 422.4982126609701, y: 536.9324749345669 },
+ { x: 540.0620003657338, y: 268.23722383346774 },
+ { x: 606.9306507865085, y: 440.36818129349916 },
+ { x: 535.9334606305631, y: 451.5978560682063 },
+ { x: 440.8281660355861, y: 497.3755369447025 },
+ { x: 364.5246826344751, y: 515.0694961266424 },
+ { x: 521.1908508917573, y: 479.6191000481474 },
+ { x: 442.3971251211775, y: 523.4672048121915 },
+ { x: 378.67831985241435, y: 600.5969420408649 },
+ { x: 516.5444197083655, y: 382.086617834092 },
+ { x: 611.1506512203224, y: 511.84686968837303 },
+ { x: 572.1600605873382, y: 559.0911496727878 },
+ { x: 355.7854975427032, y: 621.5310191309977 },
+ { x: 392.8909084134274, y: 429.44168910888624 },
+ { x: 566.1184394847702, y: 450.9517793776791 },
+ { x: 563.7852413572524, y: 398.0539864806101 },
+ { x: 571.5396768746826, y: 479.5347921109074 },
+ { x: 512.2249461606531, y: 535.6499899191176 },
+ { x: 563.4956579912108, y: 376.96931869615565 },
+ { x: 446.7971370342799, y: 469.79534247840456 },
+ { x: 395.230246518984, y: 324.8683329129203 },
+ { x: 500.27216494252224, y: 670.0041679383955 },
+ { x: 502.8298481412807, y: 381.9185623470128 },
+ { x: 438.2257985269379, y: 489.68260789180533 },
+ { x: 645.3300024449725, y: 479.75618737749863 },
+ { x: 415.91417101310475, y: 524.468344625876 },
+ { x: 478.7204998403519, y: 404.1512985659799 },
+ { x: 528.1510525044142, y: 574.4391188361618 },
+ { x: 417.2504976065919, y: 399.61027551582197 },
+ { x: 729.3227346599622, y: 459.7219096608828 },
+ { x: 508.04825319504647, y: 435.96885131963074 },
+ { x: 535.3871385799482, y: 438.1204565219904 },
+ { x: 620.2278888140053, y: 472.0920707987642 },
+ { x: 579.0737526156757, y: 512.6691282439778 },
+ { x: 563.6624155645421, y: 419.49058104290947 },
+ { x: 546.4058085812471, y: 484.973113905057 },
+ { x: 476.102132127935, y: 590.4734644345191 },
+ { x: 420.3951944583191, y: 422.96613357737476 },
+ { x: 395.5834671794034, y: 451.1057461648372 },
+ { x: 605.2924224272138, y: 632.7862602693494 },
+ { x: 320.5792318004338, y: 476.14475476682173 },
+ { x: 555.8842990108643, y: 467.0922505172094 },
+ { x: 511.752823321972, y: 497.1301987728249 },
+ { x: 627.4985443664052, y: 517.403661641187 },
+ { x: 460.467208488182, y: 442.9907522160578 },
+ { x: 325.1143775978037, y: 548.0102903590863 },
+ { x: 595.9132884053315, y: 536.4710325712115 },
+ { x: 333.9634887245654, y: 565.7690181076008 },
+ { x: 460.8070944510852, y: 542.5193469631959 },
+ { x: 569.3099243101011, y: 596.7679504034089 },
+ { x: 599.7622962192024, y: 587.7817140731728 },
+ { x: 605.2333628956932, y: 555.3397707369844 },
+ { x: 525.8541534950963, y: 591.9753384309636 },
+ { x: 562.2873883086985, y: 564.652245971429 },
+ { x: 593.125622789125, y: 646.5095121577685 },
+ { x: 528.3785696014553, y: 561.4319954581767 },
+ { x: 562.0235111049607, y: 540.0388583697173 },
+ { x: 479.98352971788245, y: 635.2537373804788 },
+ { x: 683.8163873885301, y: 540.7453259112881 },
+ { x: 341.3216916961063, y: 595.4480897965195 },
+ { x: 629.774897110141, y: 457.30992723206396 },
+ { x: 588.4621952936112, y: 463.3201846926253 },
+ { x: 539.2519782005975, y: 556.9254479421566 },
+ { x: 558.9462354769668, y: 377.9598567889521 },
+ { x: 475.25962872517897, y: 530.6505314391079 },
+ { x: 471.0898586517417, y: 607.8657439408781 },
+ { x: 405.442863418894, y: 426.63192933023663 },
+ { x: 392.277064629337, y: 508.8293609444394 },
+ { x: 563.2801972811317, y: 485.0617688947425 },
+ { x: 514.6740362301042, y: 585.456678967984 },
+ { x: 626.1445241914307, y: 434.871906309453 },
+ { x: 582.0767593537491, y: 540.7074363276917 },
+ { x: 497.66009983657636, y: 610.1909037598729 },
+ { x: 564.2139016856188, y: 573.279828843626 },
+ { x: 492.7070636593087, y: 473.3696763176616 },
+ { x: 412.1042520726131, y: 414.1932802334767 },
+ { x: 397.81463173567744, y: 608.3857394528636 },
+ { x: 529.3125325134371, y: 479.05279623435155 },
+ { x: 454.8440542817299, y: 570.8848201200701 },
+ { x: 481.99948008383234, y: 537.8984252824558 },
+ { x: 466.8233381140212, y: 614.6915748364435 },
+ { x: 529.1781259757561, y: 334.91840002589186 },
+ { x: 543.2267950376435, y: 527.2277199561922 },
+ { x: 681.0809685850758, y: 537.8042119742028 },
+ { x: 538.1749829502172, y: 390.39152308688665 },
+ { x: 486.6511639358574, y: 416.9544506386641 },
+ { x: 443.83948781249495, y: 641.4184344680891 },
+ { x: 562.9226042462709, y: 519.5118875679203 },
+ { x: 506.46394119892096, y: 422.88205256983366 },
+ { x: 585.7224010988533, y: 533.9082046729562 },
+ { x: 502.5521934638452, y: 607.6406346361509 },
+ { x: 388.7608548379816, y: 538.6793511958092 },
+ { x: 482.20369081623204, y: 506.6072228769318 },
+ { x: 531.5382726990536, y: 540.7390134393922 },
+ { x: 530.4605595177179, y: 594.337437433271 },
+ { x: 404.5134426298756, y: 429.75753802189973 },
+ { x: 492.2817855909661, y: 641.7841340715981 },
+ { x: 492.92254183696446, y: 563.6496221559248 },
+ { x: 442.6597057370762, y: 611.5223059556535 },
+ { x: 586.2417798862663, y: 418.6846916743144 },
+ { x: 493.70099652719534, y: 481.72199336724117 },
+ { x: 493.85710451631473, y: 595.8640897481832 },
+ { x: 501.1561516589185, y: 682.6908577462624 },
+ { x: 503.21578694316713, y: 519.0042987301437 },
+ { x: 507.73638975422, y: 626.510954750474 },
+ { x: 561.257261808792, y: 372.01845192963395 },
+ { x: 397.10268820590676, y: 515.7095266083511 },
+ { x: 395.1118909987129, y: 604.7286849328888 },
+ { x: 520.594740801459, y: 612.0673519411307 },
+ { x: 528.7289951158066, y: 397.9974262738962 },
+ { x: 536.6540363477791, y: 675.8725538797256 },
+ { x: 460.67581059101013, y: 578.7585018112575 },
+ { x: 613.9773683350654, y: 593.2583222013895 },
+ { x: 576.1191477958195, y: 516.5062965966378 },
+ { x: 585.9270905859661, y: 461.1538384040178 },
+ { x: 507.27837302060124, y: 529.8271375050829 },
+ { x: 408.1380593516653, y: 531.7133203675004 },
+ { x: 509.6012918287131, y: 371.3856594428655 },
+ { x: 409.35168667225224, y: 652.1061274713718 },
+ { x: 650.3279443256315, y: 521.0288033630213 },
+ { x: 407.1543118176588, y: 476.3879001917622 },
+ { x: 448.04147797243064, y: 568.792572513917 },
+ { x: 482.1862287056724, y: 672.2401592844891 },
+ { x: 332.02192200168486, y: 527.7703858055057 },
+ { x: 445.14386811395195, y: 482.37902220353334 },
+ { x: 440.83958774212545, y: 566.3770123545485 },
+ { x: 441.0182157184419, y: 523.7864876933295 },
+ { x: 505.1306979178894, y: 448.27874697316435 },
+ { x: 635.2031822731875, y: 478.9591453315155 },
+ { x: 532.5647240362346, y: 480.9144298512188 },
+ { x: 564.78132689951, y: 459.50075171562634 },
+ { x: 510.5135065996153, y: 520.1460158111068 },
+ { x: 483.87169516795325, y: 502.55005940468936 },
+ { x: 489.71411208699914, y: 520.8043235308375 },
+ { x: 440.79310406732407, y: 632.6819215982563 },
+ { x: 575.613422290649, y: 527.1345152282136 },
+ { x: 371.65949856961674, y: 557.9193680352147 },
+ { x: 448.9901943773482, y: 435.83599599218064 },
+ { x: 468.4040031546869, y: 458.8117296694587 },
+ { x: 424.1970242776248, y: 510.32903634995967 },
+ { x: 484.34423672681424, y: 329.3501756062952 },
+ { x: 396.12098238521725, y: 454.7867268028899 },
+ { x: 482.15966373561196, y: 495.7719744924583 },
+ { x: 503.1013867575087, y: 465.17657265982143 },
+ { x: 579.3035167692143, y: 363.46890350087807 },
+ { x: 539.3866713816002, y: 572.4550076678007 },
+ { x: 431.8489752404569, y: 557.7551024181017 },
+ { x: 728.4311010185129, y: 550.7901847222113 },
+ { x: 446.9185583739578, y: 404.6990098189804 },
+ { x: 556.3918962349734, y: 532.2925839339954 },
+ { x: 455.6004334910393, y: 555.073396463379 },
+ { x: 581.9122319577673, y: 555.9284731777594 },
+ { x: 429.1288672401044, y: 272.374518122646 },
+ { x: 542.5017712518866, y: 426.23077220743687 },
+ { x: 512.905253520108, y: 432.54817615160937 },
+ { x: 512.9172843348791, y: 506.01867425344483 },
+ { x: 454.91866293404667, y: 409.89812111287847 },
+ { x: 468.3343580810703, y: 473.084169194802 },
+ { x: 450.4819775082967, y: 503.08977783251584 },
+ { x: 450.739854845646, y: 524.824030718596 },
+ { x: 390.60042716092374, y: 487.99373226125834 },
+ { x: 392.6812000840405, y: 509.10463662250027 },
+ { x: 560.011654158543, y: 495.0924827676309 },
+ { x: 559.044572540643, y: 507.9525128241118 },
+ { x: 495.46702543672103, y: 503.0671526647668 },
+ { x: 513.1155355859919, y: 519.9889037862815 },
+ { x: 676.0539182941292, y: 424.86003336682506 },
+ { x: 491.72974264632586, y: 418.53343303963567 },
+ { x: 475.0936001100203, y: 446.41446990645437 },
+ { x: 589.9217358966552, y: 599.9006125154442 },
+ { x: 274.2196156246059, y: 626.589821531672 },
+ { x: 510.57488768480965, y: 430.7175620295051 },
+ { x: 407.6368010440314, y: 566.7226098608865 },
+ { x: 540.0608765923658, y: 402.8387189155337 },
+ { x: 476.49582172946845, y: 471.60797138053886 },
+ { x: 515.4826979645305, y: 366.3775120267172 },
+ { x: 420.90946350957563, y: 419.6217163626932 },
+ { x: 497.59193206509207, y: 449.4790202845697 },
+ { x: 413.96569929054135, y: 461.20456866211146 },
+ { x: 565.1460622770901, y: 510.21213053948804 },
+ { x: 496.7722587685551, y: 505.62896979322153 },
+ { x: 353.00812977813416, y: 567.3486673635567 },
+ { x: 637.2774513599962, y: 501.68414228689255 },
+ { x: 482.12984548936913, y: 454.3857295184553 },
+ { x: 563.889911381031, y: 440.1785558353954 },
+ { x: 545.0890188911553, y: 440.5289165562692 },
+ { x: 436.8073122426593, y: 619.2078751568192 },
+ { x: 605.5423387306544, y: 580.0784922449934 },
+ { x: 469.532669128929, y: 560.3442589934073 },
+ { x: 447.15116336620224, y: 478.03341754496876 },
+ { x: 515.5808008719257, y: 474.29372966281954 },
+ { x: 537.2366271808814, y: 537.9233316948031 },
+ { x: 315.9081540623598, y: 513.9677921359835 },
+ { x: 443.94087269470737, y: 253.68633480784766 },
+ { x: 525.0082453645023, y: 480.17496256937545 },
+ { x: 669.0631209450423, y: 541.4800047046759 },
+ { x: 424.9052661293348, y: 502.3414033711398 },
+ { x: 552.1617004849156, y: 487.5064843356538 },
+ { x: 512.9457421710656, y: 469.50808704275704 },
+ { x: 426.0515832085964, y: 572.9729217614308 },
+ { x: 478.12849609656286, y: 511.7360377798443 },
+ { x: 450.66402500188485, y: 331.27206240599696 },
+ { x: 414.6608994844545, y: 499.30032678644767 },
+ { x: 575.0072111226609, y: 581.9201899181702 },
+ { x: 461.1966182161947, y: 404.4640019083771 },
+ { x: 609.571694657682, y: 323.578409113701 },
+ { x: 434.07767841386516, y: 421.10137540535686 },
+ { x: 450.9535739111606, y: 525.3654064812511 },
+ { x: 525.6474862235029, y: 568.9368700640288 },
+ { x: 553.1379037972506, y: 612.587588659274 },
+ { x: 359.17679723870344, y: 478.7682358393113 },
+ { x: 463.5822016824479, y: 623.0900498251482 },
+ { x: 465.3323639241772, y: 456.367519217294 },
+ { x: 494.5755802914467, y: 551.5978034376832 },
+ { x: 624.7123300555137, y: 461.284442188934 },
+ { x: 550.2962679721757, y: 499.42672874803145 },
+ { x: 438.12895348590257, y: 593.3772231688772 },
+ { x: 493.7608422309046, y: 330.30961695869695 },
+ { x: 531.8208873228848, y: 557.5440696035282 },
+ { x: 514.1709464364438, y: 507.80868309761416 },
+ { x: 572.1098849132386, y: 506.6787891425146 },
+ { x: 534.0219889823662, y: 622.0169784812482 },
+ { x: 495.89140537808925, y: 517.0277491339862 },
+ { x: 550.4324691320285, y: 447.79648292442346 },
+ { x: 485.2682752550611, y: 343.5658914789321 },
+ { x: 443.24152110168825, y: 571.3359051310853 },
+ { x: 579.8773770712485, y: 456.3990989591147 },
+ { x: 518.0496258697879, y: 542.9899596474276 },
+ { x: 451.3719054594958, y: 513.6369281635617 },
+ { x: 509.1998923664028, y: 561.5556571742668 },
+ { x: 573.6037166985305, y: 483.6698252156604 },
+ { x: 490.9309965170419, y: 526.3404257937894 },
+ { x: 433.25360875802414, y: 464.4060911149918 },
+ { x: 420.4438713331765, y: 670.7340190547727 },
+ { x: 500.5869744603166, y: 505.02722084133694 },
+ { x: 581.4556003253261, y: 359.19624918002245 },
+ { x: 531.9339179738793, y: 639.5378342741336 },
+ { x: 451.2828535475956, y: 506.96641652703215 },
+ { x: 493.1648265346956, y: 484.304860601236 },
+ { x: 264.6167885698519, y: 618.5760529915333 },
+ { x: 444.4004898238353, y: 540.7566233371936 },
+ { x: 480.0192560494728, y: 577.562460628525 },
+ { x: 509.3496583929782, y: 642.0933343662082 },
+ { x: 534.2052141706351, y: 608.9685984048267 },
+ { x: 546.4385711619324, y: 493.491794946789 },
+ { x: 455.0166830608425, y: 376.4039902841645 },
+ { x: 428.26873852661663, y: 526.1917688075115 },
+ { x: 522.31442872344, y: 510.29854398094125 },
+ { x: 382.869569099349, y: 516.7275853977133 },
+ { x: 449.47629384380804, y: 412.5598074646182 },
+ { x: 466.3272305981255, y: 437.77647898413704 },
+ { x: 494.33730410416115, y: 569.2466741795388 },
+ { x: 570.850678721421, y: 406.8634359301221 },
+ { x: 435.86283340726897, y: 558.2099552577272 },
+ { x: 572.8617731777421, y: 523.2505269638182 },
+ { x: 764.1526383538614, y: 300.7431778693811 },
+ { x: 469.74351310035433, y: 496.6583454640491 },
+ { x: 686.4382908323215, y: 439.5344033900257 },
+ { x: 392.61085580273783, y: 520.599429489737 },
+ { x: 486.41559809454736, y: 457.95394654283683 },
+ { x: 683.483802887262, y: 525.9324975560189 },
+ { x: 604.2691827769518, y: 610.6899986402096 },
+ { x: 439.31494789718226, y: 608.0045489176407 },
+ { x: 463.914110162254, y: 435.25614989350134 },
+ { x: 477.2516239569152, y: 540.1401392177487 },
+ { x: 637.343604281198, y: 477.70219847495895 },
+ { x: 553.2977253182025, y: 524.002780960052 },
+ { x: 405.84549279887545, y: 427.5863025761163 },
+ { x: 584.2180781886257, y: 565.7475859789315 },
+ { x: 537.4779996510825, y: 483.4938547437982 },
+ { x: 410.37004037611405, y: 404.9227164465485 },
+ { x: 387.211403529204, y: 482.4726749975946 },
+ { x: 372.92765669888036, y: 607.2207729060416 },
+ { x: 388.3214843041369, y: 557.9819729419087 },
+ { x: 473.5828176772773, y: 646.0346174053482 },
+ { x: 455.8395825873313, y: 560.3714801149157 },
+ { x: 650.2344980015788, y: 509.49597270176884 },
+ { x: 560.0399104379837, y: 521.6781418624263 },
+ { x: 687.1787226172372, y: 435.6658338749941 },
+ { x: 567.1127544956692, y: 531.1822196480132 },
+ { x: 452.9559992774003, y: 583.8380290107248 },
+];
+
+const stories = storiesOf('Wrectangle', module);
+stories.addDecorator(withKnobs);
+stories.add('分箱图', () =>
);
+
+const data1 = [];
+class NewData extends React.Component {
+ state = {
+ data: defaultData.slice(0,200)
+ }
+
+ componentDidMount() {
+ setInterval(() => {
+ let t = Date.now();
+
+ this.setState({
+ data: defaultData.slice(0, Math.round(Math.random() * 500)),
+ })
+ }, 2000);
+ }
+
+ render(){
+ return (
+
+
+
+ );
+ }
+}
+stories.add('动态数据', () => (
+
+));
diff --git a/stories/chart.sankey.stories.js b/stories/chart.sankey.stories.js
index 8ec0a360..a51a8836 100644
--- a/stories/chart.sankey.stories.js
+++ b/stories/chart.sankey.stories.js
@@ -9,7 +9,9 @@ import { Wsankey, Wcontainer } from '@alicloud/cloud-charts';
const stories = storiesOf('Wsankey', module);
stories.add('基础桑基图', () => (
- (
+
+
+
+));
+
+const data2 = [
+ {
+ name: '团队1',
+ data: [
+ ['A', 35],
+ ['A', 10],
+ ['B', 32],
+ ['A', 7],
+ ['C', 32],
+ ['B', 23],
+ ['A', 80],
+ ['C', 33],
+ ['A', 11],
+ ['A', 32],
+ ['B', 24],
+ ['B', 72],
+ ['C', 14],
+ ['A', 42]
+ ]
+ },
+ {
+ name: '团队2',
+ data: [
+ ['A', 54],
+ ['A', 10],
+ ['B', 24],
+ ['B', 72],
+ ['C', 14],
+ ['A', 42],
+ ['B', 32],
+ ['A', 7],
+ ['C', 32],
+ ['B', 23],
+ ['A', 24],
+ ['C', 33],
+ ['A', 11],
+ ['A', 32]
+ ]
+ },
+ {
+ name: '团队3',
+ data: [
+ ['A', 31],
+ ['A', 10],
+ ['A', 11],
+ ['A', 32],
+ ['B', 24],
+ ['B', 32],
+ ['A', 7],
+ ['C', 32],
+ ['B', 23],
+ ['A', 43],
+ ['C', 33],
+ ['B', 72],
+ ['C', 14],
+ ['A', 42]
+ ]
+ }
+];
+
+stories.add('扰动点图', () => (
+
+
+
+));
+
diff --git a/stories/feat.autoTickCount.stories.js b/stories/feat.autoTickCount.stories.js
index 2de9ceef..33df203a 100644
--- a/stories/feat.autoTickCount.stories.js
+++ b/stories/feat.autoTickCount.stories.js
@@ -8,23 +8,46 @@ import { Wcontainer, Wline } from '@alicloud/cloud-charts';
const data = [
{
- "name":"机房A",
- "data":[[1483372800000,4092],[1483459200000,1592],[1483545600000,3714],[1483632000000,4854],[1483718400000,6514],[1483804800000,9022],[1483891200000,6023],[1483977600000,4018]]
- }, {
- "name":"机房B",
- "yAxis": 1,
- "data":[[1483372800000,6051],[1483459200000,3278],[1483545600000,5175],[1483632000000,6548],[1483718400000,9048],[1483804800000,11394],[1483891200000,8597],[1483977600000,6588]]
- }
+ "name":"曲线1",
+ "data":[]
+ },
+ {
+ "name":"曲线2",
+ "data":[]
+ },
+ {
+ "name":"曲线3",
+ yAxis: 1,
+ "data":[]
+ },
+ {
+ "name":"曲线4",
+ yAxis: 1,
+ "data":[]
+ },
];
+for (let i = 0; i < 24; i++) {
+ const time = `2020-01-01 ${i}:00:00`;
+ data[0].data.push([time, Math.round(Math.random() * 100 + 800)]);
+ data[1].data.push([time, Math.round(Math.random() * 100 + 600)]);
+ data[2].data.push([time, Math.round(Math.random() * 100 + 400)]);
+ data[3].data.push([time, Math.round(Math.random() * 100 + 200)]);
+}
+
const stories = storiesOf('autoTickCount', module);
stories.add('折线图', () => (
diff --git a/stories/feat.axis.stories.js b/stories/feat.axis.stories.js
new file mode 100644
index 00000000..3b5fe8e1
--- /dev/null
+++ b/stories/feat.axis.stories.js
@@ -0,0 +1,78 @@
+import React, { useEffect, useRef } from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { linkTo } from '@storybook/addon-links';
+import { withKnobs, select, radios } from "@storybook/addon-knobs";
+
+import { Wcontainer, Wline, Wlinebar } from '@alicloud/cloud-charts';
+
+const data = [
+ {
+ "name":"机房A",
+ "data":[[1483372800000,4092],[1483459200000,1592],[1483545600000,3714],[1483632000000,4854],[1483718400000,6514],[1483804800000,9022],[1483891200000,6023],[1483977600000,4018]]
+ }, {
+ "name":"机房B",
+ "yAxis": 1,
+ "data":[[1483372800000,6051],[1483459200000,3278],[1483545600000,5175],[1483632000000,6548],[1483718400000,9048],[1483804800000,11394],[1483891200000,8597],[1483977600000,6588]]
+ }
+];
+
+// const lineBarData = [
+// {
+// "name":"机房1",
+// type: 'bar',
+// "data":[[1483372800000,1892],[1483459200000,7292],[1483545600000,5714],[1483632000000,5354],[1483718400000,2014],[1483804800000,22],[1483891200000,11023],[1483977600000,5218],[1484064000000,8759],[1484150400000,9981],[1484236800000,4533],[1484323200000,11398],[1484409600000,1064],[1484496000000,6494]]
+// },
+// {
+// "name":"机房2",
+// type: 'bar',
+// "data":[[1483372800000,182],[1483459200000,792],[1483545600000,514],[1483632000000,554],[1483718400000,204],[1483804800000,22],[1483891200000,1023],[1483977600000,528],[1484064000000,879],[1484150400000,981],[1484236800000,453],[1484323200000,1198],[1484409600000,1064],[1484496000000,694]]
+// },
+// {
+// "name":"机房3",
+// type: 'line',
+// yAxis: 1,
+// "data":[[1483372800000,11751],[1483459200000,4078],[1483545600000,2175],[1483632000000,12048],[1483718400000,1748],[1483804800000,10494],[1483891200000,9597],[1483977600000,4788],[1484064000000,2085],[1484150400000,492],[1484236800000,2965],[1484323200000,4246],[1484409600000,2160],[1484496000000,11877]]
+// },
+// {
+// "name":"机房4",
+// type: 'line',
+// yAxis: 1,
+// "data":[[1483372800000,1151],[1483459200000,4778],[1483545600000,21175],[1483632000000,19048],[1483718400000,14748],[1483804800000,18494],[1483891200000,10597],[1483977600000,8788],[1484064000000,12985],[1484150400000,2492],[1484236800000,5965],[1484323200000,10246],[1484409600000,12160],[1484496000000,6877]]
+// }
+// ];
+
+
+const stories = storiesOf('axis', module);
+stories.addDecorator(withKnobs);
+stories.add('轴标题', () => (
+
+
+
+));
+
+stories.add('tickLine', () => (
+
+
+
+));
+
+// stories.add('图例位置测试-linebar', () => (
+//
+//
+//
+// ));
diff --git a/stories/feat.connect.stories.js b/stories/feat.connect.stories.js
new file mode 100644
index 00000000..59b43538
--- /dev/null
+++ b/stories/feat.connect.stories.js
@@ -0,0 +1,122 @@
+import React from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { linkTo } from '@storybook/addon-links';
+
+import { Wcontainer, Wline, Wbar, Util, Wscatter } from '@alicloud/cloud-charts';
+
+const lineData = [
+ {
+ name: '机房A',
+ data: [
+ [1483372800000, 1592],
+ [1483459200000, 4092],
+ [1483545600000, 3714],
+ [1483632000000, 3984],
+ [1483718400000, 6514],
+ [1483804800000, 6666],
+ [1483891200000, 6023],
+ [1483977600000, 4018]
+ ]
+ },
+ {
+ name: '机房B',
+ data: [
+ [1483372800000, 3592],
+ [1483459200000, 6092],
+ [1483545600000, 5714],
+ [1483632000000, 5984],
+ [1483718400000, 8514],
+ [1483804800000, 8666],
+ [1483891200000, 8023],
+ [1483977600000, 6018]
+ ]
+ }
+];
+
+const barData = [
+ {
+ name: '柱1',
+ data: [
+ ['一', 59],
+ ['二', 23],
+ ['三', 19],
+ ['四', 27],
+ ['五', 77],
+ ['六', 100],
+ ['七', 70],
+ ['八', 61],
+ ['九', 15],
+ ],
+ },
+ {
+ name: '柱2',
+ data: [
+ ['一', 92],
+ ['二', 15],
+ ['三', 4],
+ ['四', 49],
+ ['五', 64],
+ ['六', 76],
+ ['七', 21],
+ ['八', 100],
+ ['九', 71],
+ ],
+ },
+];
+
+const stories = storiesOf('connect', module);
+
+class ConnectDemo extends React.Component{
+ chart1 = null;
+ chart2 = null;
+ chart3 = null;
+ componentDidMount() {
+ new Util.Connect([this.chart1, this.chart2], {
+ custom(e, target, source) {
+ console.log(e, target)
+ target.showTooltip({ x: e.x, y: e.y });
+ }
+ });
+ }
+ render(){
+ return (
+
+ (this.chart1 = c)} config={{}} data={lineData}/>
+ (this.chart2 = c)} config={{}} data={barData}/>
+ (this.chart3 = c)} config={{}} data={lineData}/>
+
+ );
+ }
+}
+stories.add('线柱联动', () => (
+
+));
+
+class ConnectDataDemo extends React.Component{
+ chart1 = null;
+ chart2 = null;
+ chart3 = null;
+ componentDidMount() {
+ new Util.Connect([this.chart1, this.chart2, this.chart3], {
+ type: 'data',
+ });
+ }
+ render(){
+ return (
+
+ (this.chart1 = c)} config={{
+ padding: [40, 400, 24, 40],
+ }} data={lineData}/>
+ (this.chart2 = c)} config={{}} data={barData}/>
+ (this.chart3 = c)} config={{
+ padding: [40, 10, 24, 400],
+ }} data={lineData}/>
+
+ );
+ }
+}
+stories.add('按数据联动', () => (
+
+));
diff --git a/stories/feat.legend.stories.js b/stories/feat.legend.stories.js
index 4e084f42..ccec9d11 100644
--- a/stories/feat.legend.stories.js
+++ b/stories/feat.legend.stories.js
@@ -3,8 +3,9 @@ import React, { useEffect, useRef } from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
+import { withKnobs, select, radios } from "@storybook/addon-knobs";
-import { Wcontainer, Wline, Wlinebar } from '@alicloud/cloud-charts';
+import { Wcontainer, Wline, Wlinebar, Wpie } from '@alicloud/cloud-charts';
const data = [
{
@@ -42,53 +43,129 @@ const lineBarData = [
}
];
+
const stories = storiesOf('legend', module);
-const handleClick = action('onClick');
-stories.add('config.legend.onClick', () => (
+stories.addDecorator(withKnobs);
+// const handleClick = action('onClick');
+// stories.add('config.legend.onClick', () => (
+//
+// {
+// // handleClick('config.legend.onClick', e);
+// // },
+// }
+// }} data={data} />
+//
+// ));
+//
+// function LineLegendClick() {
+// const chart = useRef();
+// useEffect(() => {
+// if (chart.current) {
+// const legend = chart.current.get('legendController').legends['top-center'][0];
+// legend && legend.on('itemclick', handleClick);
+// }
+// }, []);
+// return (
+//
+// (chart.current = c)} height="300" data={data} />
+//
+// );
+// }
+// stories.add('线图图例点击', () => (
+//
+// ));
+//
+// function LineBarLegendClick() {
+// const chart = useRef();
+// useEffect(() => {
+// if (chart.current) {
+// const legends = chart.current.get('legendController').legends['top-center'];
+// legends[0] && legends[0].on('itemclick', handleClick);
+// legends[1] && legends[1].on('itemclick', handleClick);
+// }
+// }, []);
+// return (
+//
+// (chart.current = c)} height="300" data={lineBarData} />
+//
+// );
+// }
+// stories.add('线柱图图例点击', () => (
+//
+// ));
+
+
+const positionOptions = {
+ '顶部': 'top',
+ '底部': 'bottom',
+};
+const alignOptions = {
+ '左': 'left',
+ '中': 'center',
+ '右': 'right',
+};
+const radioOptions = {
+ '上左': 'top-left',
+ '上中': 'top',
+ '上右': 'top-right',
+ '下左': 'bottom-left',
+ '下中': 'bottom',
+ '下右': 'bottom-right',
+ '左上': 'left-top',
+ '左中': 'left',
+ '左下': 'left-bottom',
+ '右上': 'right-top',
+ '右中': 'right',
+ '右下': 'right-bottom',
+};
+stories.add('图例位置测试-line', () => (
{
- handleClick('config.legend.onClick', e);
- },
+ // position: select('上下位置', positionOptions, 'top'),
+ // align: select('左右分布', alignOptions, 'left'),
+ position: radios('位置', radioOptions, 'top'),
+ align: '',
}
}} data={data} />
));
-function LineLegendClick() {
- const chart = useRef();
- useEffect(() => {
- if (chart.current) {
- const legend = chart.current.get('legendController').legends['top-center'][0];
- legend && legend.on('itemclick', handleClick);
- }
- }, []);
- return (
-
- (chart.current = c)} height="300" data={data} />
-
- );
-}
-stories.add('线图图例点击', () => (
-
+stories.add('图例位置测试-linebar', () => (
+
+
+
));
-function LineBarLegendClick() {
- const chart = useRef();
- useEffect(() => {
- if (chart.current) {
- const legends = chart.current.get('legendController').legends['top-center'];
- legends[0] && legends[0].on('itemclick', handleClick);
- legends[1] && legends[1].on('itemclick', handleClick);
- }
- }, []);
- return (
-
- (chart.current = c)} height="300" data={lineBarData} />
-
- );
-}
-stories.add('线柱图图例点击', () => (
-
+const pieData = [
+ {
+ "name": "浏览器占比",
+ "data": [
+ ['Firefox', 45.0],
+ ['IE', 26.8],
+ ['Chrome', 12.8],
+ ['Safari', 8.5],
+ ['Opera', 6.2],
+ ['Others', 0.7]
+ ]
+ }
+];
+stories.add('图例位置测试-pie', () => (
+
+
+
));
diff --git a/stories/feat.theme.stories.js b/stories/feat.theme.stories.js
index 0ba3c168..3391770f 100644
--- a/stories/feat.theme.stories.js
+++ b/stories/feat.theme.stories.js
@@ -2,9 +2,10 @@ import React, { useMemo, useRef } from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
-import { withKnobs, select } from "@storybook/addon-knobs";
+import { withKnobs, select, color } from "@storybook/addon-knobs";
import { themes, Wcontainer, Wline, Wbar, Wlinebar } from '@alicloud/cloud-charts';
+import { isContrastColorWhite } from '@antv/g2/esm/util/color';
const data = [
@@ -89,3 +90,13 @@ function ThemeDemo() {
stories.add('主题动态切换', () => (
));
+
+stories.add('亮暗颜色判断测试', () => {
+ const bg = color('背景色', '#fff')
+ const isDark = isContrastColorWhite(bg);
+ return (
+
+ isDark: {String(isDark)}
+
+ );
+});
diff --git a/stories/feat.tooltip.stories.js b/stories/feat.tooltip.stories.js
new file mode 100644
index 00000000..b027d9e6
--- /dev/null
+++ b/stories/feat.tooltip.stories.js
@@ -0,0 +1,67 @@
+import React, { useEffect, useRef } from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { linkTo } from '@storybook/addon-links';
+import { withKnobs, select, radios } from "@storybook/addon-knobs";
+
+import { Wcontainer, Wline, Wlinebar } from '@alicloud/cloud-charts';
+
+const data = [
+ {
+ "name":"数据项长名称",
+ "data":[[1483372800000,92],[1483459200000,92],[1483545600000,714]]
+ },
+ {
+ "name":"短名",
+ // "yAxis": 1,
+ "data":[[1483372800000,651],[1483459200000,278],[1483545600000,175]]
+ },
+ {
+ "name":"长数据值",
+ "yAxis": 1,
+ "data":[[1483372800000,206051],[1483459200000,193278],[1483545600000,305175]]
+ }
+];
+
+// const lineBarData = [
+// {
+// "name":"机房1",
+// type: 'bar',
+// "data":[[1483372800000,1892],[1483459200000,7292],[1483545600000,5714],[1483632000000,5354],[1483718400000,2014],[1483804800000,22],[1483891200000,11023],[1483977600000,5218],[1484064000000,8759],[1484150400000,9981],[1484236800000,4533],[1484323200000,11398],[1484409600000,1064],[1484496000000,6494]]
+// },
+// {
+// "name":"机房2",
+// type: 'bar',
+// "data":[[1483372800000,182],[1483459200000,792],[1483545600000,514],[1483632000000,554],[1483718400000,204],[1483804800000,22],[1483891200000,1023],[1483977600000,528],[1484064000000,879],[1484150400000,981],[1484236800000,453],[1484323200000,1198],[1484409600000,1064],[1484496000000,694]]
+// },
+// {
+// "name":"机房3",
+// type: 'line',
+// yAxis: 1,
+// "data":[[1483372800000,11751],[1483459200000,4078],[1483545600000,2175],[1483632000000,12048],[1483718400000,1748],[1483804800000,10494],[1483891200000,9597],[1483977600000,4788],[1484064000000,2085],[1484150400000,492],[1484236800000,2965],[1484323200000,4246],[1484409600000,2160],[1484496000000,11877]]
+// },
+// {
+// "name":"机房4",
+// type: 'line',
+// yAxis: 1,
+// "data":[[1483372800000,1151],[1483459200000,4778],[1483545600000,21175],[1483632000000,19048],[1483718400000,14748],[1483804800000,18494],[1483891200000,10597],[1483977600000,8788],[1484064000000,12985],[1484150400000,2492],[1484236800000,5965],[1484323200000,10246],[1484409600000,12160],[1484496000000,6877]]
+// }
+// ];
+
+
+const stories = storiesOf('tooltip', module);
+stories.addDecorator(withKnobs);
+stories.add('样式测试', () => (
+
+
+
+));
+
+// stories.add('图例位置测试-linebar', () => (
+//
+//
+//
+// ));
diff --git a/stories/plugin.worldmap.stories.js b/stories/plugin.worldmap.stories.js
index f731a5ac..4ffc5957 100644
--- a/stories/plugin.worldmap.stories.js
+++ b/stories/plugin.worldmap.stories.js
@@ -5,7 +5,7 @@ import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { Wcontainer, plugins } from '@alicloud/cloud-charts';
-import '@alicloud/cloud-charts/plugins/WorldMap/index';
+import '@alicloud/cloud-charts/plugins/worldmap/index';
const { WorldMap } = plugins;
const areaData = [
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..0eb69e9b
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compileOnSave": false,
+ "buildOnSave": false,
+ "compilerOptions": {
+ "outDir": "build",
+ "module": "esnext",
+ "target": "es6",
+ "jsx": "react",
+ "moduleResolution": "node",
+ "lib": ["es6", "dom"],
+ "sourceMap": true,
+ "allowJs": true,
+ "noUnusedLocals": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "skipLibCheck": true,
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["src/*.ts", "src/*.tsx"],
+ "exclude": ["node_modules", "build", "public"]
+}
diff --git a/webpack.config.js b/webpack.config.js
deleted file mode 100644
index e7fe449f..00000000
--- a/webpack.config.js
+++ /dev/null
@@ -1,315 +0,0 @@
-'use strict';
-
-/**
- * 说明: webpack的配置请在该文件进行修改
- * webpack配置文档请查看:https://webpack.github.io/docs/configuration.html
- */
-const MiniCssExtractPlugin = require('mini-css-extract-plugin');
-const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
-const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
-const path = require('path');
-const fs = require('fs');
-const _ = require('lodash');
-const webpack = require('webpack');
-const glob = require('glob');
-const FallbackPort = require('fallback-port');
-const packageInfo = require('./package');
-
-// 默认开启3000端口,若被占用,则开启其他端口
-const fallbackPort = new FallbackPort(9009);
-
-const componentName = 'CloudCharts';
-const srcPath = path.resolve(__dirname, './components');
-const demoPath = path.resolve(__dirname, './demo');
-const outputPath = path.resolve(__dirname, './build');
-const pluginPath = path.resolve(__dirname, './components/plugins');
-
-const config = {
- // 服务器开启的端口号
- port: fallbackPort.getPort(),
-
- context: srcPath,
-
- mode: 'development',
-
- // webpack 编译的入口文件
- entry: {
- index: ['./index.scss', './index.jsx'],
- },
-
- // 输出的文件配置
- output: {
- path: outputPath,
- filename: '[name].js',
- publicPath: '/build/',
- // 设置library 则可以直接通过 window.xxx 访问到
- library: componentName,
- libraryTarget: 'umd'
- },
-
- resolve: {
- modules: [srcPath, 'node_modules'],
- extensions: ['.js', '.jsx'],
- alias: {
- '@alicloud/cloud-charts': srcPath,
- '@alicloud/cloud-charts/lib': srcPath,
- '@antv/data-set$': path.resolve(__dirname, './components/common/dataSet'),
- '@antv/data-set/lib': '@antv/data-set/lib'
- }
- },
-
- externals: [
- {
- 'react': {
- root: 'React',
- commonjs2: 'react',
- commonjs: 'react',
- amd: 'react'
- },
- 'react-dom': {
- root: 'ReactDOM',
- commonjs2: 'react-dom',
- commonjs: 'react-dom',
- amd: 'react-dom'
- },
- },
- ],
-
- module: {
- rules: [
- {
- test: /\.(js|jsx)$/,
- exclude: /node_modules/,
- use: ['babel-loader'],
- },
- {
- test: /\.scss$/,
- use: [
- {
- loader: MiniCssExtractPlugin.loader,
- options: {
- // you can specify a publicPath here
- // by default it uses publicPath in webpackOptions.output
- // publicPath: '../',
- hmr: process.env.NODE_ENV === 'development',
- },
- },
- 'css-loader',
- 'sass-loader'
- ],
- },
- {
- test: /\.(woff|woff2|eot|ttf|otf|svg)((\?|#).*)?$/,
- use: [{
- loader: 'file-loader',
- options: {
- name: '[name].[ext]',
- publicPath: './',
- },
- }],
- },
- ]
- },
-
- plugins: [
- new MiniCssExtractPlugin({
- // Options similar to the same options in webpackOptions.output
- // both options are optional
- filename: '[name].css',
- // chunkFilename: '[id].css',
- }),
- ],
-
-};
-
-
-/**
- * 获取demo文件夹中的入口文件
- * @param cwd
- * @returns {{}}
- */
-function getDevEntry(cwd) {
- const entry = {};
- glob.sync('*.jsx', {cwd}).forEach((item) => {
- const file = item.replace('.jsx', '');
- entry[file] = [
- // activate HMR for React
- 'react-hot-loader/patch',
- `webpack-dev-server/client?http://0.0.0.0:${config.port}/`,
- 'webpack/hot/only-dev-server',
- `${file}.scss`,
- item
- ];
- });
- return entry;
-}
-
-function getPlugins() {
- const entry = {};
- const plugins = fs.readdirSync(pluginPath);
- plugins.forEach(function (plugin) {
- var componentStat = fs.lstatSync(pluginPath + '/' + plugin);
- if (!componentStat.isDirectory()) {
- return;
- }
-
- entry[plugin] = './plugins/' + plugin + '/index.jsx';
- });
- return entry;
-}
-
-/**
- * 开发环境及demo编译时的配置
- * @returns {*}
- */
-function dev() {
- const _config = _.cloneDeep(config);
-
- _config.context = demoPath;
- _config.resolve.modules = [demoPath, 'node_modules'];
- _config.output = {
- path: demoPath,
- filename: '[name].js',
- publicPath: '/demo/'
- };
- _config.externals[0].react = 'var React';
- _config.externals[0]['react-dom'] = 'var ReactDOM';
-
- _config.plugins.push(
- // 进度插件
- new webpack.ProgressPlugin((percentage, msg) => {
- const stream = process.stderr;
- if (stream.isTTY && percentage < 0.71) {
- stream.cursorTo(0);
- stream.write(`📦 ${msg}`);
- stream.clearLine(1);
- }
- }),
-
- new webpack.DefinePlugin({
- __VERSION__: JSON.stringify(packageInfo.version),
- __THEME__: JSON.stringify('index')
- }),
-
- // 代码热替换
- // new webpack.HotModuleReplacementPlugin(),
- );
-
- // 添加soure-map
- _config.devtool = 'source-map';
- // 入口文件添加server 和 hrm
- _config.entry = Object.assign(getDevEntry(demoPath), getDevEntry(srcPath));
-
- return _config;
-}
-
-/**
- * 发布到cdn及tnpm时的配置
- * @returns {*}
- */
-function prod(themeName, isPlugin) {
- const _config = _.cloneDeep(config);
-
- _config.mode = 'production';
-
- _config.optimization = {
- minimizer: [
- new UglifyJsPlugin({
- uglifyOptions: {
- output: {
- comments: false,
- },
- },
- }),
- new OptimizeCSSAssetsPlugin({}),
- ],
- };
-
- // build环境
- if (themeName) {
- _config.entry = {
- [themeName]: _config.entry.index,
- };
- }
-
- if (isPlugin) {
- _config.entry = getPlugins();
- _config.output.library = componentName + '[name]';
- _config.externals[0]['@alicloud/cloud-charts'] = {
- root: componentName,
- commonjs2: '@alicloud/cloud-charts',
- commonjs: '@alicloud/cloud-charts',
- amd: '@alicloud/cloud-charts'
- };
- }
-
- _config.plugins.push(
- new webpack.DefinePlugin({
- __VERSION__: JSON.stringify(packageInfo.version),
- __THEME__: JSON.stringify(themeName || 'index')
- })
- );
-
- return _config;
-}
-
-/**
- * online 环境
- * @returns {*}
- */
-function online(themeName, isPlugin) {
- const _config = _.cloneDeep(config);
-
- if (themeName) {
- _config.entry = {
- [themeName]: _config.entry.index,
- };
- }
-
- if (isPlugin) {
- _config.entry = getPlugins();
- _config.output.library = componentName + '[name]';
- _config.externals[0]['@alicloud/cloud-charts'] = {
- root: componentName,
- commonjs2: '@alicloud/cloud-charts',
- commonjs: '@alicloud/cloud-charts',
- amd: '@alicloud/cloud-charts'
- };
- }
-
- _config.plugins.push(
- // 进度插件
- new webpack.ProgressPlugin((percentage, msg) => {
- const stream = process.stderr;
- if (stream.isTTY && percentage < 0.71) {
- stream.cursorTo(0);
- stream.write(`📦 ${msg}`);
- stream.clearLine(1);
- }
- }),
-
- new webpack.DefinePlugin({
- __VERSION__: JSON.stringify(packageInfo.version),
- __THEME__: JSON.stringify('index')
- })
- );
-
- // 添加soure-map
- _config.devtool = 'source-map';
-
- return _config;
-}
-
-module.exports = {
-
- dev,
-
- // demo,
-
- prod,
-
- online,
-
- srcPath
-
-};