(function () { var ua = navigator.userAgent, iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i), typeOfCanvas = typeof HTMLCanvasElement, nativeCanvasSupport = typeOfCanvas == "object" || typeOfCanvas == "function", textSupport = nativeCanvasSupport && typeof document.createElement("canvas").getContext("2d").fillText == "function"; //I'm setting this based on the fact that ExCanvas provides text support for IE //and that as of today iPhone/iPad current text support is lame labelType = !nativeCanvasSupport || (textSupport && !iStuff) ? "Native" : "HTML"; nativeTextSupport = labelType == "Native"; useGradients = nativeCanvasSupport; animate = !(iStuff || !nativeCanvasSupport); })(); var Log = { elem: false, write: function (text) { if (!this.elem) this.elem = document.getElementById("log"); this.elem.innerHTML = text; this.elem.style.left = 500 - this.elem.offsetWidth / 2 + "px"; } }; function init(treeMapInfos, targetElementId) { const colorMapping = {}; var treeMapBaseColors = ColorPalette.otherChartLib.treeMapChart.slice(); // 간단한 문자열 해시 함수 function hashString(str) { var hash = 0; if (!str || str.length === 0) { return hash; } for (var i = 0; i < str.length; i++) { hash = (hash << 5) - hash + str.charCodeAt(i); hash |= 0; // 32-bit int로 변환 } // 음수 방지 return Math.abs(hash); } // name 에 대한 색을 돌려주는 함수 function getColorForName(name) { if (!name) { // name 이 비었을 때를 대비한 fallback 색 return "rgba(200, 200, 200, 0.6)"; } // 이미 색이 지정돼 있으면 그대로 반환 if (colorMapping[name]) { return colorMapping[name]; } // 팔레트가 비어 있는 극단상황 방어 로직 if (!treeMapBaseColors || treeMapBaseColors.length === 0) { colorMapping[name] = "rgba(200, 200, 200, 0.6)"; return colorMapping[name]; } // 이름을 해시해서 팔레트 길이로 모듈러 연산 var idx = hashString(name) % treeMapBaseColors.length; var selectedColor = treeMapBaseColors[idx]; colorMapping[name] = selectedColor; return selectedColor; } treeMapInfos.children.forEach((worker) => { worker.children.forEach((task) => { const color = getColorForName(task.name); task.data.$color = color; task.id = task.id + "-" + worker.id; task.data.$area = task.data.involvedCount; }); worker.data.$area = worker.data.totalInvolvedCount; }); //init TreeMap var tm = new $jit.TM.Squarified({ //where to inject the visualization injectInto: targetElementId, //parent box title heights titleHeight: 22, //enable animations animate: animate, //box offsets offset: 2.5, //Attach left and right click events Events: { enable: true, onClick: function (node) { if (node) tm.enter(node); }, onRightClick: function () { tm.out(); } }, duration: 300, //Enable tips Tips: { enable: true, //add positioning offsets offsetX: 20, offsetY: 20, //implement the onShow method to //add content to the tooltip when a node //is hovered onShow: function (tip, node, isLeaf, domElement) { var html = '
' + node.name + '
'; var data = node.data; if (data.involvedCount) { html += "
관여한 횟수 : " + data.involvedCount + "
"; } if (data.totalInvolvedCount) { html += "
작업자가 관여한 총 횟수 : " + data.totalInvolvedCount + "
"; } if (data.image) { html += ''; } html += "
우클릭 시 뒤로 갑니다.
"; tip.innerHTML = html; } }, //Add the name of the node in the correponding label //This method is called once, on label creation. onCreateLabel: function (domElement, node) { if (node.id === "chart_root" || !node.id.includes("app")) { var html = '
' + node.name + "
"; } else { var html = '
' + // '' + node.name + // "" + "
"; } domElement.innerHTML = html; var style = domElement.style; style.display = ""; style.border = "1.5px solid transparent"; // style.borderRadius = "50%"; domElement.onmouseover = function () { style.border = "1.5px solid #9FD4FF"; }; domElement.onmouseout = function () { style.border = "1.5px solid transparent"; }; } }); tm.loadJSON(treeMapInfos); tm.refresh(); //end //add events to radio buttons var sq = $jit.id("r-sq"), st = $jit.id("r-st"), sd = $jit.id("r-sd"); var util = $jit.util; util.addEvent(sq, "change", function () { if (!sq.checked) return; util.extend(tm, new $jit.Layouts.TM.Squarified()); tm.refresh(); }); util.addEvent(st, "change", function () { if (!st.checked) return; util.extend(tm, new $jit.Layouts.TM.Strip()); tm.layout.orientation = "v"; tm.refresh(); }); util.addEvent(sd, "change", function () { if (!sd.checked) return; util.extend(tm, new $jit.Layouts.TM.SliceAndDice()); tm.layout.orientation = "v"; tm.refresh(); }); //add event to the back button var back = $jit.id("back"); $jit.util.addEvent(back, "click", function () { tm.out(); }); window.addEventListener("resize", function () { // var charts = document.getElementById('chart-manpower-requirement'); var charts = document.getElementById(targetElementId); var width = charts.offsetWidth; var height = charts.offsetHeight; // dashboard는 297px, 분석 페이지는 500px을 고정으로 사용하고 있음. tm.canvas.resize(width, height); tm.plot(); }); }