vislite
Version:
灵活、快速、简单的数据可视化交互式跨端前端库
506 lines (487 loc) • 18.8 kB
JavaScript
function initOption(setOption, defaultOption) {
for (var key in setOption) {
defaultOption[key] = setOption[key];
}
return defaultOption;
}
function ruler (maxValue, minValue, num, option) {
if (maxValue < minValue) {
var temp = minValue;
minValue = maxValue;
maxValue = temp;
}
else if (maxValue == minValue) {
return [maxValue];
}
var times100 = (function (_value) {
var _times100_base = (_value < 100 && _value > -100) ? 10 : 0.1;
var _times100 = -1, _tiemsValue = _value;
while (_times100_base == 10 ?
(_tiemsValue >= -100 && _tiemsValue <= 100)
:
(_tiemsValue <= -100 || _tiemsValue >= 100)) {
_times100 += 1;
_tiemsValue *= _times100_base;
}
if (_times100_base == 10) {
return Math.pow(10, _times100);
}
else {
var temp = "0.";
for (var i = 1; i < _times100; i++) {
temp += "0";
}
return +(temp + "1");
}
})(maxValue - minValue);
var distance100_oral = Math.ceil((maxValue - minValue) * times100 / num);
var getResult = function (changValue) {
var distance100 = {
3: 2,
4: 5,
6: 5,
7: 5,
8: 10,
9: 10,
11: 10,
12: 10,
13: 15,
14: 15,
16: 15,
17: 15,
18: 20,
19: 20,
21: 20,
22: 20,
23: 25,
24: 25,
26: 25,
27: 25
}[distance100_oral + changValue] || (distance100_oral + changValue);
var distance = distance100 / times100;
var begin = Math.floor(minValue / distance) * distance;
var rulerArray = [];
rulerArray.push(begin);
for (var index = 1; rulerArray[rulerArray.length - 1] < maxValue; index++) {
rulerArray.push(begin + distance * index);
}
return rulerArray;
};
var rulerArray = getResult(0);
var balanceMax = function () {
var rulerArray_temp = [];
var changeDist = rulerArray[rulerArray.length - 1] - (option === null || option === void 0 ? void 0 : option.max);
for (var index = 0; index < rulerArray.length; index++) {
if (index + 1 < rulerArray.length && rulerArray[index + 1] - changeDist < minValue) ;
else {
rulerArray_temp.push(rulerArray[index] - changeDist);
}
}
return rulerArray_temp;
};
var balanceMin = function () {
var rulerArray_temp = [];
var changeDist = rulerArray[0] - (option === null || option === void 0 ? void 0 : option.min);
for (var index = 0; index < rulerArray.length; index++) {
rulerArray_temp[index] = rulerArray[index] - changeDist;
if (maxValue <= rulerArray_temp[index])
break;
}
return rulerArray_temp;
};
if (option) {
if ('max' in option && 'min' in option && option.max >= maxValue && option.min <= minValue) {
var isAnswer = function () {
if (rulerArray[0] >= option.min && rulerArray[rulerArray.length - 1] <= option.max)
return true;
var rulerArray_max = balanceMax();
if (rulerArray_max[0] >= option.min && rulerArray_max[rulerArray_max.length - 1] <= option.max) {
rulerArray = rulerArray_max;
return true;
}
var rulerArray_min = balanceMin();
if (rulerArray_min[0] >= option.min && rulerArray_min[rulerArray_max.length - 1] <= option.max) {
rulerArray = rulerArray_min;
return true;
}
};
if (isAnswer())
return rulerArray;
for (var changValue = 1; changValue < 100; changValue++) {
rulerArray = getResult(changValue);
if (isAnswer())
return rulerArray;
rulerArray = getResult(-changValue);
if (isAnswer())
return rulerArray;
}
}
if ('max' in option && option.max >= maxValue) {
if (option.max < rulerArray[rulerArray.length - 1]) {
rulerArray = balanceMax();
}
}
else if ('min' in option && option.min <= minValue) {
if (option.min > rulerArray[0]) {
rulerArray = balanceMin();
}
}
}
for (var index = 0; index < rulerArray.length; index++) {
var valStr = rulerArray[index] + "";
if (/\./.test(valStr)) {
if (/9{7,}$/.test(valStr)) {
valStr = valStr.replace(/9{7,}$/, '');
rulerArray[index] = +(valStr.substring(0, valStr.length - 1) + ((+valStr[valStr.length - 1]) + 1));
}
else if (/0{7,}\d$/.test(valStr)) {
rulerArray[index] = +(valStr.replace(/0{7,}\d$/, ''));
}
}
}
return rulerArray;
}
//当前正在运动的动画的tick函数堆栈
let $timers = [];
//唯一定时器的定时间隔
let $interval = 13;
//定时器ID
let $timerId;
/**
* 动画轮播
* @param {function} doback 轮询函数,有一个形参deep,0-1,表示执行进度
* @param {number} duration 动画时长,可选
* @param {function} callback 动画结束回调,可选,有一个形参deep,0-1,表示执行进度
*
* @returns {object} 返回一个对象,包含一个stop方法,用于在动画结束前结束动画
*/
function animation(doback, duration, callback) {
if (arguments.length < 2) duration = 400;
if (arguments.length < 3) callback = function () { };
let clock = {
//把tick函数推入堆栈
"timer": function (tick, duration, callback) {
if (!tick) {
throw new Error('Tick is required!');
}
let id = new Date().valueOf() + "_" + (Math.random() * 1000).toFixed(0);
$timers.push({
"id": id,
"createTime": new Date(), // 开始时间
"pauseTime": -1, // 暂停的时间,继续运行的时候,借助此计算暂停的时间差
"pauseKeepTime": 0, // 暂停用去的时间
"status": "running", // running(运行中), paused(暂停中)
"tick": tick,
"duration": duration,
"callback": callback
});
clock.start();
return id;
},
//开启唯一的定时器timerId
"start": function () {
if (!$timerId) {
try {
if (globalThis && globalThis.requestAnimationFrame) {
$timerId = globalThis.requestAnimationFrame(function step() {
clock.tick();
if ($timerId) $timerId = globalThis.requestAnimationFrame(step);
});
} else {
$timerId = setInterval(clock.tick, $interval);
}
} catch (e) {
$timerId = setInterval(clock.tick, $interval);
}
}
},
//被定时器调用,遍历timers堆栈
"tick": function () {
let createTime, flag, tick, callback, timer, duration, passTime, timers = $timers;
$timers = [];
$timers.length = 0;
for (flag = 0; flag < timers.length; flag++) {
//初始化数据
timer = timers[flag];
createTime = timer.createTime;
tick = timer.tick;
duration = timer.duration;
callback = timer.callback;
//执行
passTime = (+new Date().valueOf() - createTime.valueOf() - timer.pauseKeepTime) / duration;
passTime = passTime > 1 ? 1 : passTime;
if (timer.status === "running") {
tick(passTime);
}
// 只有当动画没有结束或者动画处于暂停状态时,才继续添加到timers堆栈
if ((passTime < 1 || timer.status === "paused") && timer.id) {
//动画没有结束再添加
$timers.push(timer);
} else {
callback(passTime);
}
}
if ($timers.length <= 0) {
clock.stop();
}
},
//停止定时器,重置timerId=null
"stop": function () {
if ($timerId) {
try {
if (globalThis && globalThis.requestAnimationFrame) globalThis.cancelAnimationFrame($timerId);
else clearInterval($timerId);
} catch (e) {
clearInterval($timerId);
}
$timerId = null;
}
}
};
let id = clock.timer(function (deep) {
//其中deep为0-1,表示改变的程度
doback(deep);
}, duration, callback);
return {
// 结束动画
stop: function () {
for (let i in $timers) {
if ($timers[i].id == id) {
$timers[i].id = void 0;
}
}
},
// 暂停动画
pause: function () {
for (let i in $timers) {
if ($timers[i].id == id) {
if ($timers[i].pauseTime === -1) {
$timers[i].pauseTime = new Date();
$timers[i].status = "paused";
}
}
}
},
// 继续动画
resume: function () {
for (let i in $timers) {
if ($timers[i].id == id) {
if ($timers[i].pauseTime !== -1) {
$timers[i].pauseKeepTime += (new Date().valueOf() - $timers[i].pauseTime.valueOf());
$timers[i].pauseTime = -1;
$timers[i].status = "running";
}
}
}
}
};
}
var BarLayout = (function () {
function BarLayout(config) {
if (config === void 0) { config = {}; }
this.name = 'BarLayout';
this.__option = {
x: 50,
y: 350,
width: 400,
height: 300,
category: "xAxis",
duration: 200
};
this.__config = initOption(config, {});
}
BarLayout.prototype.setOption = function (option) {
initOption(option, this.__option);
return this;
};
BarLayout.prototype.use = function (initBar) {
var bar = {
coordinate: {
x: this.__option.x,
y: this.__option.y,
width: this.__option.width,
height: this.__option.height,
xAxis: {
type: this.__option.category === "xAxis" ? "category" : "value",
data: []
},
yAxis: {
type: this.__option.category === "xAxis" ? "value" : "category",
data: []
}
},
node: []
};
var maxValue = void 0, minValue = void 0;
if (initBar.data) {
for (var _i = 0, _a = initBar.data; _i < _a.length; _i++) {
var val = _a[_i];
if (maxValue === void 0 || val > maxValue)
maxValue = val;
if (minValue === void 0 || val < minValue)
minValue = val;
}
}
else if (initBar.value) {
for (var _b = 0, _c = initBar.value; _b < _c.length; _b++) {
var item = _c[_b];
for (var _d = 0, _e = item.data; _d < _e.length; _d++) {
var val = _e[_d];
if (maxValue === void 0 || val > maxValue)
maxValue = val;
if (minValue === void 0 || val < minValue)
minValue = val;
}
}
}
else {
throw new Error('No data leads to parsing errors');
}
var rulerArray = ruler(maxValue || 0, minValue || 0, 5);
var categoryLen;
var valueLen;
if (this.__option.category === "xAxis") {
bar.coordinate.xAxis.data = initBar.category;
bar.coordinate.yAxis.data = rulerArray;
categoryLen = this.__option.width;
valueLen = -1 * this.__option.height;
}
else {
bar.coordinate.xAxis.data = rulerArray;
bar.coordinate.yAxis.data = initBar.category;
categoryLen = this.__option.height;
valueLen = this.__option.width;
}
var category = [];
var categorySingle1Width = categoryLen / initBar.category.length;
var categorySingle2Width = categorySingle1Width * 0.9;
var categoryStart = categorySingle1Width * 0.05;
if (initBar.data) {
for (var i = 0; i < initBar.data.length; i++) {
category.push([
categoryStart + categorySingle1Width * i,
categorySingle2Width
]);
}
}
else {
var categorySingle3Width = categorySingle2Width / initBar.value.length;
var categorySingle4Width = categorySingle3Width * 0.9;
var categoryStartBlance = categorySingle3Width * 0.05;
for (var i = 0; i < initBar.value[0].data.length; i++) {
category[i] = [];
for (var j = 0; j < initBar.value.length; j++) {
category[i].push([
categoryStart + categorySingle1Width * i + categorySingle3Width * j + categoryStartBlance,
categorySingle4Width
]);
}
}
}
var singleValueLen = valueLen / (rulerArray[rulerArray.length - 1] - rulerArray[0]);
var getLenByValue = function (value) {
return singleValueLen * (value - rulerArray[0]);
};
if (this.__option.category === "xAxis") {
if (initBar.data) {
var nodeBar = [];
for (var i = 0; i < initBar.data.length; i++) {
nodeBar.push({
x: this.__option.x + category[i][0],
y: this.__option.y,
width: category[i][1],
height: getLenByValue(initBar.data[i]),
value: initBar.data[i]
});
}
bar.node.push({
bar: nodeBar
});
}
else {
for (var j = 0; j < initBar.value.length; j++) {
var nodeBar = [];
for (var i = 0; i < initBar.value[j].data.length; i++) {
nodeBar.push({
x: this.__option.x + category[i][j][0],
y: this.__option.y,
width: category[i][j][1],
height: getLenByValue(initBar.value[j].data[i]),
value: initBar.value[j].data[i]
});
}
bar.node.push({
name: initBar.value[j].name,
bar: nodeBar
});
}
}
}
else {
if (initBar.data) {
var nodeBar = [];
for (var i = 0; i < initBar.data.length; i++) {
nodeBar.push({
x: this.__option.x,
y: this.__option.y - this.__option.height + category[i][0],
width: getLenByValue(initBar.data[i]),
height: category[i][1],
value: initBar.data[i]
});
}
bar.node.push({
bar: nodeBar
});
}
else {
for (var j = 0; j < initBar.value.length; j++) {
var nodeBar = [];
for (var i = 0; i < initBar.value[j].data.length; i++) {
nodeBar.push({
x: this.__option.x,
y: this.__option.y - this.__option.height + category[i][j][0],
width: getLenByValue(initBar.value[j].data[i]),
height: category[i][j][1],
value: initBar.value[j].data[i]
});
}
bar.node.push({
name: initBar.value[j].name,
bar: nodeBar
});
}
}
}
return bar;
};
BarLayout.prototype.bind = function (initBar, renderBack) {
this.__rback = renderBack;
this.__oralBar = initBar;
this.__preBar = this.use(this.__oralBar);
this.__rback(this.__preBar);
return this;
};
BarLayout.prototype.unbind = function () {
this.__rback = function () { return null; };
this.__oralBar = null;
this.__preBar = null;
return this;
};
BarLayout.prototype.doUpdate = function () {
var _this = this;
var newBar = this.use(this.__oralBar);
var cacheBar = JSON.parse(JSON.stringify(newBar));
animation(function (deep) {
if (_this.__preBar) ;
else {
_this.__rback(cacheBar);
}
}, this.__option.duration, function () {
_this.__preBar = newBar;
_this.__rback(_this.__preBar);
});
return this;
};
return BarLayout;
}());
export { BarLayout as default };