Index: arms/html/analysisScope/content-container.html
===================================================================
diff -u -rf53218e3b68e19c2d17937b91a3f130ca5f8345b -r6993b6519461e4671fc8f57194e14912edf6bdda
--- arms/html/analysisScope/content-container.html (.../content-container.html) (revision f53218e3b68e19c2d17937b91a3f130ca5f8345b)
+++ arms/html/analysisScope/content-container.html (.../content-container.html) (revision 6993b6519461e4671fc8f57194e14912edf6bdda)
@@ -674,7 +674,7 @@
Index: arms/js/analysis/mockData/circularPackingEx.json
===================================================================
diff -u
--- arms/js/analysis/mockData/circularPackingEx.json (revision 0)
+++ arms/js/analysis/mockData/circularPackingEx.json (revision 6993b6519461e4671fc8f57194e14912edf6bdda)
@@ -0,0 +1,239 @@
+{
+ "Baseversion": {
+ "$count": 1250,
+ "yAxisIndex": {
+ "$count": 100
+ },
+ "startValue": {
+ "$count": 300
+ },
+ "endValue": {
+ "$count": 500
+ },
+ "xAxisIndex": {
+ "$count": 700
+ },
+ "angleAxisIndex": {
+ "$count": 900
+ },
+ "filterMode": {
+ "$count": 1100
+ },
+ "type": {
+ "$count": 900
+ },
+ "start": {
+ "$count": 700
+ },
+ "orient": {
+ "$count": 500
+ },
+ "radiusAxisIndex": {
+ "$count": 300
+ },
+ "throttle": {
+ "$count": 100
+ },
+ "end": {
+ "$count": 100
+ },
+ "zoomLock": {
+ "$count": 200
+ }
+ },
+ "버전1_0_1": {
+ "$count": 3744,
+ "요구사항1": {
+ "$count": 757,
+ "title": {
+ "$count": 55,
+ "zoom": {
+ "$count": 23
+ },
+ "back": {
+ "$count": 14
+ }
+ },
+ "show": {
+ "$count": 650
+ },
+ "iconStyle": {
+ "normal": {
+ "$count": 20,
+ "shadowBlur": {
+ "$count": 1
+ },
+ "color": {
+ "$count": 1
+ },
+ "borderColor": {
+ "$count": 1
+ }
+ },
+ "$count": 38,
+ "emphasis": {
+ "$count": 11,
+ "color": {
+ "$count": 1
+ }
+ }
+ },
+ "yAxisIndex": {
+ "$count": 43
+ },
+ "xAxisIndex": {
+ "$count": 75
+ },
+ "icon": {
+ "$count": 33,
+ "zoom": {
+ "$count": 26
+ },
+ "back": {
+ "$count": 15
+ }
+ }
+ },
+ "요구사항2": {
+ "type": {
+ "$count": 121
+ },
+ "$count": 692,
+ "backgroundColor": {
+ "$count": 99
+ },
+ "excludeComponents": {
+ "$count": 125
+ },
+ "show": {
+ "$count": 97
+ },
+ "title": {
+ "$count": 98
+ },
+ "icon": {
+ "$count": 128
+ },
+ "iconStyle": {
+ "normal": {
+ "$count": 52,
+ "color": {
+ "$count": 19
+ },
+ "opacity": {
+ "$count": 7
+ },
+ "shadowOffsetY": {
+ "$count": 3
+ },
+ "shadowOffsetX": {
+ "$count": 7
+ },
+ "shadowBlur": {
+ "$count": 12
+ },
+ "shadowColor": {
+ "$count": 11
+ },
+ "borderColor": {
+ "$count": 14
+ },
+ "borderWidth": {
+ "$count": 5
+ }
+ },
+ "emphasis": {
+ "$count": 61,
+ "color": {
+ "$count": 10
+ },
+ "shadowBlur": {
+ "$count": 3
+ },
+ "opacity": {
+ "$count": 4
+ },
+ "borderColor": {
+ "$count": 4
+ },
+ "shadowOffsetX": {
+ "$count": 2
+ },
+ "shadowColor": {
+ "$count": 3
+ },
+ "shadowOffsetY": {
+ "$count": 1
+ },
+ "borderWidth": {
+ "$count": 1
+ }
+ },
+ "$count": 87
+ },
+ "pixelRatio": {
+ "$count": 9
+ },
+ "name": {
+ "$count": 14
+ }
+ },
+ "요구사항3": {
+ "$count": 681
+ },
+ "restore": {
+ "$count": 383,
+ "iconStyle": {
+ "normal": {
+ "borderColor": {
+ "$count": 7
+ },
+ "$count": 33,
+ "color": {
+ "$count": 12
+ },
+ "shadowColor": {
+ "$count": 4
+ },
+ "opacity": {
+ "$count": 7
+ },
+ "shadowOffsetX": {
+ "$count": 3
+ },
+ "shadowBlur": {
+ "$count": 6
+ },
+ "borderWidth": {
+ "$count": 4
+ },
+ "shadowOffsetY": {
+ "$count": 3
+ }
+ },
+ "$count": 24,
+ "emphasis": {
+ "shadowBlur": {
+ "$count": 1
+ },
+ "$count": 20,
+ "color": {
+ "$count": 1
+ },
+ "borderColor": {
+ "$count": 1
+ }
+ }
+ },
+ "show": {
+ "$count": 35
+ },
+ "title": {
+ "$count": 24
+ },
+ "icon": {
+ "$count": 35
+ }
+ }
+ }
+}
\ No newline at end of file
Index: arms/js/analysis/resource/chart/circularPackingChart.js
===================================================================
diff -u
--- arms/js/analysis/resource/chart/circularPackingChart.js (revision 0)
+++ arms/js/analysis/resource/chart/circularPackingChart.js (revision 6993b6519461e4671fc8f57194e14912edf6bdda)
@@ -0,0 +1,413 @@
+function exampleCircularPackingChart() {
+ var chartDom = document.getElementById('circularPacking');
+ var myChart = echarts.init(chartDom);
+ var option;
+
+ $.when(
+ $.get("./js/analysis/mockData/circularPackingEx.json"),
+ $.getScript(
+ "./js/analysisTime/d3.v5.min.js"
+ // "../reference/jquery-plugins/d3-7.8.2/dist/d3.min.js"
+ /*'https://fastly.jsdelivr.net/npm/d3-hierarchy@2.0.0/dist/d3-hierarchy.min.js'*/
+ )
+ ).done(function (res) {
+ run(res[0]);
+ });
+ function run(rawData) {
+ const dataWrap = prepareData(rawData);
+ console.log(dataWrap);
+ initChart(dataWrap.seriesData, dataWrap.maxDepth);
+ }
+ function prepareData(rawData) {
+ const seriesData = [];
+ let maxDepth = 0;
+ function convert(source, basePath, depth) {
+ if (source == null) {
+ return;
+ }
+ if (maxDepth > 5) {
+ return;
+ }
+ maxDepth = Math.max(depth, maxDepth);
+ seriesData.push({
+ id: basePath,
+ value: source.$count,
+ depth: depth,
+ index: seriesData.length
+ });
+ for (var key in source) {
+ if (source.hasOwnProperty(key) && !key.match(/^\$/)) {
+ var path = basePath + '.' + key;
+ convert(source[key], path, depth + 1);
+ }
+ }
+ }
+ convert(rawData, '제품-이름', 0);
+ return {
+ seriesData: seriesData,
+ maxDepth: maxDepth
+ };
+ }
+ function initChart(seriesData, maxDepth) {
+ var displayRoot = stratify();
+ function stratify() {
+ return d3
+ .stratify()
+ .parentId(function (d) {
+ return d.id.substring(0, d.id.lastIndexOf('.'));
+ })(seriesData)
+ .sum(function (d) {
+ return d.value || 0;
+ })
+ .sort(function (a, b) {
+ return b.value - a.value;
+ });
+ }
+ function overallLayout(params, api) {
+ var context = params.context;
+ d3
+ .pack()
+ .size([api.getWidth() - 2, api.getHeight() - 2])
+ .padding(3)(displayRoot);
+ context.nodes = {};
+ displayRoot.descendants().forEach(function (node, index) {
+ context.nodes[node.id] = node;
+ });
+ }
+ function renderItem(params, api) {
+ var context = params.context;
+ // Only do that layout once in each time `setOption` called.
+ if (!context.layout) {
+ context.layout = true;
+ overallLayout(params, api);
+ }
+ var nodePath = api.value('id');
+ var node = context.nodes[nodePath];
+ if (!node) {
+ // Reder nothing.
+ return;
+ }
+ var isLeaf = !node.children || !node.children.length;
+ var focus = new Uint32Array(
+ node.descendants().map(function (node) {
+ return node.data.index;
+ })
+ );
+ var nodeName = isLeaf
+ ? nodePath
+ .slice(nodePath.lastIndexOf('.') + 1)
+ .split(/(?=[A-Z][^A-Z])/g)
+ .join('\n')
+ : '';
+ var z2 = api.value('depth') * 2;
+ return {
+ type: 'circle',
+ focus: focus,
+ shape: {
+ cx: node.x,
+ cy: node.y,
+ r: node.r
+ },
+ transition: ['shape'],
+ z2: z2,
+ textContent: {
+ type: 'text',
+ style: {
+ // transition: isLeaf ? 'fontSize' : null,
+ text: nodeName,
+ fontFamily: 'Arial',
+ width: node.r * 1.3,
+ overflow: 'truncate',
+ fontSize: node.r / 3
+ },
+ emphasis: {
+ style: {
+ overflow: null,
+ fontSize: Math.max(node.r / 3, 12)
+ }
+ }
+ },
+ textConfig: {
+ position: 'inside'
+ },
+ style: {
+ fill: api.visual('color')
+ },
+ emphasis: {
+ style: {
+ fontFamily: 'Arial',
+ fontSize: 12,
+ shadowBlur: 20,
+ shadowOffsetX: 3,
+ shadowOffsetY: 5,
+ shadowColor: 'rgba(0,0,0,0.3)'
+ }
+ }
+ };
+ }
+ option = {
+ dataset: {
+ source: seriesData
+ },
+ tooltip: {},
+ visualMap: [
+ {
+ show: false,
+ min: 0,
+ max: maxDepth,
+ dimension: 'depth',
+ inRange: {
+ color: ["#264961", "#4A8FBD", "#82A5BD", "#5E7788", "#5D8AA8", "#2c5571"]//['#006edd', '#e0ffff']
+ }
+ }
+ ],
+ hoverLayerThreshold: Infinity,
+ series: {
+ type: 'custom',
+ renderItem: renderItem,
+ progressive: 0,
+ coordinateSystem: 'none',
+ encode: {
+ tooltip: 'value',
+ itemName: 'id'
+ }
+ }
+ };
+ myChart.setOption(option);
+ myChart.on('click', { seriesIndex: 0 }, function (params) {
+ drillDown(params.data.id);
+ });
+ function drillDown(targetNodeId) {
+ displayRoot = stratify();
+ if (targetNodeId != null) {
+ displayRoot = displayRoot.descendants().find(function (node) {
+ return node.data.id === targetNodeId;
+ });
+ }
+ // A trick to prevent d3-hierarchy from visiting parents in this algorithm.
+ displayRoot.parent = null;
+ myChart.setOption({
+ dataset: {
+ source: seriesData
+ }
+ });
+ }
+ // Reset: click on the blank area.
+ myChart.getZr().on('click', function (event) {
+ if (!event.target) {
+ drillDown();
+ }
+ });
+ }
+
+ option && myChart.setOption(option, true);
+ window.addEventListener('resize', function () {
+ myChart.resize();
+ });
+}
+
+function drawCircularPacking(target, psServiceName) {
+ var chartDom = document.getElementById('circularPacking');
+ var myChart = echarts.init(chartDom);
+ var option;
+
+ $.when(
+ $.get("./js/analysis/mockData/circularPackingEx.json"),
+ $.getScript(
+ "./js/analysisTime/d3.v5.min.js"
+ )
+ ).done(function (res) {
+ run(res[0]);
+ });
+ function run(rawData) {
+ const dataWrap = prepareData(rawData);
+ initChart(dataWrap.seriesData, dataWrap.maxDepth);
+ }
+ function prepareData(rawData) {
+ const seriesData = [];
+ let maxDepth = 0;
+ function convert(source, basePath, depth) {
+ if (source == null) {
+ return;
+ }
+ if (maxDepth > 5) {
+ return;
+ }
+ maxDepth = Math.max(depth, maxDepth);
+ seriesData.push({
+ id: basePath,
+ value: source.$count,
+ depth: depth,
+ index: seriesData.length
+ });
+ for (var key in source) {
+ if (source.hasOwnProperty(key) && !key.match(/^\$/)) {
+ var path = basePath + '.' + key;
+ convert(source[key], path, depth + 1);
+ }
+ }
+ }
+ convert(rawData, psServiceName, 0); // 첫번째 Node 이름 설정.
+ return {
+ seriesData: seriesData,
+ maxDepth: maxDepth
+ };
+ }
+ function initChart(seriesData, maxDepth) {
+ var displayRoot = stratify();
+ function stratify() {
+ return d3
+ .stratify()
+ .parentId(function (d) {
+ return d.id.substring(0, d.id.lastIndexOf('.'));
+ })(seriesData)
+ .sum(function (d) {
+ return d.value || 0;
+ })
+ .sort(function (a, b) {
+ return b.value - a.value;
+ });
+ }
+ function overallLayout(params, api) {
+ var context = params.context;
+ d3
+ .pack()
+ .size([api.getWidth() - 2, api.getHeight() - 2])
+ .padding(3)(displayRoot);
+ context.nodes = {};
+ displayRoot.descendants().forEach(function (node, index) {
+ context.nodes[node.id] = node;
+ });
+ }
+ function renderItem(params, api) {
+ var context = params.context;
+ // Only do that layout once in each time `setOption` called.
+ if (!context.layout) {
+ context.layout = true;
+ overallLayout(params, api);
+ }
+ var nodePath = api.value('id');
+ var node = context.nodes[nodePath];
+ if (!node) {
+ // Reder nothing.
+ return;
+ }
+ var isLeaf = !node.children || !node.children.length;
+ var focus = new Uint32Array(
+ node.descendants().map(function (node) {
+ return node.data.index;
+ })
+ );
+ var nodeName = isLeaf
+ ? nodePath
+ .slice(nodePath.lastIndexOf('.') + 1)
+ .split(/(?=[A-Z][^A-Z])/g)
+ .join('\n')
+ : '';
+ var z2 = api.value('depth') * 2;
+ return {
+ type: 'circle',
+ focus: focus,
+ shape: {
+ cx: node.x,
+ cy: node.y,
+ r: node.r
+ },
+ transition: ['shape'],
+ z2: z2,
+ textContent: {
+ type: 'text',
+ style: {
+ // transition: isLeaf ? 'fontSize' : null,
+ text: nodeName,
+ fontFamily: 'Arial',
+ width: node.r * 1.3,
+ overflow: 'truncate',
+ fontSize: node.r / 3
+ },
+ emphasis: {
+ style: {
+ overflow: null,
+ fontSize: Math.max(node.r / 3, 12)
+ }
+ }
+ },
+ textConfig: {
+ position: 'inside'
+ },
+ style: {
+ fill: api.visual('color')
+ },
+ emphasis: {
+ style: {
+ fontFamily: 'Arial',
+ fontSize: 12,
+ shadowBlur: 20,
+ shadowOffsetX: 3,
+ shadowOffsetY: 5,
+ shadowColor: 'rgba(0,0,0,0.3)'
+ }
+ }
+ };
+ }
+ option = {
+ dataset: {
+ source: seriesData
+ },
+ tooltip: {},
+ visualMap: [
+ {
+ show: false,
+ min: 0,
+ max: maxDepth,
+ dimension: 'depth',
+ inRange: {
+ color: ["#182E3D", "#4A8FBD", "#82A5BD", "#5E7788", "#5D8AA8", "#2c5571"]//['#006edd', '#e0ffff']
+ }
+ }
+ ],
+ hoverLayerThreshold: Infinity,
+ series: {
+ type: 'custom',
+ renderItem: renderItem,
+ progressive: 0,
+ coordinateSystem: 'none',
+ encode: {
+ tooltip: 'value',
+ itemName: 'id'
+ }
+ }
+ };
+ myChart.setOption(option);
+ myChart.on('click', { seriesIndex: 0 }, function (params) {
+ drillDown(params.data.id);
+ });
+ function drillDown(targetNodeId) {
+ displayRoot = stratify();
+ if (targetNodeId != null) {
+ displayRoot = displayRoot.descendants().find(function (node) {
+ return node.data.id === targetNodeId;
+ });
+ }
+ // A trick to prevent d3-hierarchy from visiting parents in this algorithm.
+ displayRoot.parent = null;
+ myChart.setOption({
+ dataset: {
+ source: seriesData
+ }
+ });
+ }
+ // Reset: click on the blank area.
+ myChart.getZr().on('click', function (event) {
+ if (!event.target) {
+ drillDown();
+ }
+ });
+ }
+
+ option && myChart.setOption(option, true);
+ window.addEventListener('resize', function () {
+ myChart.resize();
+ });
+}
+
Index: arms/js/analysisScope.js
===================================================================
diff -u -rf53218e3b68e19c2d17937b91a3f130ca5f8345b -r6993b6519461e4671fc8f57194e14912edf6bdda
--- arms/js/analysisScope.js (.../analysisScope.js) (revision f53218e3b68e19c2d17937b91a3f130ca5f8345b)
+++ arms/js/analysisScope.js (.../analysisScope.js) (revision 6993b6519461e4671fc8f57194e14912edf6bdda)
@@ -62,6 +62,8 @@
//tree chart
//CirclePacking with d3 Chart
+ "js/analysis/resource/chart/circularPackingChart.js",
+ "js/analysis/mockData/circularPackingEx.json"
],
[ "../reference/jquery-plugins/dataTables-1.10.16/media/css/jquery.dataTables_lightblue4.css",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/css/responsive.dataTables_lightblue4.css",
@@ -96,6 +98,7 @@
versionUpdateIssueScatterChart();
dashboardColor = dashboardPalette.dashboardPalette01;
+ exampleCircularPackingChart(); // circularPackingChart - MockData
})
.catch(function() {
console.error('플러그인 로드 중 오류 발생');
@@ -933,9 +936,7 @@
200: function (result) {
console.log("[ analysisScope :: getReqAndSubtaskPerVersion ] :: result");
console.log(result);
- console.log(versionListData);
-
let legend_arr = ["요구사항", "연결이슈"];
let verDataArr = [];