확대/축소

GanttSheet 차트 영역을 확대/축소하여 차트를 더 많이 또는 더 적게 표시할 수 있습니다.

설명
app.jsx
app-func.jsx
app-class.jsx
index.html
styles.css

확대/축소 비율

확대/축소 비율은 날짜 표시줄의 확대/축소 비율을 나타내는 숫자 값입니다. 확대/축소 비율을 변경하려면 날짜 표시줄의 확대/축소 함수를 호출합니다.

var timescale = ganttsheet.project.timescale;
console.log(timescale.zoomFactor);

확대/축소

날짜 표시줄에서 확대/축소할 수 있습니다.

var timescale = ganttsheet.project.timescale;
timescale.zoomIn();
timescale.zoomOut();

자동 확대/축소

각 계층의 눈금 레이블에 따라 날짜 표시줄을 적절한 비율로 자동으로 확대/축소할 수도 있습니다.

var timescale = ganttsheet.project.timescale;
timescale.zoomAuto();

확대/축소 값

날짜 표시줄을 지정한 비율로 확대/축소할 수 있습니다.

var timescale = ganttsheet.project.timescale;
var zoomFactor = 2;
timescale.zoomTo(zoomFactor);

다음 코드는 날짜 표시줄을 확대/축소하여 대상 날짜 범위를 뷰포트에 표시합니다. 날짜 표시줄은 가장 가까운 눈금으로 조정됩니다.

var timescale = ganttsheet.project.timescale;
var startDate = new Date(2022, 1, 5);
var endDate = new Date(2023, 1, 5);
timescale.zoomToRange(startDate, endDate);

계층 단위 조정

부울 값은 확대/축소 비율에 따라 계층 단위를 적절한 값으로 조정하는지를 나타냅니다. API에서 기본적으로 true입니다.

  • timescale.zoomIn(adjustTierUnit);
  • timescale.zoomOut(adjustTierUnit);
  • timescale.zoomTo(zoomFactor, adjustTierUnit);
  • timescale.zoomToRange(startDate, endDate, adjustTierUnit);
