[]
Visual api 用于呈现自定义的可视化效果。它提供了一些有用的界面帮助作者做一些工作,例如显示提示、交叉筛选、管理选择状态和 i18n。
interface IFilterTarget {
// dataset: string;
column: string;
}
enum VisualFilterType {
Basic = 'basic',
Advanced = 'advanced',
Tuple = 'tuple',
}
interface IFilterBase {
target: IFilterTarget;
filterType: VisualFilterType;
}
enum BasicFilterOperator {
In = 'In',
NotIn = 'NotIn',
}
interface IBasicFilter extends IFilterBase {
operator: BasicFilterOperator;
values: any[];
}
enum AdvancedFilterOperator {
LessThan = 'LessThan',
LessThanOrEqual = 'LessThanOrEqual',
GreaterThan = 'GreaterThan',
GreaterThanOrEqual = 'GreaterThanOrEqual',
}
interface IAdvancedFilterCondition {
value: any;
operator: AdvancedFilterOperator;
}
enum AdvancedFilterLogicalOperator {
And = 'And',
Or = 'Or',
}
interface IAdvancedFilter extends IFilterBase {
conditions: IAdvancedFilterCondition[];
logicalOperator: AdvancedFilterLogicalOperator;
}
type ITuple = { value: any }[];
interface ITupleFilter {
target: IFilterTarget[];
filterType: VisualFilterType;
operator: BasicFilterOperator;
values: ITuple[];
}
type IFilter = IBasicFilter | IAdvancedFilter | ITupleFilter;
interface IVisualUpdateOptions {
isViewer: boolean;
isMobile: boolean;
isEditing: boolean;
isFocus: boolean;
dataViews: any;
updateType: string;
properties: any;
// docTheme: RuntimeNS.IDocTheme;
language: string;
scale: number;
filters: IFilter[];
}
VisualUpdateOption是可视化更新时的数据包(包含聚合更改或属性更改)。
isViewer:表示在预览仪表板时是否呈现该组件。
isMobile::表示是否在移动端显示该组件。
isEditing:表示组件的编辑状态。当触发了编辑操作时,值为true。
isFocus: 表示组件的聚焦状态。当触发了聚焦操作时,值为true。
dataViews: 在capabilities.json中定义的计算数据视图(dataViewMapping)。
properties: 在 capabilities.json 中定义的属性模型(options.visual)。
docTheme: 选择的文档主题。
language: 当前语言。
scale: 比例因子。
filters: 用来影响其他组件。
要实现的主类。
declare class WynVisual {
static Models = {
Filter: {
BasicFilter, AdvancedFilter, TupleFilter,
},
};
static Enums = {
FilterType,
BasicFilterOperator,
AdvancedFilterOperator,
AdvancedFilterLogicalOperator,
UpdateType
};
constructor(dom: HTMLDivElement, host: VisualNS.VisualHost, updateOptions: VisualNS.IVisualUpdateOptions);
update(options: VisualNS.IVisualUpdateOptions): void;
getInspectorHiddenState(updateOptions: VisualNS.IVisualUpdateOptions): string[];
getActionBarHiddenState(updateOptions: VisualNS.IVisualUpdateOptions): string[];
getColorAssignmentConfigMapping(dataViews: VisualNS.IDataView[]): VisualNS.IColorAssignmentConfigMapping;
onResize(): void;
onDestroy(): void;
}
更新将调用每个聚合更改和属性更改。
getInspectorHiddenState返回值路径列表,表示此属性不应显示在属性设置中。
getActionBarHiddenState返回值路径列表,表示此属性不应显示在操作栏中。
getColorAssignmentConfigMapping 返回一个颜色赋值映射对象,表示应该给哪个值赋值颜色。
在调整组件对象的大小时将调用onResize。
卸载时将调用onDestroy。
静态属性Models和Enums为自定义可视化插件提供一些类或枚举。
//capabilities.json
{
options: {
visual: [
{
properties: [{
"name": "mainColorAssignment",
"type": "ColorAssignment",
"displayName": "Enable Color Assignment",
"defaultValue": true
}]
}
]
}
}
// visual.ts
export default class Visual extends WynVisual {
//...others method
private render() {
//...
const circle = node.append('circle')
.attr('r', function (d: any) { return d.r; })
.style('fill', function (d: any) {
//consume the color assignment property
if (options.mainColorAssignment) {
return options.mainColorAssignment[d.data.size] || color(d.package);
} else {
return color(d.package);
}
});
//...
}
public getColorAssignmentConfigMapping(dataViews: VisualNS.IDataView[]): VisualNS.IColorAssignmentConfigMapping {
if (!dataViews.length) {
return null;
}
const plain = dataViews[0].plain;
const colorProfile = plain.profile.series.values[0];
const dimProfile = plain.profile.dimensions.values[0];
if (!colorProfile || !dimProfile) {
return null;
}
// make the values in series color assignmentable
const colorValues = plain.data.map(d => d[colorProfile.display]);
return {
mainColorAssignment: {
values: Array.from(new Set(colorValues)),
type: 'dimension',
columns: [colorProfile],
},
};
}
}
EventService 用于调度一些渲染事件,并且用户可以注册操作栏自定义事件处理程序。
方法 | interface | 说明 | 示例 |
---|---|---|---|
renderStart | renderStart(): void | 用于通知仪表板该组件的渲染状态 | // Update method will be invoke while something changed. public update(options: VisualNS.IVisualUpdateOptions) { this.visualHost.eventService.renderStart(); try { this.render(); // render method is used to update UI this.visualHost.eventService.renderFinish(); } catch (e) { this.visualHost.eventService.renderError(); } } |
renderError | renderError(): void | ||
renderFinish | renderFinish(): void | ||
registerOnCustomEventCallback | registerOnCustomEventCallback(fn: (name: string) => void) | 用于注册操作栏事件 callback 是自定义事件处理程序 | // Register the callback in visual constructor. It will print the action name when you click the corresponding button on action bar. this.visualHost.eventService.registerOnCustomEventCallback((name: string) => { console.log(name); }); |
LocalizationManger 用于在此处提供一些本地化的字符串。
方法 | interface | 说明 | 示例 |
---|---|---|---|
getDisplay | getDisplay(displayNameKey: string): string | 返回本地化字符串 | const noDataText = this.visualHost.localizationManager.getDisplay('NoData'); this.container.textContent = noDataText; |
TooltipService 用来控制提示的显示/隐藏。
方法 | interface | 说明 | 示例 |
---|---|---|---|
show | interface ITootipPosition { x: number; y: number; } interface ILabelFields { label: string; value: string; } interface ITooltipConfig { position: ITootipPosition; title?: string; fields?: ILabelFields[]; selectionId?: SelectionId; selected?: SelectionId[]; menu?: boolean; } show(config: VisualImplNS.ITooltipConfig): void | 显示提示(tooltip)
- position: 鼠标光标位置 - title: 提示的标题 - fields: 需要显示在提示信息中的字段 - selectionId:显示字段的另一种方式,提示信息将显示您绑定到selectionId的字段 - selected: 所有选择的 selectionId - menu:应在提示上显示菜单,例如向下钻取,保留和排除。 | // this function will bind to the chart mouse enter event. It will show a tooltip with title, fields, selection info and menu buttons. private mouseEnterHandler = (node: any) => { this.visualHost.toolTipService.show({ position: { x: d3.event.x, y: d3.event.y, }, title: node.data.color, fields: [{ label: this.valueField, value: node.data.value, }], selectionId: node.data.selectionId, selected: this.selectionManager.getSelectionIds(), menu: true, }); } |
hide | hide(): void | 隐藏提示(tooltip) | // hide the tooltip when the mouse leave the chart shape private mouseLeaveHandler = () => { this.visualHost.toolTipService.hide(); } |
move | move(pos: VisualImplNS.ITootipPosition): void | 移动提示(tooltip) | // update the tooltip position while mouse move on chart private mouseMoveHandler = (e: any) => { this.visualHost.toolTipService.move({ x: d3.event.x, y: d3.event.y, }); } |
PropertyService 用于更新在 capabilities.json 中定义的属性(options.visual)。
方法 | interface | 说明 | 示例 |
---|---|---|---|
setProperty | setProperty(propertyName: string, value: any): void | 更新属性 | // when the button be clicked. The property of showBorder will be change. private onToggle = () => { this.visualHost.propertyService.setProperty('showBorder', !this.properties.showBorder); } |
FormatService用来设置格式化。
方法 | interface | 说明 | 示例 |
---|---|---|---|
isAutoDisplayUnit | isAutoDisplayUnit(displayUnit: DisplayUnit): boolean | 判断 displayUnit 是否为DisplayUnit.Auto | enum DisplayUnit { Auto = 'auto', None = 'none', Hundreds = 'hundreds', Thousands = 'thousands', TenThousand = 'tenThousands', HundredThousand = 'hundredThousand', Millions = 'millions', TenMillion = 'tenMillion', HundredMillion = 'hundredMillion', Billions = 'billions', Trillions = 'trillions', } |
getAutoDisplayUnit | getAutoDisplayUnit(values: number[]): DisplayUnit | 当displayUnit为DisplayUnit.Auto时,得到realDisplayUnit。 | |
format | format(format: string, value: number): string | 格式化数值。 第一个参数格式来自 Format Property或 DataView Profile 项目。 默认 displayUnit 为 DisplayUnit.None; | const formatService = this.visualHost.formatService; const { displayUnit, labelFormat } = updateOptions.properties; let realDisplayUnit = displayUnit; if (formatService.isAutoDisplayUnit(displayUnit)) { const values = dataPoints.map(dataPoint => dataPoint.value); realDisplayUnit = formatService.getAutoDisplayUnit(values); } dataPoints.forEach((dataPoint) => { // prepare a formated text for label. dataPoint.labelText = formatService.format(labelFormat, dataPoint.value, realDisplayUnit); }) |
方法 | interface | 说明 | 示例 |
---|---|---|---|
createSelectionManager | createSelectionManager(): SelectionManager | 创建一个SelectionManager。 | this.selectionManager = this.visualHost.selectionService.createSelectionManager(); |
createSelectionId | createSelectionId(): SelectionId | 为数据点创建SelectionId。 | const selectionId = this.visualHost.selectionService.createSelectionId(); |
SelectionId就像一个向量。它包含绑定到它的维度和度量。将 selection id 附加到数据点后,在图表中单击时就可以触发。
还可以用SelectionId 做很多事情,例如交叉筛选、呈现选择状态、显示提示信息和链接文档。
方法 | interface | 说明 | 示例 |
---|---|---|---|
withMeasure | withMeasure(profile: RuntimeNS.IFieldProfile): SelectionId | 将度量字段绑定到selection id。 | public update(options: VisualNS.IVisualUpdateOptions) { console.log(options); const dataView = options.dataViews[0]; // convert the data view to datas which can be used in chart if (dataView) { const plainData = dataView.plain; // get the fields via different data role. const valueField = plainData.profile.values.values[0].display; const sizeField = plainData.profile.series.values[0].display; const colorField = plainData.profile.dimensions.values[0].display; const items = plainData.data.reduce((result: any, item: any, i: number) => { if (item[valueField]) { // create a selection id for a data point. const selectionId = this.visualHost.selectionService.createSelectionId(); // set the dimensions of the selection id. This will affect on the crossfilter result and others. selectionId .withDimension(plainData.profile.dimensions.values[0], item) .withDimension(plainData.profile.series.values[0], item); // attach the selection id on data model. so that you can access it on hit test result.push({ size: (item[sizeField] |
withDimension | withDimension(profile: RuntimeNS.IFieldProfile, dataPoint: RuntimeNS.IDataPoint): SelectionId | 将维度字段绑定到selection id。 |
Selection manager 用于管理选择状态,并触发交叉筛选。
方法 | interface | 说明 | 示例 |
---|---|---|---|
setSelectionIds | setSelectionIds(ids: Array<SelectionId>) | setter | |
getSelectionIds | getSelectionIds(): Array<SelectionId> | getter | |
getCount | getCount(): number | 获取所选selectionId的计数 | |
select | select(id: SelectionId | Array<SelectionId>, multiSelect: boolean = false): Promise<void> | 选择一个或多个selectionId。multiselect表示应该支持选择多个selectionId。它返回一个许可,并将在选择完成后解决。 |
clear | clear(id?: SelectionId): Promise<void> | 清除选中的或者全部 SelectionId。 | |
registerOnSelectCallback | registerOnSelectCallback(onSelectCallback: (ids: SelectionId[]) => void) | Register a callback, the callback will be invoke after every selection change. 注册 callback,每次选择更改后都将调用callback。 | this.selectionManager.registerOnSelectCallback(() => { // while the selection state changed, should update ui, to highlight the shape which has been selected this.render(); }); |
contains | contains(id: SelectionId): boolean | 检查目标id 是否被选中。 | |
isEmpty | isEmpty(): boolean | 检查 selection manager 是否包含选中的selectionId。 |
ConfigurationManger should work with the configuration in visual.json. If you defined a configuration item. you can access it via this.
ConfigurationManger 应与 visual.json中的配置项一起使用。如果定义一个配置项目,就可以通过这个进行访问。
method | interface | description | sample |
---|---|---|---|
get | get(key: string): string | 获取配置项 | // to access the amapToken in configuration const amapToken = this.visualHost.configurationManager.get('amapToken'); |
AssetsManager 应与 visual.json 中的 assets 一起使用。当前您可以在assets 中定义图片资源,它们将被打包。可以通过这个访问图片。
method | interface | description | sample |
---|---|---|---|
getImage | getImage(imageName: string): string | 返回base64字符串 | // to access the image in assets this.container.style.backgroundImage = |
CommandService 提供了一些仪表板命令,例如切换选项卡容器。
方法 | interface | 说明 | 示例 |
---|---|---|---|
execute | interface ICommandDescription { name: string; payload: { target: string; }; } execute(commandsDesc: Array<ICommandDescription>): void | 执行命令 | // run a command to active a tab container this.visualHost.commandService.execute([{ name: 'SelectTab', payload: { target: 'myTabContainer', index: 0, } }]) |
Command Name | 描述 | 说明 | 示例 |
---|---|---|---|
SwitchTab | 用户可以使用这个命令来切换选项卡组件中的标签。 | - SwitchTab 命令是专为选项卡设计的命令。
- 标签的索引将通过参数命令传递。 以下是 SwitchTab 的接口。
- 如果 index 小于0,将切换到0;如果 index 大于标签计数-1,将切换到最后一个标签。
- 如存在多个标签时,建议使用选项卡的组件名称来定位标签。
- 如果 index 和组件名称同时被传递,则 index 优先生效。 | - 在Visual Plugin中使用 command service 来调用
- 在命令被立即执行后,选项卡标签将显示为预期的样子。
- 如果执行失败,返回值将是 false,否则是 true。 |
Command Name | 描述 | 说明 | 示例 |
---|---|---|---|
SwitchPage | 用户可以使用这个命令来切换仪表板页面。 | - SwitchPage 命令是专仪表板设计的。
- 如果 page index 或 page name 无效,将不进行页面切换。
- 如果存在大量的页面,page index 就很难计算。建议使用页面名称(page name)。
- 如果page index 和 page name 同时被传递,那么page index 优先生效。 | - 在Visual Plugin 中使用command service 来调用
- 在命令被立即执行后,页面切换将显示为预期的效果。 |
Command Name | 描述 | 说明 | 示例 |
---|---|---|---|
Keep/Exclude | 用户可以使用这个命令来执行保留或排除操作。 | // Keep & Exclude this.host.commandService.execute([{ name: 'Keep', // or 'Exclude' payload: { selectionIds, }, }]); | — |
Command Name | 描述 | 说明 | 示例 |
---|---|---|---|
Drill/Jump | 用户可以使用这个命令来执行钻取或跳转操作。 | // Drill & Jump this.host.commandService.execute([{ name: 'Drill', // or 'Jump' payload: { selectionIds, // optional position: { x: event.clientX, y: event.clientY }, }, }]); | — |
FilterService用于派遣过滤器影响其他场景。过滤器将被列在 updateOptions.filters 中。
目前,您可以创建Basic,Tuple和Advanced Filter。
首先,你应该通过设置options.common.filter为 "true "来启用过滤器。
方法 | interface | description | 示例 |
---|---|---|---|
applyFilter | interface IFilterTarget { // dataset: string; column: string; } enum VisualFilterType { Basic = 'basic', Advanced = 'advanced', Tuple = 'tuple', } interface IFilterBase { target: IFilterTarget; filterType: VisualFilterType; } applyFilter(filter: BasicFilter | TupleFilter | AdvancedFilter): void |
clean | clean(): void | 清除过滤器 | host.filterService.clean(); |
与内置的标签列表类似,相当于SQL:
SELECT * FROM table WHERE Dept IN ( DTD1 , DTD2 , DTD3 )
方法 | interface | description | 示例 |
---|---|---|---|
constructor | enum BasicFilterOperator { In = 'In', NotIn = 'NotIn', } interface IBasicFilter extends IFilterBase { operator: BasicFilterOperator; values: any[]; } constructor(targetProfile: RuntimeNS.IFieldProfile, operator: BasicFilterOperator = BasicFilterOperator.In, values: any[] = []) | targetProfile是数据视图中的过滤区域。 | const profile = dv.plain.profile.dimensions.values[0]; const BasicFilter = WynVisual.Models.Filter.BasicFilter; const filter = new BasicFilter(profile); |
setOperator/getOperator | setOperator(operator: BasicFilterOperator) getOperator(): BasicFilterOperator | this.filter.setOperator(this.filter.getOperator() === WynVisual.Enums.BasicFilterOperator.In ? WynVisual.Enums.BasicFilterOperator.NotIn : WynVisual.Enums.BasicFilterOperator.In ) | |
setValues/getValues | getValues(): any[] setValues(vals: any[]) | filter.setValues(['DTD1', 'DTD2']) | |
toJSON/fromJSON | toJSON(): BasicNS.IBasicFilter fromJSON(obj: BasicNS.IBasicFilter) | 从updateOptions.filters中恢复过滤器。 | const profile = dv.plain.profile.dimensions.values[0]; const filter = new BasicFilter(profile); filter.fromJSON(options.filters[0]); |
contains | contains(value: any): boolean | 是否包含在过滤器中的值 | if (this.filter.contains(val)) { this.filter.remove(val); } else { this.filter.add(val); } |
remove/add | remove(val: any) add(val: any) | 添加或移除值 | if (this.filter.contains(val)) { this.filter.remove(val); } else { this.filter.add(val); } |
isEmpty | isEmpty(): boolean |
它类似于BasicFilter,但它可以在多维度时生效.相当于SQL:
SELECT * FROM DataTable WHERE ( Team = "DTD1" AND Prod = "Wyn" ) OR ( Team = "DTD2" AND Prod = "SpreadJS" );
方法 | interface | description | 示例 |
---|---|---|---|
constructor | type ITuple = { value: any }[]; interface ITupleFilter { target: IFilterTarget[]; filterType: VisualFilterType; operator: BasicFilterOperator; values: ITuple[]; } constructor(targetProfiles: RuntimeNS.IFieldProfile[], operator: BasicFilterOperator = BasicFilterOperator.In, values: BasicNS.ITuple[] = []) | const dimensionsProfiles = dv.plain.profile.dimensions.values; const filter = new TupleFilter(dimensionsProfiles); | |
setOperator/getOperator | setOperator(operator: BasicFilterOperator) getOperator(): BasicFilterOperator | ||
getValues/setValues | getValues(): BasicNS.ITuple[] setValues(vals: BasicNS.ITuple[]) | ||
toJSON/fromJSON | toJSON(): BasicNS.ITupleFilter fromJSON(obj: BasicNS.ITupleFilter) | ||
contains | contains(tuple: BasicNS.ITuple): boolean | ||
remove/add | remove(tuple: BasicNS.ITuple) add(tuple: BasicNS.ITuple) | ||
createTuple | createTuple(dp: RuntimeNS.IDataPoint, depth?: number): BasicNS.ITuple | 按选定的数据点创建元组 | this.items = dv.plain.data.reduce((res, dp) => { const label = Object.keys(dp).map(key => dp[key]).join('-'); const tuple = filter.createTuple(dp); res.push({ label, className: filter.contains(tuple) ? 'selected' : '', tuple: JSON.stringify(tuple), }); return res; }, []); |
isEmpty | isEmpty(): boolean |
高级过滤器提供了lessThan、greatThan和其他运算符来查询,目前不支持逻辑运算符 "Or"。
方法 | interface | description | 示例 |
---|---|---|---|
constructor | enum AdvancedFilterLogicalOperator { And = 'And', Or = 'Or', } enum AdvancedFilterOperator { LessThan = 'LessThan', LessThanOrEqual = 'LessThanOrEqual', GreaterThan = 'GreaterThan', GreaterThanOrEqual = 'GreaterThanOrEqual', } interface IAdvancedFilterCondition { value: any; operator: AdvancedFilterOperator; } interface IAdvancedFilter extends IFilterBase { conditions: IAdvancedFilterCondition[]; logicalOperator: AdvancedFilterLogicalOperator; } constructor(targetProfile: RuntimeNS.IFieldProfile, logicalOperator: AdvancedFilterLogicalOperator = AdvancedFilterLogicalOperator.And, conditions: BasicNS.IAdvancedFilterCondition[] = []) | ||
setLogicalOperator/getLogicalOperator | setLogicalOperator(operator: AdvancedFilterLogicalOperator) getLogicalOperator(): AdvancedFilterLogicalOperator | ||
setConditions/getConditions | setConditions(conditions: BasicNS.IAdvancedFilterCondition[]) getConditions(): BasicNS.IAdvancedFilterCondition[] | this.filter.setConditions([{ value: min, operator: this.includeMinEle.checked ? Enums.AdvancedFilterOperator.GreaterThanOrEqual : Enums.AdvancedFilterOperator.GreaterThan, }, { value: max, operator: this.includeMaxEle.checked ? Enums.AdvancedFilterOperator.LessThanOrEqual : Enums.AdvancedFilterOperator.LessThan, }]); | |
toJSON/fromJSON | toJSON(): BasicNS.IAdvancedFilter fromJSON(obj: BasicNS.IAdvancedFilter) | ||
remove/add | remove(condtion: BasicNS.IAdvancedFilterCondition) add(condtion: BasicNS.IAdvancedFilterCondition) | ||
isEmpty | isEmpty(): boolean |