指标核心逻辑
以simplelabel为例,下面讲解一下开发指标逻辑的注意事项,下面是其代码部分。
/**
* Created by FreezeSoul on 2016/4/7.
*/
define([
"app/core/base",
"app/core/util",
"jquery",
"underscore",
'loglevel',
'jqueryTmpl',
'jQueryUUID'
], function (Chart, Util, $, _, log) {
var property = {
config: "property",
option: [
{
group: '基础',
id: 'LabelInitText',
name: '初始文本',
enable: false,
type: 'text',
value: '',
default: '',
link: 'text',
tooltip: '文本标签初始值'
},
{
group: '基础',
id: 'LabelFontSize',
name: '字体大小',
enable: false,
type: 'number',
value: 14,
default: 14,
link: 'fontSize',
tooltip: '文本字体大小'
},
{
group: '基础',
id: 'LabelFontColor',
name: '字体颜色',
enable: false,
type: 'color',
value: '#000000',
default: '#000000',
link: 'fontColor',
tooltip: '文本字体颜色'
},
{
group: '基础',
id: 'LabelBorderPadding',
name: '内边距值',
enable: false,
type: 'padding',
value: [5,5,5,5],
default: [5,5,5,5],
link: 'padding',
tooltip: '文本内边距值'
},
{
group: '基础',
id: 'LabelBorderWidth',
name: '边框宽度',
enable: false,
type: 'number',
value: 1,
default: 1,
link: 'borderWidth',
tooltip: '文本边框宽度'
},
{
group: '基础',
id: 'LabelBorderStyle',
name: '边框样式',
enable: false,
type: 'select',
value: 'solid',
default: 'solid',
data: [{
value: 'dotted',
text: '点线边框'
}, {
value: 'dashed',
text: '虚线边框'
}, {
value: 'solid',
text: '实线边框'
}, {
value: 'double',
text: '两个边框'
}, {
value: 'groove',
text: '3D沟槽边框'
}, {
value: 'ridge',
text: '3D脊边框'
}, {
value: 'inset',
text: '3D嵌入边框'
}, {
value: 'outset',
text: '3D突出边框'
}],
link: 'fontStyle',
tooltip: '文本边框样式'
},
{
group: '基础',
id: 'LabelBorderColor',
name: '边框颜色',
enable: false,
type: 'color',
value: '#000000',
default: '#000000',
link: 'borderColor',
tooltip: '文本边框颜色'
},
{
group: '基础',
id: 'LabelBackColor',
name: '背景颜色',
enable: false,
type: 'color',
value: 'transparent',
default: 'transparent',
link: 'backColor',
tooltip: '文本背景颜色,透明色transparent'
},
{
group: '基础',
id: 'LabelBangDing',
name: '绑定文本',
enable: false,
type: 'textBinding',
dataset: '',
ctype: 'all',
column: {},
tooltip: '文本绑定'
}
],
MapOption: function (option) {
Util.linkOption(this.option, option);
}
};
var label = Chart.extend({
constructor: function (layout) {
this._layout = layout;
this._element = null;
this._container = null;
this._option = {
Series: [],
Events: [],
Extend: $.extend(true, {}, property),
Option: {
text: "标签控件",
padding: [5, 5, 5, 5],
fontSize: 14,
fontColor: "#000000",
fontStyle: "",
borderWidth: 1,
borderColor: "#000000",
backColor: "transparent"
}
};
},
init: function (element) {
try {
this._uuid = $.uuid();
this._container = element;
} catch (e) {
log.error(e);
}
},
_readProperty: function () {
try {
if (!this._option.Extend) return;
Util.deepMapOption(property, this._option.Extend, this._option.Option);
} catch (e) {
log.error(e);
}
},
_render: function (option) {
var $element = $.tmpl('<span id="${id}" class="label-text">${text}</span>', $.extend(true, {
id: this._uuid
}, option));
if (option.fontSize && option.fontSize > 0) {
$element.css("font-size", option.fontSize + "px")
}
if ($.isArray(option.padding) && option.padding.length == 4) {
if (option.padding[0] && option.padding[0] > 0)
$element.css("padding-top", option.padding[0]);
if (option.padding[1] && option.padding[1] > 0)
$element.css("padding-right", option.padding[1]);
if (option.padding[2] && option.padding[2] > 0)
$element.css("padding-bottom", option.padding[2]);
if (option.padding[3] && option.padding[3] > 0)
$element.css("padding-left", option.padding[3]);
}
if (option.fontColor) {
$element.css("color", option.fontColor)
}
if (option.borderWidth && option.borderWidth > 0) {
$element.css("border-width", option.borderWidth + "px")
}
if (option.borderColor) {
$element.css("border-color", option.borderColor)
}
if (option.fontStyle) {
$element.css("border-style", option.fontStyle)
}
if (option.backColor) {
$element.css("background-color", option.backColor)
}
$element.css("display", "inline-block");
$(this._container).empty();
$element.appendTo(this._container);
this._bindEvent($element);
return $element;
},
_bindEvent: function (element) {
var _this = this;
$(element).on("click", function (e) {
if (_this._layout
&& _this._layout.navigate
&& _this._option.Events
&& _this._option.Events.length > 0) {
var registerEvent = _.findWhere(_this._option.Events, {Event: "LabelClick"});
if (registerEvent) {
var pageId = registerEvent.PageId;
var params = registerEvent.Params;
var args = [];
var dParam = _.findWhere(params, {Name: "文本"});
if (dParam && dParam.ParamName) {
args.push({
ParamName: dParam.ParamName,
ParamValue: $(element).find(".label-text").text()
});
}
_this._layout.navigate(pageId, args);
}
e.preventDefault();
}
});
},
example: function () {
try {
this._element = this._render(this._option.Option);
} catch (e) {
log.error(e);
}
},
_bindData: function (data) {
var bindProperty = _.findWhere(this._option.Extend.option, {type: 'textBinding'});
if (!bindProperty || !bindProperty.dataset) return;
var dataSetCode = bindProperty.dataset;
var table = data[dataSetCode];
if (table && table.length > 0 && bindProperty.column) {
var row = table[0];
var columnName = bindProperty.column.ColumnName;
if (columnName) {
this._option.Option.text = row[columnName];
}
}
},
setData: function (data) {
try {
this._readProperty();
if (data
&& this._option.Binding
&& this._option.Binding.length > 0
&& this._option.Extend
) {
this._bindData(data);
}
this._element = this._render(this._option.Option);
} catch (e) {
log.error(e);
}
},
setOption: function (option) {
try {
this._option = $.extend(true, {}, option);
} catch (e) {
log.error(e);
}
},
getOption: function () {
try {
this._readProperty();
} catch (e) {
log.error(e);
}
return this._option;
},
setTheme: function (theme) {
try {
} catch (e) {
log.error(e);
}
},
resize: function () {
try {
} catch (e) {
log.error(e);
}
},
showLoading: function () {
try {
if (this._layout && this._layout.showLoading) {
this._layout.showLoading(this);
}
} catch (e) {
log.error(e);
}
},
hideLoading: function () {
try {
if (this._layout && this._layout.hideLoading) {
this._layout.hideLoading(this);
}
} catch (e) {
log.error(e);
}
},
dispose: function () {
try {
} catch (e) {
log.error(e);
}
},
getElement: function () {
return this._element;
}
getChart: function () {
return this._element;
}
});
return {
Chart: label,
Property: property
};
});
整体代码风格采用了AMD方式做了包装,此示例中采用了通用属性设计器的支持,所以返回类型包含Property
(通用属性部分详解请参见 指标通用属性 章节)
下面针对实现方法重点讲解:
- 所有指标插件的实现都要求采用
Chart.extend
方式继承平台接口,其Chart是通过define引用的"app/core/base"
脚本实例。 - 接口方法
constructor
是构造指标插件的实例的调用方法,通常放置一些与数据无关的类型定义等操作。方法参数传入页面布局实例对象。 - 接口方法
init
是初始化指标插件的调用方法,在这里一般会做指标插件的初始化操作。方法参数传入一个dom元素,是用来装载指标插件的HMTL element元素。方法支持返回 JavaScript Promises 对象,可以将一些异步初始化操作放置于此(如AMD异步资源加载、Ajax服务请求代码等),具体可参见如下:
同步初始化方式:
init: function (element) {
try {
this._uuid = $.uuid();
this._container = element;
} catch (e) {
log.error(e);
}
}
异步初始化方式:
init: function (element) {
try {
var _this = this;
var deferred = $.Deferred();
require([FindMapJsFile(this._option.Option.mapType)], function () {
_this._chart = ec.init(element, null, {
renderer: 'canvas'
});
_this._bindEvent();
deferred.resolve(_this._chart);
});
return deferred.promise();
} catch (e) {
log.error(e);
}
}
- 接口方法
example
是设计器调用加载示例数据的方法,在方法里需要准备一组示例数据初始化指标插件。 接口方法
setData
是指标插件绑定数据集后,数据集填充指标所需调用的方法,传入参数为数据json对象。{ "yuetongji": [ { "value": 312, "month": "一月" }, { "value": 142, "month": "二月" }, { "value": 412, "month": "三月" }, { "value": 421, "month": "四月" }, { "value": 234, "month": "五月" }, { "value": 785, "month": "六月" }, { "value": 249, "month": "七月" }, { "value": 675, "month": "八月" }, { "value": 689, "month": "九月" }, { "value": 642, "month": "十月" }, { "value": 423, "month": "十一月" }, { "value": 753, "month": "十二月" } ] }
接口方法
setOption
与getOption
是平台设计器在指标编辑时设置与获取指标设置参数的方法。{ "Binding": [ ], "Events": [ ], "Extend": { }, "Option": { } }
其中指标参数中Binding
为绑定对象,描述了绑定数据集的结构与信息,一般用于setData
操作中,示例结构如下:
"Binding": [
{
"Name": "月统计分析",
"Dimensions": [
{
"Code": "月份",
"Name": "月份",
"DataType": "string",
"AnalysisType": "dimension",
"Column": "month"
}
],
"Measures": [
{
"Code": "数值",
"Name": "2012年",
"DataType": "int",
"AnalysisType": "measure",
"Column": "value"
}
],
"DataSetCode": "yuetongji",
"PushFrequency": 0
}
]
指标参数的Events
为事件对象,描述了指标事件发生的参数信息,一般用于指标参数的事件处理逻辑中,ParamName
对应数据集定义的参数,实例结构如下:
"Events": [
{
"Event": "SeriesClick",
"Params": [
{
"ParamName":"#序列名称#",
"Value": "SeriesName",
"Name": "序列名称"
},
{
"ParamName":"#序列维度值#",
"Value": "Dimension",
"Name": "序列维度值"
},
{
"ParamName":"#序列度量值#",
"Value": "Measure",
"Name": "序列度量值"
}
],
"PageId": 18
}
]
指标参数的Extend
为扩展数据,一般用于存储通用属性设计器的设置信息,但不强制,可参见上面的示例代码处理方式。
指标参数的Option
为参数数据,一般用于存储指标的配置参数信息,在指标设计模式下的代码模式所加载的内容。
- 接口方法
resize
在窗体与容器变化时调用,需实现指标插件的重绘。 - 接口方法
showLoading
与hideLoading
用于显示与隐藏加载动画的操作。 - 接口方法
dispose
需实现指标插件的释放逻辑,回收资源。 - 接口方法
getElement
需返回指标插件的DOM对象。 - 接口方法
getChart
需返回指标插件的实例对象。