확대/축소 비율 확대/축소 비율은 날짜 표시줄의 확대/축소 비율을 나타내는 숫자 값입니다. 확대/축소 비율을 변경하려면 날짜 표시줄의 확대/축소 함수를 호출합니다. 확대/축소 날짜 표시줄에서 확대/축소할 수 있습니다. 자동 확대/축소 각 계층의 눈금 레이블에 따라 날짜 표시줄을 적절한 비율로 자동으로 확대/축소할 수도 있습니다. 확대/축소 값 날짜 표시줄을 지정한 비율로 확대/축소할 수 있습니다. 다음 코드는 날짜 표시줄을 확대/축소하여 대상 날짜 범위를 뷰포트에 표시합니다. 날짜 표시줄은 가장 가까운 눈금으로 조정됩니다. 계층 단위 조정 부울 값은 확대/축소 비율에 따라 계층 단위를 적절한 값으로 조정하는지를 나타냅니다. API에서 기본적으로 true입니다. timescale.zoomIn(adjustTierUnit); timescale.zoomOut(adjustTierUnit); timescale.zoomTo(zoomFactor, adjustTierUnit); timescale.zoomToRange(startDate, endDate, adjustTierUnit);
import * as React from 'react'; import * as ReactDOM from 'react-dom'; import './styles.css'; import { AppFunc } from './app-func'; import { App } from './app-class'; // 1. Functional Component sample ReactDOM.render(<AppFunc />, document.getElementById('app')); // 2. Class Component sample // ReactDOM.render(<App />, document.getElementById('app'));
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-tablesheet"; import "@mescius/spread-sheets-ganttsheet"; import '@mescius/spread-sheets-resources-ko'; GC.Spread.Common.CultureManager.culture("ko-kr"); import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; const useState = React.useState; let ganttSheet = null; let myTable = null; export function AppFunc() { const [state, setState] = useState({ zoomFactor: 1, zoomToType: "0", adjustTierUnit: true }); const initSpread = (spread) => { spread.suspendPaint(); spread.clearSheets(); initDataSource(spread); initGanttSheet(spread); spread.resumePaint(); initSplitView(spread); } const initDataSource = (spread) => { let tableName = "Gantt_Id"; let baseApiUrl = getBaseApiUrl(); let apiUrl = baseApiUrl + "/" + tableName; let dataManager = spread.dataManager(); myTable = dataManager.addTable("myTable", { batch: true, remote: { read: { url: apiUrl } }, schema: { hierarchy: { type: "Parent", column: "parentId" }, columns: { id: { isPrimaryKey: true }, taskNumber: { dataType: "rowOrder" } } } }); } const initGanttSheet = (spread) => { ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet); let view = myTable.addView("ganttView", [ { value: "taskNumber", caption: "NO.", width: 60 }, { value: "name", caption: "Task Name", width: 200 }, { value: "duration", caption: "Duration", width: 90 }, { value: "predecessors", caption: "Predecessors", width: 120 } ]); view.fetch().then(function () { ganttSheet.bindGanttView(view); }).then(function () { ganttSheet.project.timescale.zoomOut(); }); // initSidePanel(ganttSheet); } const tierUnit = () => { let adjustTierUnitCheckbox = document.getElementById("adjust-tier-unit"); if (adjustTierUnitCheckbox.classList.contains("active")) { adjustTierUnitCheckbox.classList.remove("active"); setState({ ...state, adjustTierUnit: false }); } else { adjustTierUnitCheckbox.classList.add("active"); setState({ ...state, adjustTierUnit: true }); } } const zoomAuto = () => { ganttSheet.project.timescale.zoomAuto(); syncPanel(ganttSheet); } const zoomIn = () => { ganttSheet.project.timescale.zoomIn(state.adjustTierUnit); syncPanel(ganttSheet); } const zoomOut = () => { ganttSheet.project.timescale.zoomOut(state.adjustTierUnit); syncPanel(ganttSheet); } const zoomTo = () => { let factor = Number(state.zoomFactor); if (!isNaN(factor)) { ganttSheet.project.timescale.zoomTo(factor, state.adjustTierUnit); syncPanel(ganttSheet); } } const zoomToRange = () => { let zoomToType = state.zoomToType; let project = ganttSheet.project; if (zoomToType === "0") { let task = ganttSheet.getActiveTask(); if (task && task.finish && task.start) { project.timescale.zoomToRange(task.start, task.finish); } } else if (zoomToType === "1") { let startDate = Math.min.apply(null, project.tasks.filter(function (t) { return t.start }).map(function (t) { return t.start.valueOf() })); let finishDate = Math.max.apply(null, project.tasks.filter(function (t) { return t.finish }).map(function (t) { return t.finish.valueOf() })); project.timescale.zoomToRange(new Date(startDate), new Date(finishDate)); } syncPanel(ganttSheet); } const syncPanel = (ganttSheet) => { let zoomFactorInput = document.getElementById("zoom-factor"); zoomFactorInput.value = ganttSheet.project.timescale.zoomFactor; } return ( <div id="split-view" class="sample-tutorial"> <div id="ss" class="sample-spreadsheets split-content"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}></SpreadSheets> </div> <div class="options-container split-panel"> <div class="option-row option-title"> Zoom the ganttsheet chart area. </div> <div class="option-block"> <div class="option-row"> <label class="option-checkbox active" id="adjust-tier-unit" onClick={() => { tierUnit() }}>Adjust Tier Unit</label> <div class="option-info">* checkbox toggle whether adjust tier unit or not when zoom. It affects the result of zoom in, zoom out, zoom to and zoom to range.</div> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="zoom-auto" class="option-button" value="Zoom Auto" onClick={() => { zoomAuto(state) }} /> </div> <div class="option-row"> <input type="button" id="zoom-in" class="option-button" value="Zoom In" onClick={() => { zoomIn(state) }} /> </div> <div class="option-row"> <input type="button" id="zoom-out" class="option-button" value="Zoom Out" onClick={() => { zoomOut(state) }} /> </div> </div> <div class="option-block"> <div class="option-row input-box"> <label for="zoom-factor">Zoom Factor</label> <input type="text" id="zoom-factor" value={state.zoomFactor} onChange={(e) => { setState({ ...state, zoomFactor: e.target.value }) }} /> <div class="option-info valid">* valid value: number</div> </div> <div class="option-row"> <input type="button" id="zoom-to" class="option-button" value="Zoom To" onClick={() => { zoomTo(state) }} /> </div> <div class="option-row selection-box"> <label for="zoom-to-type">Demo Range</label> <select id="zoom-to-type" value={state.zoomToType} onChange={(e) => { setState({ ...state, zoomToType: e.target.value }) }}> <option value="0">Selected Task</option> <option value="1">Entire Project</option> </select> </div> <div class="option-row"> <input type="button" id="zoom-to-range" class="option-button" value="Zoom To Range" onClick={() => { zoomToRange(state) }} /> </div> </div> </div> </div> ); } function initSplitView(spread) { let host = document.getElementById("split-view"); let content = host.getElementsByClassName("split-content")[0]; let panel = host.getElementsByClassName("split-panel")[0]; new SplitView({ host: host, content: content, panel: panel, refreshContent: function () { spread.refresh(); } }); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/learn-spreadjs\//)[0] + 'server/api'; }
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import GC from '@mescius/spread-sheets'; import "@mescius/spread-sheets-tablesheet"; import "@mescius/spread-sheets-ganttsheet"; import '@mescius/spread-sheets-resources-ko'; GC.Spread.Common.CultureManager.culture("ko-kr"); import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; const Component = React.Component; export class App extends Component { constructor(props) { super(props); this.spread = null; this.ganttSheet = null; this.state = { zoomFactor: 1, zoomToType: "0", adjustTierUnit: true }; } render() { return ( <div id="split-view" class="sample-tutorial"> <div id="ss" class="sample-spreadsheets split-content"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}></SpreadSheets> </div> <div class="options-container split-panel"> <div class="option-row option-title"> Zoom the ganttsheet chart area. </div> <div class="option-block"> <div class="option-row"> <label class="option-checkbox active" id="adjust-tier-unit" onClick={() => { this.tierUnit() }}>Adjust Tier Unit</label> <div class="option-info">* checkbox toggle whether adjust tier unit or not when zoom. It affects the result of zoom in, zoom out, zoom to and zoom to range.</div> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="zoom-auto" class="option-button" value="Zoom Auto" onClick={() => { this.zoomAuto(this.state) }} /> </div> <div class="option-row"> <input type="button" id="zoom-in" class="option-button" value="Zoom In" onClick={() => { this.zoomIn(this.state) }} /> </div> <div class="option-row"> <input type="button" id="zoom-out" class="option-button" value="Zoom Out" onClick={() => { this.zoomOut(this.state) }} /> </div> </div> <div class="option-block"> <div class="option-row input-box"> <label for="zoom-factor">Zoom Factor</label> <input type="text" id="zoom-factor" value={this.state.zoomFactor} onChange={(e) => { this.setState({ zoomFactor: e.target.value }) }} /> <div class="option-info valid">* valid value: number</div> </div> <div class="option-row"> <input type="button" id="zoom-to" class="option-button" value="Zoom To" onClick={() => { this.zoomTo(this.state) }} /> </div> <div class="option-row selection-box"> <label for="zoom-to-type">Demo Range</label> <select id="zoom-to-type" value={this.state.zoomToType} onChange={(e) => { this.setState({ zoomToType: e.target.value }) }}> <option value="0">Selected Task</option> <option value="1">Entire Project</option> </select> </div> <div class="option-row"> <input type="button" id="zoom-to-range" class="option-button" value="Zoom To Range" onClick={() => { this.zoomToRange(this.state) }} /> </div> </div> </div> </div> ); } initSpread(spread) { this.spread = spread; spread.suspendPaint(); spread.clearSheets(); this.initDataSource(spread); this.initGanttSheet(spread); spread.resumePaint(); initSplitView(spread); } initDataSource(spread) { let tableName = "Gantt_Id"; let baseApiUrl = getBaseApiUrl(); let apiUrl = baseApiUrl + "/" + tableName; let dataManager = spread.dataManager(); let myTable = dataManager.addTable("myTable", { batch: true, remote: { read: { url: apiUrl } }, schema: { hierarchy: { type: "Parent", column: "parentId" }, columns: { id: { isPrimaryKey: true }, taskNumber: { dataType: "rowOrder" } } } }); this.myTable = myTable; } initGanttSheet(spread) { let ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet); this.ganttSheet = ganttSheet; let view = this.myTable.addView("ganttView", [ { value: "taskNumber", caption: "NO.", width: 60 }, { value: "name", caption: "Task Name", width: 200 }, { value: "duration", caption: "Duration", width: 90 }, { value: "predecessors", caption: "Predecessors", width: 120 } ]); view.fetch().then(function () { ganttSheet.bindGanttView(view); }).then(function () { ganttSheet.project.timescale.zoomOut(); }); // initSidePanel(ganttSheet); } tierUnit() { let adjustTierUnitCheckbox = document.getElementById("adjust-tier-unit"); if (adjustTierUnitCheckbox.classList.contains("active")) { adjustTierUnitCheckbox.classList.remove("active"); this.setState({ adjustTierUnit: false }); } else { adjustTierUnitCheckbox.classList.add("active"); this.setState({ adjustTierUnit: true }); } } zoomAuto() { this.ganttSheet.project.timescale.zoomAuto(); this.syncPanel(this.ganttSheet); } zoomIn() { this.ganttSheet.project.timescale.zoomIn(this.state.adjustTierUnit); this.syncPanel(this.ganttSheet); } zoomOut() { this.ganttSheet.project.timescale.zoomOut(this.state.adjustTierUnit); this.syncPanel(this.ganttSheet); } zoomTo() { let factor = Number(this.state.zoomFactor); if (!isNaN(factor)) { this.ganttSheet.project.timescale.zoomTo(factor, this.state.adjustTierUnit); this.syncPanel(this.ganttSheet); } } zoomToRange() { let zoomToType = this.state.zoomToType; let project = this.ganttSheet.project; if (zoomToType === "0") { let task = this.ganttSheet.getActiveTask(); if (task && task.finish && task.start) { project.timescale.zoomToRange(task.start, task.finish); } } else if (zoomToType === "1") { let startDate = Math.min.apply(null, project.tasks.filter(function (t) { return t.start }).map(function (t) { return t.start.valueOf() })); let finishDate = Math.max.apply(null, project.tasks.filter(function (t) { return t.finish }).map(function (t) { return t.finish.valueOf() })); project.timescale.zoomToRange(new Date(startDate), new Date(finishDate)); } this.syncPanel(this.ganttSheet); } syncPanel(ganttSheet) { let zoomFactorInput = document.getElementById("zoom-factor"); zoomFactorInput.value = ganttSheet.project.timescale.zoomFactor; } } function initSplitView(spread) { let host = document.getElementById("split-view"); let content = host.getElementsByClassName("split-content")[0]; let panel = host.getElementsByClassName("split-panel")[0]; new SplitView({ host: host, content: content, panel: panel, refreshContent: function () { spread.refresh(); } }); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/learn-spreadjs\//)[0] + 'server/api'; }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css"> <!-- SystemJS --> <script src="$DEMOROOT$/ko/react/node_modules/systemjs/dist/system.src.js"></script> <script src="$DEMOROOT$/spread/source/data/employees.js" type="text/javascript"></script> <script src="systemjs.config.js"></script> <!-- plugins --> <script src="$DEMOROOT$/spread/source/splitView/SplitView.js"></script> <script> System.import('$DEMOROOT$/ko/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app" style="height: 100%;"></div> </body> </html>
.option-block { background: #fff; padding: 8px; margin: 12px 0; border-radius: 4px; border: 1px dashed #82bc00; box-shadow: 0px 0 6px 0 rgba(0,0,0,0.1); } .option-block.toggle { border: 1px dotted #f7a711; } .option-row { font-size: 14px; box-sizing: border-box; padding: 4px 0; } .option-title { font-weight: bold; color: #656565; } .option-info { font-size: 12px; color: #919191; margin-top: 6px; font-weight: normal; } .option-info.valid { color: #82bc00; } .option-info.toggle { color: #f7a711; } .option-button { width: 100%; padding: 0; line-height: 20px; background: #82bc00; color: #fff; transition: 0.3s; cursor: pointer; outline: none; border-radius: 4px; box-sizing: border-box; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border: none; } .option-button:hover { background: #82bc00; color: #fff; box-shadow: 0 3px 8px 0 rgba(0,0,0,0.4); } .option-checkbox { background: #fff; border: 1px dashed #f7a711; color: #f7a711; padding: 2px 4px; transition: 0.3s; box-sizing: border-box; cursor: pointer; } .option-checkbox.active { color: #fff; background: #f7a711; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border-radius: 4px; } .selection-box { position: relative; } .selection-box > select { text-align: left; width: 100%; height: 20px; padding: 0; line-height: 20px; background: transparent; border: none; border-bottom: 2px solid #656565; color: #656565; transition: 0.3s; cursor: pointer; outline: none; box-sizing: border-box; } .selection-box > select > option { background: white; } .selection-box > select:focus { border-bottom: 2px solid #82bc00; color: #82bc00; box-shadow: 0 2px 6px 0 rgba(0,0,0,0.3); } .selection-box > label { position: absolute; cursor: pointer; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; right: 0; top: 6px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); } .input-box { position: relative; } .input-box > input[type=text] { width: 100%; background: transparent; border: none; color: #656565; border-bottom: 2px solid #656565; outline: none; box-sizing: border-box; transition: 0.3s; } .input-box > input[type=text]:focus { color: #82bc00; border-bottom: 2px solid #82bc00; } .input-box > label { cursor: pointer; position: absolute; right: 0; top: 5px; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-resources-ko': 'npm:@mescius/spread-sheets-resources-ko/index.js', '@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js', '@mescius/spread-sheets-ganttsheet': 'npm:@mescius/spread-sheets-ganttsheet/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/umd/react.production.min.js', 'react-dom': 'npm:react-dom/umd/react-dom.production.min.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);