Design and Implementation of a Generalized Data Visualization Big‑Screen Platform
This article explains the motivation, architecture, technology stack, adaptive layout techniques, component development workflow, drag‑and‑drop enhancements, and real‑time state management used to build a low‑code, front‑end‑focused big‑screen data visualization platform.
In recent years, many product platforms have tried visual low‑code construction to lower the development threshold of GUI applications and improve efficiency; as data needs grow, big‑screen visualizations have become a popular way to present large‑scale data in exhibitions, showrooms, and press conferences.
The article first introduces data visualization from both technical (Echarts, AntV, Chart.js, D3.js, Vega) and business perspectives, emphasizing the transformation data → chart combination → visual page that makes complex data easier to understand.
Design ideas include the following technical selections: React full‑stack as the front‑end framework, Echarts and DataV‑React for high‑level chart components, D3.js for fine‑grained custom visualizations, dnd‑kit for tree‑structured drag‑and‑drop, and React‑Grid‑Layout for flexible grid layouts.
The overall architecture consists of four key subsystems: a visual material center that defines a DSL protocol for 40+ reusable components, a canvas editor (the core low‑code builder) handling layout, interaction, and data configuration, a data center that connects to MySQL, ClickHouse, Elasticsearch, Presto, etc., and a management center for template management, publishing, and access control.
Adaptive layout is achieved through two approaches. The first uses vh , vw , and rem units with a base font size calculated from the design width:
// vw vh units w3c official explanation
// vw: 1% of viewport width, vh: 1% of viewport height
body,html { font-size: 5.208vw; }The second approach employs a font.js script that recalculates the root font size on resize/orientation change:
(function(doc, win) {
const docEl = doc.documentElement;
const resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
const recalc = function() {
let clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = 100 * (clientWidth / 1920) + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);When third‑party plugins use px units, the article notes the need for transform: scale(X, Y) scaling based on container size, allowing equal‑height, equal‑width, or full‑screen scaling modes.
Component development follows a three‑layer model: component (React component body), schema (DSL configuration protocol), and definition (type, hierarchy, default size). Example Echarts initialization and event binding code is provided:
// initialization echarts
const renderNewEcharts = () => {
const echartObj = updateEChartsOption();
bindEvents(echartObj, onEvents || {});
if (typeof onChartReady === 'function') onChartReady(echartObj);
echartObj.resize();
};
const bindEvents = (instance, events) => {
const _bindEvent = (eventName, func) => {
instance.on(eventName, (param) => { func(param, instance); });
};
for (const eventName in events) {
if (Object.prototype.hasOwnProperty.call(events, eventName)) {
_bindEvent(eventName, events[eventName]);
}
}
};
const dispose = () => {
if ($chartEl.current) {
clear($chartEl.current);
(echartsLib || echarts).dispose($chartEl.current);
}
};A similar pattern is used for DataV‑React components, with resize listeners and cleanup logic.
The schema DSL defines fields such as headerGroupName , name , valueType , UI widget type, dependencies, and data binding keys, enabling dynamic form generation from simple Excel inputs.
Drag‑and‑drop enhancements extend React‑Grid‑Layout to support free layout, locked aspect ratios, rotation, and z‑index stacking. Example code shows CSS transform handling and z‑index increment logic:
// CSS Transforms support (default)
if (useCSSTransforms) {
if (activeResize) {
const { width, height, handle } = activeResize;
const clonePos = { ...pos };
if (["w","nw","sw"].includes(handle)) {
clonePos.left -= clonePos.width - width;
}
if (["n","nw","ne"].includes(handle)) {
clonePos.top -= clonePos.height - height;
}
style = setTransform(clonePos, this.props.angle);
} else {
style = setTransform(pos, this.props.angle);
}
}
const getAfterMaxZIndex = useCallback(i => {
if (i === curDragItemI) return;
setCurDragItemI(i);
setMaxZIndex(maxZIndex => maxZIndex + 1);
return maxZIndex;
}, []);For real‑time state management, a WebSocket‑based long‑connection with heartbeat and reconnection is implemented to push version updates or take a big screen offline.
The article concludes with a preview of the platform’s visual effects and a summary that the presented low‑code, schema‑driven approach satisfies core big‑screen requirements, while future work will focus on expanding component libraries, building a visual material ecosystem, and adding 3D/animation rendering capabilities.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.