首次提交
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
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(",");
|
||||
|
||||
Reference in New Issue
Block a user