Files
2026-06-16 11:24:50 +08:00

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(",");