//////////////////////////////////////////////////////////////////////////////////////// //Document Ready //////////////////////////////////////////////////////////////////////////////////////// function execDocReady() { var pluginGroups = [ [ "../reference/light-blue/lib/vendor/jquery.ui.widget.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Templates_js_tmpl.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Load-Image_js_load-image.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Canvas-to-Blob_js_canvas-to-blob.js", "../reference/light-blue/lib/jquery.iframe-transport.js", "../reference/light-blue/lib/jquery.fileupload.js", "../reference/light-blue/lib/jquery.fileupload-fp.js", "../reference/light-blue/lib/jquery.fileupload-ui.js"], [ "../reference/jquery-plugins/select2-4.0.2/dist/css/select2_lightblue4.css", "../reference/jquery-plugins/lou-multi-select-0.9.12/css/multiselect-lightblue4.css", "../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select-bluelight.css", "../reference/jquery-plugins/select2-4.0.2/dist/js/select2.min.js", "../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.quicksearch.js", "../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.multi-select.js", "../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select.min.js"], [ "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.min.css", "../reference/light-blue/lib/bootstrap-datepicker.js", "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.full.min.js", "../reference/lightblue4/docs/lib/widgster/widgster.js", //d3 변경 "../reference/jquery-plugins/d3-6.7.0/d3.min.js", "../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js", "../reference/jquery-plugins/timerStyles.js"], ["../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", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/css/select.dataTables_lightblue4.css", "../reference/jquery-plugins/dataTables-1.10.16/media/js/jquery.dataTables.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/js/dataTables.responsive.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/js/dataTables.select.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/RowGroup/js/dataTables.rowsGroup.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/dataTables.buttons.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.html5.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.print.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/jszip.min.js", "../reference/jquery-plugins/swiper-11.1.4/swiper-bundle.min.js", "../reference/jquery-plugins/swiper-11.1.4/swiper-bundle.min.css", "./js/common/swiperHelper.js", "./css/customSwiper.css" ] // 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다. ]; loadPluginGroupsParallelAndSequential(pluginGroups) .then(function() { console.log('모든 플러그인 로드 완료'); //사이드 메뉴 처리 $('.widget').widgster(); setSideMenu("sidebar_menu_report", "sidebar_menu_report_swot"); //coming soon $("#count-down").TimeCircles( { circle_bg_color: "#f8f8f8", use_background: true, bg_width: .2, fg_width: 0.013, time: { Days: { color: "#f8f8f8" }, Hours: { color: "#f8f8f8" }, Minutes: { color: "#f8f8f8" }, Seconds: { color: "#f8f8f8" } } } ); initResponsiveMatrix(); }) .catch(function() { console.error('플러그인 로드 중 오류 발생'); }); } function initResponsiveMatrix() { const svg = d3.select('#matrix'); const wrapper = $("#matrix_wrapper"); function render() { const containerPadding = 40; const width = wrapper.width() - containerPadding; const height = 800; const matrixMargin = 40; // 내부 margin 적용 svg .attr('viewBox', `0 0 ${width + matrixMargin * 2} ${height}`) .attr('preserveAspectRatio', 'xMidYMid meet') .attr('width', '100%') .attr('height', height); svg.selectAll('*').remove(); drawMatrixChart(svg, width, height - 100, matrixMargin); addDummyData(svg, width, height - 100, matrixMargin); } render(); window.addEventListener('resize', render); } function drawMatrixChart(svg, width, height, margin) { const MATRIX_X = margin; const MATRIX_Y = margin; const BORDER_X = 25; const BORDER_Y = 25; const colors = ['rgb(255, 77, 77)', 'rgb(77, 255, 77)', 'rgb(61, 61, 61)', 'rgb(179, 115, 0)']; const priority = [ { x: MATRIX_X + width / 2, y: MATRIX_Y, color: colors[0], text: '긴급하고 중요한 일', index: 1 }, { x: MATRIX_X + width / 2, y: MATRIX_Y + height / 2, color: colors[3], text: '긴급하지만 중요하지 않은 일', index: 2 }, { x: MATRIX_X, y: MATRIX_Y, color: colors[1], text: '긴급하지 않지만 중요한 일', index: 3 }, { x: MATRIX_X, y: MATRIX_Y + height / 2, color: colors[2], text: '긴급하지도 중요하지도 않은 일', index: 4 }, ]; svg.append('rect') .attr('x', MATRIX_X) .attr('y', MATRIX_Y) .attr('width', width) .attr('height', height) .attr('rx', 8) .attr('class', 'rectangle'); priority.forEach((q) => { svg.append('rect') .attr('x', q.x + 10) .attr('y', q.y + 10) .attr('width', 30) .attr('height', 30) .attr('rx', 8) .attr('fill', q.color) .attr('opacity', 0.4); svg.append('text') .attr('x', q.x + 21) .attr('y', q.y + 30) .attr('class', 'text') .text(q.index); svg.append('text') .attr('x', q.x + 45) .attr('y', q.y + 30) .attr('class', 'text') .text(q.text); }); const borders = [ { x1: BORDER_X, y1: MATRIX_Y, x2: BORDER_X, y2: MATRIX_Y + height }, { x1: BORDER_X, y1: MATRIX_Y, x2: BORDER_X - 10, y2: MATRIX_Y + 10 }, { x1: MATRIX_X, y1: MATRIX_Y + BORDER_Y + height, x2: MATRIX_X + width, y2: MATRIX_Y + BORDER_Y + height }, { x1: MATRIX_X + width, y1: MATRIX_Y + BORDER_Y + height, x2: MATRIX_X + width - 10, y2: MATRIX_Y + BORDER_Y + height + 10 }, { x1: MATRIX_X, y1: MATRIX_Y + height / 2, x2: MATRIX_X + width, y2: MATRIX_Y + height / 2 }, { x1: MATRIX_X + width / 2, y1: MATRIX_Y, x2: MATRIX_X + width / 2, y2: height + 20 }, ]; borders.forEach((b) => { svg.append('line') .attr('class', 'border') .attr('x1', b.x1) .attr('y1', b.y1) .attr('x2', b.x2) .attr('y2', b.y2); }); svg.append('text') .attr('x', MATRIX_X + width / 2) .attr('y', MATRIX_Y - 10 + height) .attr('text-anchor', 'middle') .attr('class', 'text') .text('D-7'); svg.append('text') .attr('x', MATRIX_X + 15) .attr('y', MATRIX_Y - 10 + height) .attr('class', 'text') .text('D-30'); svg.append('text') .attr('x', MATRIX_X - 15 + width) .attr('y', MATRIX_Y - 10 + height) .attr('class', 'text') .attr('text-anchor', 'end') .style('fill', colors[0]) .text('D-day'); svg.append('text') .attr('x', -(MATRIX_X + height / 2 - height / 4)) .attr('y', 20) .attr('class', 'text') .attr('text-anchor', 'middle') .attr('transform', 'rotate(-90)') .text('중요함'); svg.append('text') .attr('x', -(MATRIX_X + height / 2 + height / 4)) .attr('y', 20) .attr('class', 'text') .attr('text-anchor', 'middle') .attr('transform', 'rotate(-90)') .text('중요하지 않음'); svg.append('text') .attr('x', MATRIX_X + width / 2 + width / 4) .attr('y', MATRIX_Y + height + 40) .attr('text-anchor', 'middle') .attr('class', 'text') .text('긴급함'); svg.append('text') .attr('x', MATRIX_X + width / 2 - width / 4) .attr('y', MATRIX_Y + height + 40) .attr('text-anchor', 'middle') .attr('class', 'text') .text('긴급하지 않음'); } function addDummyData(svg, width, height, margin) { const MATRIX_X = margin; const MATRIX_Y = margin; const colors = ['rgb(255, 77, 77)', 'rgb(77, 255, 77)', 'rgb(61, 61, 61)', 'rgb(179, 115, 0)']; const quadrants = [ { x1: MATRIX_X + width / 2, y1: MATRIX_Y, x2: MATRIX_X + width, y2: MATRIX_Y + height / 2 }, { x1: MATRIX_X, y1: MATRIX_Y, x2: MATRIX_X + width / 2, y2: MATRIX_Y + height / 2 }, { x1: MATRIX_X, y1: MATRIX_Y + height / 2, x2: MATRIX_X + width / 2, y2: MATRIX_Y + height }, { x1: MATRIX_X + width / 2, y1: MATRIX_Y + height / 2, x2: MATRIX_X + width, y2: MATRIX_Y + height }, ]; const dummyData = [ { px: 0.3, py: 0.7 }, { px: 0.4, py: 0.9 }, { px: 0.55, py: 0.4 }, { px: 0.8, py: 0.45 }, { px: 0.7, py: 0.65 }, { px: 0.43, py: 0.85 }, { px: 0.6, py: 0.95 }, { px: 0.58, py: 0.79 }, { px: 0.9, py: 0.92 }, { px: 0.25, py: 0.3 }, { px: 0.75, py: 0.43 }, { px: 0.5, py: 0.15 } ]; const drag = d3.drag() .on("start", function (event, d) { d.__dragged = false; d3.select(this).raise().attr("stroke", "black"); }) .on("drag", function (event, d) { // D3 v6+에서는 event.x, event.y가 내부 SVG 좌표이므로 그대로 사용 d.__dragged = true; d.cx = event.x; d.cy = event.y; d3.select(this) .attr("cx", d.cx) .attr("cy", d.cy); }) .on("end", function (event, d) { d3.select(this).attr("stroke", null); }); dummyData.forEach(d => { d.cx = MATRIX_X + d.px * width; d.cy = MATRIX_Y + d.py * height; const colorIndex = quadrants.findIndex(q => d.cx >= q.x1 && d.cx <= q.x2 && d.cy >= q.y1 && d.cy <= q.y2 ); svg.append('circle') .datum(d) .attr('class', 'draggable-circle') .attr('cx', d.cx) .attr('cy', d.cy) .attr('r', 5) .attr('fill', colors[colorIndex]) .style('cursor', 'pointer') .call(drag) .on("click", function (event, d) { if (!d.__dragged) { console.log("이벤트를 받아서, 이슈의 내용을 보여주기"); } }); }); }