visactor / vchart Goto Github PK
View Code? Open in Web Editor NEWVChart, more than just a cross-platform charting library, but also an expressive data storyteller.
Home Page: https://www.visactor.io/vchart
License: MIT License
VChart, more than just a cross-platform charting library, but also an expressive data storyteller.
Home Page: https://www.visactor.io/vchart
License: MIT License
New 4.x indicator chart, which includes 3.x's features.
interface IIndicatorChartSpec {
data: ...
title: MaybeArray<{
key: ITextMarkSpec;
value: ITextMarkSpec;
symbol: ISymbolMarkSpec;
}>;
content: MaybeArray<{
key: ITextMarkSpec;
value: ITextMarkSpec;
symbol: ISymbolMarkSpec;
}>;
layoutMode: 'normal' | 'comparative';
}
In some chart scenarios, users expect to use multiple discrete legends corresponding to different dimension mappings, such as a color legend and a shape legend, which require the legends to correspond to different dimensions
spec: {
legends: {
type: "discrete",
field: 'shape'
}
}
1.0.0
https://codepen.io/xuanhun/pen/BaGZRYb
direction: 'horizontal',
yField: 'type',
xField: ['min', 'max'],
label: {
visible: false,
position: 'bothEnd', // 两端
// position: 'start', // 起点
// position: 'end', // 终点
// position: 'middle', // 中间
},
set "label.visible" as "false",but it is not effect.
The labels are hidden.
- OS:
- Browser:
- Framework:
Like lineChart, barChart, we should provide crosshair component by default.
none
目前按需引入的方式如下:
import { VChart } from "@visactor/vchart/esm/core/vchart";
import { Factory } from "@visactor/vchart/esm/core/factory";
import { Region } from "@visactor/vchart/esm/region/region";
import { Layout } from "@visactor/vchart/esm/layout/index";
import { RectMark } from "@visactor/vchart/esm/mark/rect";
import { ComponentMark } from "@visactor/vchart/esm/mark/component";
import { GroupMark } from "@visactor/vchart/esm/mark/group";
import {
CartesianAxis,
CartesianLinearAxis,
CartesianBandAxis
} from "@visactor/vchart/esm/component/axis/cartesian/index";
import { Tooltip } from "@visactor/vchart/esm/component/tooltip";
import { CartesianCrossHair } from "@visactor/vchart/esm/component/crosshair/cartesian";
import { BarSeries } from "@visactor/vchart/esm/series/bar/bar";
import { BarChart } from "@visactor/vchart/esm/chart/bar/bar";
// charts
VChart.useChart([BarChart]);
// series
VChart.useSeries([BarSeries]);
// marks
VChart.useMark([RectMark, ComponentMark, GroupMark]);
// components
VChart.useComponent([
CartesianAxis as any,
CartesianLinearAxis,
CartesianBandAxis,
Tooltip,
CartesianCrossHair
]);
// region
Factory.registerRegion("region", Region as any);
// layout
Factory.registerLayout("base", Layout as any);
存在如下问题:
1.0.0
null
trigger dimension tooltip and then scroll page
tooltip is displayed incorrectly in this case
- OS:
- Browser:
- Framework:
No response
1.0.0
none
Just run the spec:
const spec = {
type: 'line',
data: [
{
id: 'line',
values: [
{ x: '周一', y: 12 },
{ x: '周二', y: 13 },
{ x: '周三', y: 11 },
{ x: '周四', y: 10 },
{ x: '周五', y: 12 },
{ x: '周六', y: 14 },
{ x: '周日', y: 17 }
]
}
],
xField: 'y',
yField: 'y',
axes: [
{
zIndex: 100,
orient: 'bottom'
},
{
zIndex: 100,
orient: 'left',
inverse: true, // 左轴开启反转, inverse the left axis
domainLine: {
visible: true,
// 开启末端箭头标记,show the endSymbol
endSymbol: {
visible: true,
style: {
fill: '#000'
}
}
}
}
]
};
throw the following error:
It should support this situation.
- OS:
- Browser:
- Framework:
No response
1.0.0
https://jsfiddle.net/785wxezc/3/
see: https://jsfiddle.net/785wxezc/3/
axis disappear
axis should not disappear
- OS:
- Browser:
- Framework:
No response
It should display all the label on the bottom axis.
preproduce spec:
const items = [
'资产负债率',
'剔除预收款项后的资产负债率',
'长期资本负债率',
'长期资产适合率',
'权益乘数',
'流动负债权益比率',
'带息债务/全部投入资本',
'流动负债/负债合计',
'资本固定化比率',
'期望违约频率EDF'
];
const rawData = [
1.0, 0.594527, 0.492963, -0.160995, 0.723664, 0.658646, -0.857474, 0.320706, -0.284634, -0.091423, 0.594527, 1.0,
0.724546, -0.099318, 0.540639, 0.49214, -0.554039, 0.17127, -0.265259, 0.068577, 0.492963, 0.724546, 1.0, -0.091338,
0.450542, 0.375839, -0.524955, 0.300627, -0.198362, 0.033209, -0.160995, -0.099318, -0.091338, 1.0, -0.049872,
-0.028452, 0.157157, 0.009742, -0.162374, 0.155095, 0.723664, 0.540639, 0.450542, -0.049872, 1.0, 0.951933, -0.651767,
0.079052, -0.535984, 0.00798, 0.658646, 0.49214, 0.375839, -0.028452, 0.951933, 1.0, -0.543147, -0.106139, -0.52232,
0.011466, -0.857474, -0.554039, -0.524955, 0.157157, -0.651767, -0.543147, 1.0, -0.595016, 0.310521, 0.066397,
0.320706, 0.17127, 0.300627, 0.009742, 0.079052, -0.106139, -0.595016, 1.0, -0.105199, -0.064886, -0.284634,
-0.265259, -0.198362, -0.162374, -0.535984, -0.52232, 0.310521, -0.105199, 1.0, -0.080153, -0.091423, 0.068577,
0.033209, 0.155095, 0.00798, 0.011466, 0.066397, -0.064886, -0.080153, 1.0
];
const data = [];
for (let i = 0; i < items.length; i++) {
for (let j = 0; j < items.length; j++) {
data.push({
var1: items[i],
var2: items[j],
value: rawData[i * items.length + j]
});
}
}
const spec = {
type: 'common',
padding: 12,
data: [
{
id: 'data0',
values: data
}
],
series: [
{
type: 'heatmap',
regionId: 'region0',
xField: 'var1',
yField: 'var2',
valueField: 'value',
cell: {
style: {
fill: {
field: 'value',
scale: 'color'
}
}
}
}
],
region: [
{
id: 'region0',
width: 300, // 限定 region 的宽度
height: 300 // 限定 region 的高度
}
],
color: {
type: 'linear',
domain: [
{
dataId: 'data0',
fields: ['value']
}
],
range: ['#feedde', '#fdbe85', '#fd8d3c', '#e6550d', '#a63603']
},
axes: [
{
orient: 'bottom',
type: 'band',
grid: {
visible: false
},
domainLine: {
visible: false
},
label: {
space: 10,
style: {
textAlign: 'left',
textBaseline: 'middle',
angle: 90
}
},
bandPadding: 0,
height: layoutRect => {
// 将底部轴的高度设置为画布的高度 - region 高度 - paddingTop - paddingBottom
return layoutRect.height - 324;
}
},
{
orient: 'left',
type: 'band',
grid: {
visible: false
},
domainLine: {
visible: false
},
label: {
space: 10
},
bandPadding: 0
}
],
legends: {
visible: true,
orient: 'right',
type: 'color',
field: 'value',
title: {
visible: true,
text: `Correlation Coefficient`
}
}
};
zoomLimit
didn't work in map markvRender problem:
consume
config in event did not work as expectedSupport image mark. Image mark is required in extended and narrative scenarios
export inerface IImageMarkSpec extends IFillMarkSpec{
width: number;
height: number;
repeatX: IRepeatType;
repeatY: IRepeatType;
image: string | HTMLImageElement | HTMLCanvasElement;
}
1.0.0
https://jsfiddle.net/4otquy30/1/
I made a reproduction in this jsfiddle link: https://jsfiddle.net/4otquy30/1/
The area value cannot be displayed, just like the following snapshot:
The area values should be displayed, and the shape should be circle.
- OS:
- Browser:
- Framework:
No response
0.0.1-alpha.1
none
reproduce spec:
const spec = {
data: [
{
name: 'data1',
values: [
{
x0: -400,
x1: -380,
frequency: 0
},
{
x0: -380,
x1: -360,
frequency: 4
},
{
x0: -360,
x1: -340,
frequency: 7
},
{
x0: -340,
x1: -320,
frequency: 7
},
{
x0: -320,
x1: -300,
frequency: 18
},
{
x0: -300,
x1: -280,
frequency: 30
},
{
x0: -280,
x1: -260,
frequency: 33
},
{
x0: -260,
x1: -240,
frequency: 80
},
{
x0: -240,
x1: -220,
frequency: 98
},
{
x0: -220,
x1: -200,
frequency: 124
},
{
x0: -200,
x1: -180,
frequency: 161
},
{
x0: -180,
x1: -160,
frequency: 176
},
{
x0: -160,
x1: -140,
frequency: 227
},
{
x0: -140,
x1: -120,
frequency: 276
},
{
x0: -120,
x1: -100,
frequency: 321
},
{
x0: -100,
x1: -80,
frequency: 452
},
{
x0: -80,
x1: -60,
frequency: 441
},
{
x0: -60,
x1: -40,
frequency: 505
},
{
x0: -40,
x1: -20,
frequency: 521
},
{
x0: -20,
x1: 0,
frequency: 733
},
{
x0: 0,
x1: 20,
frequency: 892
},
{
x0: 20,
x1: 40,
frequency: 362
},
{
x0: 40,
x1: 60,
frequency: 267
},
{
x0: 60,
x1: 80,
frequency: 223
},
{
x0: 80,
x1: 100,
frequency: 157
},
{
x0: 100,
x1: 120,
frequency: 170
},
{
x0: 120,
x1: 140,
frequency: 124
},
{
x0: 140,
x1: 160,
frequency: 112
},
{
x0: 160,
x1: 180,
frequency: 73
},
{
x0: 180,
x1: 200,
frequency: 80
},
{
x0: 200,
x1: 220,
frequency: 49
},
{
x0: 220,
x1: 240,
frequency: 33
},
{
x0: 240,
x1: 260,
frequency: 30
},
{
x0: 260,
x1: 280,
frequency: 21
},
{
x0: 280,
x1: 300,
frequency: 9
},
{
x0: 300,
x1: 320,
frequency: 13
},
{
x0: 320,
x1: 340,
frequency: 11
},
{
x0: 340,
x1: 360,
frequency: 5
},
{
x0: 360,
x1: 380,
frequency: 4
},
{
x0: 380,
x1: 400,
frequency: 4
},
{
x0: 400,
x1: 420,
frequency: 2
},
{
x0: 420,
x1: 440,
frequency: 8
},
{
x0: 440,
x1: 460,
frequency: 2
},
{
x0: 460,
x1: 480,
frequency: 3
},
{
x0: 480,
x1: 500,
frequency: 10
},
{
x0: 500,
x1: 520,
frequency: 7
},
{
x0: 520,
x1: 540,
frequency: 14
},
{
x0: 540,
x1: 560,
frequency: 6
},
{
x0: 560,
x1: 580,
frequency: 1
},
{
x0: 580,
x1: 600,
frequency: 3
},
{
x0: 600,
x1: 620,
frequency: 0
},
{
x0: 620,
x1: 640,
frequency: 6
},
{
x0: 640,
x1: 660,
frequency: 5
},
{
x0: 660,
x1: 680,
frequency: 3
},
{
x0: 680,
x1: 700,
frequency: 2
},
{
x0: 700,
x1: 720,
frequency: 0
}
]
}
],
type: 'histogram',
xField: 'x0',
x2Field: 'x1',
yField: 'frequency',
bar: {
style: {
stroke: 'white',
lineWidth: 1
}
},
title: {
text: 'Arrival Time Histogram',
textStyle: {
height: 50,
lineWidth: 3,
fill: '#333',
fontSize: 25,
fontFamily: 'Times New Roman'
},
subtextStyle: {
character: [
{
text: 'This histogram details the distribution of the number of seconds the arrival of tram line 1 of Amsterdam on 2 October 2017 deviated from the planning on each stop in each trip.\nThe data was filtered to remove 4 extreme measurements from ~7000 datapoints that caused significant skewing.',
fontFamily: 'Times New Roman',
fontSize: 14,
fill: '#333'
},
{
text: '\ndata source: https://observablehq.com/@nickrttn/departure-time-histogram',
fontSize: 10,
fill: '#333',
fillOpacity: 0.5
}
]
}
},
tooltip: {
visible: true,
mark: {
title: {
key: 'title',
value: 'frequency'
},
content: [
{
key: datum => datum['x0'] + '~' + datum['x1'],
value: datum => datum['frequency']
}
]
}
},
crosshair: {
xField: { visible: true }
}
};
the line of crosshair can not render.
show the rect of crosshair
- OS:
- Browser:
- Framework:
No response
currently, if you configured animation: false
in spec, and then use updateSpec
API to rerender chart, the morphing animation will still run. This might be confusing.
Support a new built-in interaction mode that allows selecting data for a specific group
add build-in state:
Users want to achieve the effect shown in the figure below by configuring the first line title as the shape / key of the content line.
But under the current logic, the layout will become like this:
It is expected to support setting the key column of a certain content row not to participate in the overall column alignment, achieving the effect of adapting to text content. Just like this:
Add a new api in IToolTipLinePattern
:
interface IToolTipLinePattern extends ITooltipShapePattern {
/** 该 pattern 属于哪个系列id(用户不需要设置) */
seriesId?: number;
/** tooltip key 值内容 */
key?: TooltipContentProperty<string>;
/** tooltip value 值内容 */
value?: TooltipContentProperty<string>;
/** 该行是否可见 */
visible?: TooltipContentProperty<boolean>;
// new api
/** Does the key column in this row fit the content */
isKeyAdaptive?: TooltipContentProperty<boolean>;
}
If isKeyAdaptive
of a certain content line is set to true, then:
1.1.0-beta.0
none
just run the following spec, and set vchart-tooltip-element
line-height to 18px, you can reproduce the bug.
const spec = {
type: 'line',
data: {
values: [
{
time: '2:00',
value: 8
},
{
time: '4:00',
value: 9
},
{
time: '6:00',
value: 11
},
{
time: '8:00',
value: 14
},
{
time: '10:00',
value: 16
},
{
time: '12:00',
value: 17
},
{
time: '14:00',
value: 17
},
{
time: '16:00',
value: 16
},
{
time: '18:00',
value: 15
}
]
},
xField: 'time',
yField: 'value'
};
The tooltip's shape can not be vertical aligned.
The tooltip's shape should be vertical aligned.
- OS:
- Browser:
- Framework:
No response
reproduce spec:
const spec = {
type: 'line',
data: {
values: [
{
time: '0:05',
value: 10
},
{
time: '0:10',
value: 18
},
{
time: '0:15',
value: 20
},
{
time: '0:20',
value: 18
},
{
time: '0:25',
value: 20
},
{
time: '0:30',
value: 18
},
{
time: '0:35',
value: 20
},
{
time: '0:40',
value: 18
},
{
time: '0:45',
value: 20
},
{
time: '0:50',
value: 18
},
{
time: '0:55',
value: 10
},
{
time: '1:00',
value: 28
},
{
time: '1:05',
value: 18
},
{
time: '1:10',
value: 14
},
{
time: '1:15',
value: 12
},
{
time: '1:20',
value: 9
},
{
time: '1:25',
value: 20
},
{
time: '1:30',
value: 3
},
{
time: '1:35',
value: 4
},
{
time: '1:40',
value: 5
},
{
time: '1:45',
value: 10
},
{
time: '1:50',
value: 16
},
{
time: '1:55',
value: 10
},
{
time: '2:00',
value: 8
},
{
time: '2:05',
value: 18
},
{
time: '2:10',
value: 14
},
{
time: '2:15',
value: 12
},
{
time: '2:20',
value: 9
},
{
time: '2:25',
value: 20
},
{
time: '2:30',
value: 3
},
{
time: '2:35',
value: 4
},
{
time: '2:40',
value: 5
},
{
time: '2:45',
value: 10
},
{
time: '2:50',
value: 16
},
{
time: '2:55',
value: 10
},
{
time: '4:00',
value: 9
},
{
time: '6:00',
value: 11
},
{
time: '8:00',
value: 14
},
{
time: '10:00',
value: 16
},
{
time: '12:00',
value: 17
},
{
time: '14:00',
value: 17
},
{
time: '16:00',
value: 16
},
{
time: '18:00',
value: 15
}
]
},
xField: 'time',
yField: 'value',
crosshair: {
xField: { visible: true }
},
scrollBar: [
{
orient: 'bottom',
start: 0.8,
end: 1,
roam: true,
filterMode: 'axis'
}
]
};
Users hope to more conveniently configure different tooltip content for different mark types.
There are 2 ways to implement:
tooltip
api to mark spec, like this:// series spec
{
funnel: {
style: { ... },
state: { ... },
tooltip: { ... } // ITooltipPattern
},
transform: {
style: { ... },
state: { ... },
tooltip: { ... } // ITooltipPattern
},
}
ITooltipPattern
declaration:
interface ITooltipPattern {
visible?: boolean;
title?: IToolTipLinePattern;
content?: IToolTipLinePattern[];
position?: TooltipPosition;
hasShape?: boolean;
shapeType?: ShapeType | TooltipContentCallback;
shapeColor?: string | TooltipContentCallback;
shapeHollow?: boolean;
updateTitle?: (prev: IToolTipLineActual | undefined, data: TooltipData) => IToolTipLineActual | undefined;
updateContent?: (prev: IToolTipLineActual[] | undefined, data: TooltipData) => IToolTipLineActual[] | undefined;
updatePosition?: (prev: ITooltipPositionActual | undefined, data: TooltipData) => ITooltipPositionActual | undefined;
// new api, same to the property in ITooltipSpec
style?: Omit<ITooltipTheme, 'maxWidth' | 'minWidth' | 'offset'>;
}
This method is very intuitive but difficult to implement.
ITooltipPattern.visible
, ITooltipPattern.title
and ITooltipPattern.content
support custom callback:interface ITooltipPattern {
visible?: boolean | ((data: TooltipData, mark: IMark) => boolean);
title?: IToolTipLinePattern | ((data: TooltipData, mark: IMark) => IToolTipLinePattern);
content?: IToolTipLinePattern[] | ((data: TooltipData, mark: IMark) => IToolTipLinePattern[]);
}
This method is less flexible and scalable.
0.0.1-alpha.0
null
const VChart = require("@visactor/vchart");
In the node environment, use the cjs method to run, and get an error:
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/bytedance/Downloads/node-canvas/node_modules/@visactor/vdataset/node_modules/d3-geo/src/index.js from /Users/bytedance/Downloads/node-canvas/node_modules/@visactor/vdataset/cjs/utils/geo.js not supported.
Instead change the require of index.js in /Users/bytedance/Downloads/node-canvas/node_modules/@visactor/vdataset/cjs/utils/geo.js to a dynamic import() which is available in all CommonJS modules.
normal operation
- node v16.16.0
No response
It will be convenient for users to switch chart themes through specification.
{
theme: 'myThemeName'
}
Related VisActor/VRender#20
demo: legend/cutsom-ui
fillColor
-> fill
strokeColor
-> stroke
boxPlot
mark style namecommon theme properties in ITheme
export interface ITheme {
/** 全局 mark 样式属性,按 mark 名称区分 */
markByName?: IGlobalMarkThemeByName;
}
export interface IGlobalMarkThemeByName {
/** used in lineSeries, areaSeries, radarSeries, etc. */
line?: Partial<IMarkTheme<ILineMarkSpec>>;
/** used in lineSeries, areaSeries, radarSeries, scatterSeries etc. */
point?: Partial<IMarkTheme<ISymbolMarkSpec>>;
/** used in lineSeries, areaSeries, radarSeries, etc. */
area?: Partial<IMarkTheme<IAreaMarkSpec>>;
/** used in barSeries, rangeColumnSeries etc. */
bar?: Partial<IMarkTheme<IRectMarkSpec>>;
/** used in many series */
label?: Partial<IMarkTheme<ITextMarkSpec>>;
[markName: string]: Partial<IMarkTheme<any>>;
}
@visactor/[email protected]
none
if add a random key for the component, this problem can be avoided.
onPointerUp onClick not triggered
event handler works if rerender.
- OS: Mac
- Browser: Chrome
- Framework: React
No response
label.overlap
not workcenter
not workIf you use VChart, don't be shy edit this wiki page.
1.0.0-alpha.0
https://codesandbox.io/s/fervent-fermi-6pllny?file=/src/index.ts
after setting all values to negative, the left axis has disappears
when setting all values to negative, the left axis work well
- OS:
- Browser:
- Framework:
No response
The page-turner interaction range of the discrete legend on the mobile terminal is too small and difficult to click
change the default of the page-turner interaction range or add a switch to toggle precise interaction
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.