336 lines
12 KiB
JavaScript
336 lines
12 KiB
JavaScript
if(globalThis.Charts = globalThis.Charts || {});
|
|
globalThis.Charts.WaterFallChart = (function (lcjs) {
|
|
const RANGE_TIME_MS = 10 * 1000;
|
|
//#region 瀑布图
|
|
function WaterFallChart({ texts, board, container,btns, } = { texts: {},btns : [] }) {
|
|
var DefaultAxisYThickness = 65;
|
|
let { UseChartExtra } = globalThis.Charts;
|
|
let { AxisScrollStrategies, AxisTickStrategies, TimeFormattingFunctions, emptyLine, emptyFill, lightningChart } =
|
|
lcjs;
|
|
let { ColorHSV, LUT, PalettedFill, ColorCSS } = arctionJS.lcjs;
|
|
// Initialize chart.
|
|
let chart = null;
|
|
if (board) {
|
|
chart = board.createChartXY({
|
|
columnIndex: 0,
|
|
rowIndex: 1,
|
|
columnSpan: 1,
|
|
rowSpan: 1,
|
|
});
|
|
}
|
|
if (container) {
|
|
chart = lightningChart({
|
|
overrideInteractionMouseButtons:{
|
|
axisXYZoomMouseButton:2,// 右键框选放大
|
|
chartXYPanMouseButton:2,// 邮件按住移动
|
|
chartXYRectangleZoomFitMouseButton:0,// 左键按住框选(已屏蔽)
|
|
axisXYPanMouseButton:0, // 左键拖动XY轴
|
|
}
|
|
}).ChartXY({ container });
|
|
}
|
|
chart
|
|
.setTitle(false)
|
|
.setSeriesBackgroundFillStyle(emptyFill)
|
|
.setSeriesBackgroundFillStyle(emptyFill)
|
|
.setPadding(5)
|
|
.setPadding({ top: 0 })
|
|
.disableAnimations();
|
|
|
|
btns = btns||[];
|
|
let [_Context, _Events, _Methods, _EventsMapToMethods, _UIElements] =
|
|
UseChartExtra(chart);
|
|
let _DefaultAxisX = chart.getDefaultAxisX();
|
|
let _DefaultAxisY = chart.getDefaultAxisY();
|
|
let _DisplayAxisX = chart.addAxisX({ type: 'linear-highPrecision',}).setInterval(0,0,false,true);
|
|
Object.assign(_Context, {
|
|
period:100,
|
|
last:[],
|
|
cache: [],
|
|
resolution: 1920,
|
|
series: null,
|
|
updater:{
|
|
last:0,
|
|
timeout:100
|
|
}
|
|
});
|
|
Object.assign(_Methods, {
|
|
addData: (data) => {
|
|
if (_Context.paused) {
|
|
return;
|
|
}
|
|
_Context.updater.last = window.performance.now();
|
|
_Context.cache.push(data);
|
|
},
|
|
});
|
|
Object.assign(_Events, {
|
|
RESOLUTION_CHANGE: new EventHandle({
|
|
resolution: (val) => (_Context.resolution = val),
|
|
}),
|
|
});
|
|
_EventsMapToMethods();
|
|
|
|
//#region 设置 默认X轴
|
|
_DefaultAxisX
|
|
.setMouseInteractions(false)
|
|
.setTickStrategy(AxisTickStrategies.Empty);
|
|
//#endregion
|
|
|
|
//#region 设置 展示X轴
|
|
const _DefaultAxisXScaleChange = () => {
|
|
requestAnimationFrame(() => {
|
|
const _Chart = chart;
|
|
let { start, end } = _DefaultAxisX.getInterval();
|
|
_Methods.resolution((_Context.resolution = end - start));
|
|
});
|
|
};
|
|
_DefaultAxisX.onScaleChange(_DefaultAxisXScaleChange);
|
|
_Events["RESOLUTION_CHANGE"].on(
|
|
(val) => _Context.series != null && (_Context.series.Vm.resolution = val)
|
|
);
|
|
//#endregion
|
|
|
|
//#region 设置 默认Y轴
|
|
_DefaultAxisY
|
|
.setScrollStrategy(AxisScrollStrategies.progressive)
|
|
.setTickStrategy(AxisTickStrategies.Numeric, (strategy) =>
|
|
strategy
|
|
.setMajorFormattingFunction((val) =>
|
|
TimeFormattingFunctions.hhmmss(val)
|
|
)
|
|
.setMinorFormattingFunction((val) =>
|
|
TimeFormattingFunctions.hhmmss(val)
|
|
)
|
|
.setMajorTickStyle((style) => strategy.getMinorTickStyle())
|
|
)
|
|
.setInterval( -RANGE_TIME_MS,0)
|
|
.setThickness(DefaultAxisYThickness)
|
|
;
|
|
//#endregion
|
|
|
|
//#region 设置 数值对应的颜色
|
|
var defaultMaxDb = 120;
|
|
var defaultMinDb = -20;
|
|
|
|
function SetColorStyle(min,max){
|
|
|
|
if(!_Context.series)return;
|
|
var range = max - min;
|
|
var colors = globalThis.Charts.WaterFallChart.Colors;
|
|
var valueColors = [];
|
|
for(var i = 0 ; i < range ; i ++){
|
|
valueColors.push({value:i+min,color:colors[Math.floor(i / range * 256)]});
|
|
}
|
|
|
|
var steps = valueColors.map(({ value, color }) => ({
|
|
value: value,
|
|
label: value,
|
|
color: ColorCSS(color),
|
|
}));
|
|
const lut = new LUT({
|
|
steps: steps,
|
|
units: "dB",
|
|
interpolate: false,
|
|
});
|
|
const paletteFill = new PalettedFill({ lut, lookUpProperty: "value" });
|
|
_Context.series.setFillStyle(paletteFill)
|
|
}
|
|
|
|
Object.assign(_Methods, { SetColorStyle });
|
|
_Context.SetColorStyle = SetColorStyle;
|
|
//#endregion
|
|
function _CreateSeries() {
|
|
if (_Context.series != null) {
|
|
chart.getSeries()[0].dispose();
|
|
}
|
|
var { start } = _DefaultAxisY.getInterval();
|
|
|
|
_Context.series = chart
|
|
.addHeatmapScrollingGridSeries({
|
|
scrollDimension: "rows",
|
|
resolution: _Context.resolution,
|
|
start: { x: 0, y: 0 },
|
|
step: { x: 1, y: _Context.period },
|
|
})
|
|
.setWireframeStyle(emptyLine)
|
|
.setMouseInteractions(false)
|
|
.setDataCleaning({ minDataPointCount: 0 });
|
|
_Methods.SetColorStyle(defaultMinDb,defaultMaxDb);
|
|
_DefaultAxisY
|
|
.setScrollStrategy(AxisScrollStrategies.progressive)
|
|
.setTickStrategy(AxisTickStrategies.Numeric, (strategy) =>
|
|
strategy
|
|
//.setFormattingOffset(0)
|
|
.setMajorFormattingFunction((val) =>
|
|
TimeFormattingFunctions.hhmmss(val)
|
|
)
|
|
.setMinorFormattingFunction((val) =>
|
|
TimeFormattingFunctions.hhmmss(val)
|
|
)
|
|
.setMajorTickStyle((style) => strategy.getMinorTickStyle())
|
|
);
|
|
//.setInterval(0, -10 * 1000)
|
|
}
|
|
_Methods.reset = _CreateSeries;
|
|
window._Context = _Context;
|
|
_Events["PERIOD_CHANGE"].on((val) => {
|
|
_CreateSeries();
|
|
});
|
|
|
|
function spreadData(source, count) {
|
|
var length = source.length;
|
|
var multiple = Math.floor(count / length);
|
|
var remain = length - (count % length);
|
|
var target = [];
|
|
for (var i = 0; i < source.length; i++) {
|
|
var val = source[i];
|
|
for (var m = 0; m < multiple; m++) {
|
|
target.push(val);
|
|
}
|
|
if (i > remain) {
|
|
target.push(val);
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
//#region 添加 UI 组件
|
|
|
|
//#region 添加 名称
|
|
{
|
|
let element = _Methods.addText({
|
|
text: texts.title,
|
|
bgcolor: false,
|
|
name: "Title",
|
|
});
|
|
_UIElements.TopLeft.push(element);
|
|
}
|
|
//#endregion
|
|
//#region 添加 单位
|
|
{
|
|
let element = _Methods.addText({
|
|
text: texts.unit,
|
|
bgcolor: false,
|
|
name: "Unit",
|
|
});
|
|
_UIElements.TopRight.push(element);
|
|
}
|
|
|
|
//#endregion
|
|
//#region 添加 暂停
|
|
if(btns.indexOf("pause") > -1){
|
|
let _PauseEl = _Methods.addButton({
|
|
text: "暂停",
|
|
name: "Pause",
|
|
handle() {
|
|
_Context.paused ? _Methods.play() : _Methods.pause();
|
|
},
|
|
});
|
|
_Methods.onPausedChange((val) => {
|
|
val?_PauseEl.set("继续","#409eff"):_PauseEl.set("暂停","#113665");
|
|
});
|
|
_UIElements.RightTop.push(_PauseEl);
|
|
}
|
|
//#endregion
|
|
// 尺寸变化时
|
|
//fallChart.chart.getDefaultAxisY().getHeight() + 10;;
|
|
chart.onResize(() => _UIElements.LayoutUIElements());
|
|
requestAnimationFrame(() => {
|
|
_UIElements.LayoutUIElements(true);
|
|
});
|
|
//#endregion
|
|
|
|
|
|
var _count = 0;
|
|
var _RenderWorker = new WebWorker({
|
|
methods:{
|
|
start:(ctx,payload)=>{
|
|
ctx.last = performance.now();
|
|
let offset = 0;
|
|
ctx.period = payload.period;
|
|
function rAF() {
|
|
let now = performance.now();
|
|
let span = now - ctx.last;
|
|
let interval = ctx.period;
|
|
if (span > interval) {
|
|
ctx.last = now - span % interval;
|
|
let count = Math.floor(span / interval);
|
|
callback('render',{count});
|
|
}
|
|
requestAnimationFrame(rAF);
|
|
}
|
|
requestAnimationFrame(rAF);
|
|
},
|
|
addtime:(ctx,payload)=>{
|
|
ctx.addtime = performance.now();
|
|
}
|
|
},
|
|
callback(name,payload){
|
|
switch(name){
|
|
case 'render':{
|
|
let { count } = payload;
|
|
let values = _Context.cache.splice(0,count);
|
|
if (values.length == 0) {
|
|
values.push(_Context.last);
|
|
} else {
|
|
_Context.last = values.slice(-1)[0];
|
|
}
|
|
let now = performance.now();
|
|
if(now - _Context.updater.last < _Context.updater.timeout){
|
|
if (_Context.last.length > 1) {
|
|
if (values.length < count) {
|
|
values = spreadData(values, count);
|
|
}
|
|
_Context.series.addIntensityValues(values);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
})
|
|
//#region 按刷新率渲染
|
|
let _Render = ()=>{
|
|
let period = _Context.period;
|
|
_RenderWorker.call("start",{period})
|
|
//let intervalId = setTimeout(rAF,1000/60);
|
|
}
|
|
//#endregion
|
|
requestAnimationFrame(() => {
|
|
_DefaultAxisXScaleChange();
|
|
_CreateSeries();
|
|
// _Context.series.addIntensityValues((Array[]))
|
|
_Render();
|
|
});
|
|
let _expose = { chart };
|
|
{
|
|
_expose.Context = {};
|
|
Object.keys(_Context).forEach((key) => {
|
|
Object.defineProperty(_expose.Context, key, {
|
|
enumerable: true,
|
|
get() {
|
|
return _Context[key];
|
|
},
|
|
});
|
|
});
|
|
}
|
|
Object.keys(_Methods).forEach((key) => {
|
|
Object.defineProperty(_expose, key, {
|
|
enumerable: true,
|
|
get() {
|
|
return _Methods[key];
|
|
},
|
|
});
|
|
});
|
|
|
|
Object.assign(_expose, {
|
|
DisplayAxisX: _DisplayAxisX,
|
|
DefaultAxisX: _DefaultAxisX,
|
|
DefaultAxisY: _DefaultAxisY,
|
|
});
|
|
return _expose;
|
|
}
|
|
//#endregion
|
|
return WaterFallChart;
|
|
})(arctionJS.lcjs);
|
|
globalThis.Charts.WaterFallChart.Colors = "#000000,#000008,#000010,#000018,#000020,#000029,#000031,#000039,#000041,#00004a,#000052,#00005a,#000062,#00006a,#000073,#00007b,#000083,#00008b,#000094,#00009c,#0000a4,#0000ac,#0000b4,#0000bd,#0000c5,#0000cd,#0000d5,#0000de,#0000e6,#0000ee,#0000f6,#0000ff,#0000ff,#0006ff,#000dff,#0013ff,#001aff,#0020ff,#0027ff,#002dff,#0034ff,#003aff,#0041ff,#0047ff,#004eff,#0055ff,#005bff,#0062ff,#0068ff,#006fff,#0075ff,#007cff,#0082ff,#0089ff,#008fff,#0096ff,#009cff,#00a3ff,#00aaff,#00b0ff,#00b7ff,#00bdff,#00c4ff,#00caff,#00d1ff,#00d7ff,#00deff,#00e4ff,#00ebff,#00f1ff,#00f8ff,#00ffff,#00ffff,#00fff3,#00ffe8,#00ffdd,#00ffd2,#00ffc7,#00ffbc,#00ffb1,#00ffa6,#00ff9b,#00ff90,#00ff85,#00ff79,#00ff6e,#00ff63,#00ff58,#00ff4d,#00ff42,#00ff37,#00ff2c,#00ff21,#00ff16,#00ff0b,#00ff00,#00ff00,#0dff00,#1aff00,#28ff00,#35ff00,#43ff00,#50ff00,#5dff00,#6bff00,#78ff00,#86ff00,#93ff00,#a1ff00,#aeff00,#bbff00,#c9ff00,#d6ff00,#e4ff00,#f1ff00,#ffff00,#ffff00,#fffb00,#fff700,#fff300,#ffef00,#ffeb00,#ffe800,#ffe400,#ffe000,#ffdc00,#ffd800,#ffd500,#ffd100,#ffcd00,#ffc900,#ffc500,#ffc200,#ffbe00,#ffba00,#ffb600,#ffb200,#ffaf00,#ffab00,#ffa700,#ffa300,#ff9f00,#ff9c00,#ff9800,#ff9400,#ff9000,#ff8c00,#ff8900,#ff8500,#ff8100,#ff7d00,#ff7900,#ff7500,#ff7200,#ff6e00,#ff6a00,#ff6600,#ff6200,#ff5f00,#ff5b00,#ff5700,#ff5300,#ff4f00,#ff4c00,#ff4800,#ff4400,#ff4000,#ff3c00,#ff3900,#ff3500,#ff3100,#ff2d00,#ff2900,#ff2600,#ff2200,#ff1e00,#ff1a00,#ff1600,#ff1300,#ff0f00,#ff0b00,#ff0700,#ff0300,#ff0000,#ff0000,#ff0001,#ff0003,#ff0005,#ff0007,#ff0009,#ff000a,#ff000c,#ff000e,#ff0010,#ff0012,#ff0014,#ff0015,#ff0017,#ff0019,#ff001b,#ff001d,#ff001f,#ff0020,#ff0022,#ff0024,#ff0026,#ff0028,#ff002a,#ff002b,#ff002d,#ff002f,#ff0031,#ff0033,#ff0035,#ff0036,#ff0038,#ff003a,#ff003c,#ff003e,#ff0040,#ff0041,#ff0043,#ff0045,#ff0047,#ff0049,#ff004a,#ff004c,#ff004e,#ff0050,#ff0052,#ff0054,#ff0055,#ff0057,#ff0059,#ff005b,#ff005d,#ff005f,#ff0060,#ff0062,#ff0064,#ff0066,#ff0068,#ff006a,#ff006b,#ff006d,#ff006f,#ff0071,#ff0073,#ff0075,#ff0076,#ff0078,#ff007a,#ff007c,#ff007e,#ff0080,#ff0081".split(",");
|
|
|