テーマのカスタマイズ

このデモでは、リボンコンテナのテーマをカスタマイズする方法を示します。

リボンコンテナは、テーマの色、境界線の半径、影をカスタマイズできるトークンのセットを提供します。 テーマをカスタマイズする前に、ベースとなるテーマを選択してください。 Light: gc.spread.sheets.designer.light.x.x.x.min.css Dark: gc.spread.sheets.designer.dark.x.x.x.min.css リボンコンテナは setTheme API を提供しており、テーマを簡単にカスタマイズできます。 例: リボンコンテナは、以下のカスタマイズもサポートしています。 CSS 変数を上書きすることでテーマを設定できます。 例: 現在サポートされているトークンは次のとおりです: APIトークン CSS変数トークン colorForeground--sjs-color-foreground colorForegroundDisabled--sjs-color-foreground-disabled colorBackground--sjs-color-background colorBackgroundHover--sjs-color-background-hover colorBackgroundSelected--sjs-color-background-selected colorBackgroundDisabled--sjs-color-background-disabled colorBackground2--sjs-color-background-2 colorBackground2Hover--sjs-color-background-2-hover colorBackground2Selected--sjs-color-background-2-selected colorBrandForeground--sjs-color-brand-foreground colorBrandBackground--sjs-color-brand-background colorBrandBackgroundHover--sjs-color-brand-background-hover colorBrandBackgroundSelected--sjs-color-brand-background-selected colorStroke--sjs-color-stroke colorStrokeHover--sjs-color-stroke-hover colorStrokeSelected--sjs-color-stroke-selected colorStrokeDisabled--sjs-color-stroke-disabled borderRadiusM--sjs-border-radius-m borderRadiusL--sjs-border-radius-l borderRadiusXL--sjs-border-radius-xl shadow4--sjs-shadow-4 shadow8--sjs-shadow-8
let spreadNS = GC.Spread.Sheets; let config = GC.Spread.Sheets.Designer.DefaultConfig; let designer, spread; window.onload = function () { initDesignerConfig(); }; const THEME_SETTING_PANEL_CMD = 'theme-setting-panel-command'; const THEME_SETTING_PANEL_TEMPLATE = 'theme-setting-panel-template'; const i18n = { designerPresetThemes: "リボンコンテナのテーマ", runtimePresetThemes: "SpreadJSのテーマ", loading: "CSSファイルをロード中...", gradientVariable: "グラデーショントークン", colorForeground: "前景色", colorForegroundDisabled: "無効時の前景色", colorBackground: "背景色", colorBackgroundHover: "ホバー時の背景色", colorBackgroundSelected: "選択時の背景色", colorBackgroundDisabled: "無効時の背景色", colorBackground2: "ページ背景色", colorBackground2Hover: "ホバー時のページ背景色", colorBackground2Selected: "選択時のページ背景色", colorBrandBackground: "ブランド背景色", colorBrandForeground: "ブランド前景色", colorBrandBackgroundHover: "ホバー時のブランド背景色", colorBrandBackgroundSelected: "選択時のブランド背景色", colorStroke: "ストローク色", colorStrokeHover: "ホバー時のストローク色", colorStrokeSelected: "選択時のストローク色", } function initDesignerConfig() { const colorSettings = [{ name: "colorForeground", gradient: [{ name: "colorForegroundDisabled", offset: 2 }] }, { name: "colorBackground", gradient: [{ name: "colorBackgroundHover", offset: 1 }, { name: "colorBackgroundSelected", offset: 2 }, { name: "colorBackgroundDisabled", offset: 3 }] }, { name: "colorBackground2", gradient: [{ name: "colorBackground2Hover", offset: 1 }, { name: "colorBackground2Selected", offset: 2 }] }, { name: "colorBrandBackground", gradient: [{ name: "colorBrandForeground" }, { name: "colorBrandBackgroundHover", offset: 1 }, { name: "colorBrandBackgroundSelected", offset: 2 }] }, { name: "colorStroke", gradient: [{ name: "colorStrokeHover", offset: 1 }, { name: "colorStrokeSelected", offset: 2 }] }] let designerTheme = 'light'; let runtimeTheme = 'excel2013white'; const themeSettingCMD = { commandName: THEME_SETTING_PANEL_CMD, execute: async (designer, propertyName, value) => { if (propertyName === 'designerTheme') { GC.Spread.Sheets.Designer.setTheme(null); await changeCSSScript(getDesignerCSSHref(designerTheme), getDesignerCSSHref(value)); designerTheme = value; if (value === 'dark') { await changeCSSScript(getRuntimeCSSHref(runtimeTheme), getRuntimeCSSHref('excel2016black')); designer.getWorkbook().refresh(); runtimeTheme = 'excel2016black'; } } else if (propertyName === 'runtimeTheme') { await changeCSSScript(getRuntimeCSSHref(runtimeTheme), getRuntimeCSSHref(value)); designer.getWorkbook().refresh(); runtimeTheme = value; } else { let customTheme = { [propertyName]: value }; // Automatically generate gradient colors if (colorSettings.find(item => item.name === propertyName)) { colorSettings.find(item => item.name === propertyName).gradient.forEach(item => { if (item.offset !== undefined) { customTheme[item.name] = ColorTool.generate(value, {theme: value === '#000000' ? 'dark' : 'default'})[5 + item.offset]; } }); } // Auto foreground color if (propertyName === 'colorBackground') { customTheme["colorForeground"] = calcForegroundColor(value); } GC.Spread.Sheets.Designer.setTheme(customTheme); } }, getState: (designer) => { return { designerTheme, runtimeTheme, ...GC.Spread.Sheets.Designer.getTheme() }; } } const generateColorEditor = (colorSetting) => { return { type: "LabelContainer", text: i18n[colorSetting.name], margin: "5px 0 0 0", padding: "10px 10px", children: [{ type: "FlexContainer", direction: "horizontal", className: "custom-theme-demo", children: [{ type: "TextBlock", text: i18n[colorSetting.name], margin: "0 0 0 10px" },{ type: "ColorComboEditor", margin: "0 0 0 30px", bindingPath: colorSetting.name }] }, { type: "CollapsePanel", text: i18n.gradientVariable, active: false, children: colorSetting.gradient.map(item => ({ type: "FlexContainer", direction: "horizontal", className: "custom-theme-demo", children: [{ type: "TextBlock", margin: "0 0 0 5px", text: i18n[item.name], },{ type: "ColorComboEditor", margin: "0 0 0 10px", bindingPath: item.name }] })) }] } } const themeSettingTemplate = { templateName: THEME_SETTING_PANEL_TEMPLATE, content: [{ type: "Column", margin: "10px", children: [{ type: "ColumnSet", children: [{ type: "Column", width: "stretch", children: [{ type: "LabelContainer", text: i18n.designerPresetThemes, padding: "5px 5px", children: [{ type: "List", bindingPath: "designerTheme", items: [{ text: "Light", value: "light" },{ text: "Dark", value: "dark" },] },] }] },{ type: "Column", width: "stretch", margin: "0 0 0 5px", children: [{ type: "LabelContainer", text: i18n.runtimePresetThemes, padding: "5px 5px", children: [{ type: "List", bindingPath: "runtimeTheme", items: [{ text: "Excel2013 White", value: "excel2013white" },{ text: "Excel2016 Black", value: "excel2016black" },] },] }] },] }, ...colorSettings.map(generateColorEditor)] }] } GC.Spread.Sheets.Designer.registerTemplate(THEME_SETTING_PANEL_TEMPLATE, themeSettingTemplate); const themeSettingPanel = { command: THEME_SETTING_PANEL_CMD, uiTemplate: THEME_SETTING_PANEL_TEMPLATE, position: "right", width: "400px", classList: ['theme-setting-demo'] } config.sidePanels.push(themeSettingPanel); config.commandMap = { [THEME_SETTING_PANEL_CMD]: themeSettingCMD } new spreadNS.Designer.Designer(document.getElementById('ribbonHost'), config); } function getDesignerCSSHref(themeName) { return 'gc.spread.sheets.designer' + (themeName === 'classic' ? '' : ('.' + themeName)); } function getRuntimeCSSHref(themeName) { return 'gc.spread.sheets.' + themeName; } function showLoadingMask() { let mask = document.createElement('div'); mask.id = 'loading-mask'; mask.innerText = i18n.loading; let target = document.querySelector('.theme-setting-demo'); if (getComputedStyle(target).position === "static") { target.style.position = "relative"; } mask.setAttribute('data-mask', '1'); target.appendChild(mask); } function hideLoadingMask() { let mask = document.getElementById('loading-mask'); if (mask) mask.remove(); } function withLoadingMask(promise) { showLoadingMask(); return promise.finally(hideLoadingMask); } function changeCSSScript (current, target) { let currentLink = document.querySelector(`link[href*="${current}"]`); let href = currentLink.href; return withLoadingMask(addLink(href.replace(current, target)).then(() => { currentLink.remove(); })); } function calcForegroundColor (backgroundColor) { const [r, g, b] = (s => s.startsWith('#') ? s.slice(1).match(/\w\w/g).map(x=>parseInt(x,16)) : s.match(/\d+/g).map(Number))(backgroundColor); const grayLevel = (0.299 * r + 0.587 * g + 0.114 * b) / 255; return grayLevel > 0.5 ? "#000000" : "#ffffff"; } function addLink (href) { return new Promise((resolve, reject) => { const link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet"; link.href = href; link.onload = function () { resolve(); }; const header = document.head; header.insertBefore(link, header.firstElementChild); }) }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture" content="ja-jp" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.light.min.css"> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-datacharts-addon/dist/gc.spread.sheets.datacharts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-resources-ja/dist/gc.spread.sheets.resources.ja.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-designer-resources-ja/dist/gc.spread.sheets.designer.resource.ja.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ja/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/designer/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <script src="color-tool.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="container"> <div class="spreadSheet"> <div id="ribbonHost"></div> <div id="ss"></div> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .container { height: 100%; } .spreadSheet { height: 100%; } #ribbonHost { height: 100%; } .description { margin: 10px; width: 40%; } .gc-designer-label-container { background-color: var(--sjs-color-background); } .custom-theme-demo .gc-combo-editor-container { width: 120px; margin-right: 10px; } .custom-theme-demo { justify-content: space-between } #loading-mask { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--sjs-color-background, #fff); color: var(--sjs,color-foreground, #000); display: flex; align-items: center; justify-content: center; font-size: 22px; z-index: 99; opacity: 0.8; }