形状文本样式定制

SpreadJS 支持在形状中添加和自定义文本样式,包括文本内容、颜色、透明度、字体、对齐方式以及文本方向等属性。本功能帮助用户在表格中创建具有丰富文本效果的形状元素,适用于数据标注、流程图设计、报表美化等多种场景。

概述 本 Demo 展示了如何通过 Shape API 为形状设置丰富的文本样式。Demo 创建了四种不同类型的形状(矩形、三角形、六边形、椭圆),并提供交互式面板,允许用户动态调整形状中文本的内容、颜色、透明度、字体、对齐方式以及文本方向。 实现思路 在工作表中添加四个不同类型的形状作为示例对象 监听形状选择事件,当用户选中形状时显示文本属性面板 为每个文本属性设置项绑定按钮点击事件,调用相应的 API 修改形状样式 根据用户输入动态更新形状的文本效果(textEffect)和文本框(textFrame)属性 代码解析 创建形状并设置初始样式 这段代码使用 shapes.add() 方法创建了四个形状。每个形状都有名称、类型和位置尺寸参数。 设置文本内容 使用 shape.text() 方法直接设置形状的文本内容,支持多行文本(使用 \n 换行)。 设置文本样式属性 这段代码展示了如何通过修改 style 对象的 textEffect 和 textFrame 属性来自定义文本样式。所有样式修改都需要通过 shape.style(shapeStyle) 重新应用到形状上。 处理文本方向的自动对齐 当设置某些特定的文本方向(如垂直方向)时,代码会自动调整水平对齐方式,确保文本显示效果最佳。 运行效果 页面加载后,工作表中显示四个不同类型的形状 点击任意形状,右侧面板会显示文本属性设置选项 输入文本内容并点击"设置"按钮,形状中会显示对应的文本 使用文本方向下拉框可选择 7 种不同的文本方向:水平、垂直(从左到右)、垂直、旋转 90°、旋转 270°、堆积、堆积(从右到左) 调整文本颜色、透明度、字体可以实时改变文本的视觉效果 设置水平和垂直对齐可以控制文本在形状中的位置 启用"根据文本调整大小"选项后,形状会自动调整尺寸以适应文本内容 API 参考 shape.text(value) 设置或获取形状的文本内容。 value:文本字符串,支持使用 \n 换行 shape.style(value?) 获取或设置形状的样式对象。 value:可选,ShapeStyle 对象,包含 fill、line、textEffect、textFrame 等属性 textEffect 属性 color:文本颜色,字符串格式(如 'red'、'#FF0000') transparency:文本透明度,0-1 之间的数值 font:字体设置,字符串格式(如 'bold 15px Georgia') textFrame 属性 hAlign:水平对齐,使用 GC.Spread.Sheets.HorizontalAlign 枚举(left、center、right) vAlign:垂直对齐,使用 GC.Spread.Sheets.VerticalAlign 枚举(top、center、bottom) textDirection:文本方向,使用 GC.Spread.Sheets.Shapes.TextDirection 枚举 resizeToFitText:布尔值,是否自动调整形状大小以适应文本 TextDirection 枚举值 horz:水平(默认) eaVertLtr:垂直(从左到右) eaVert:垂直(东亚语言) vert:旋转 90° vert270:旋转 270° wordArtVert:堆积 wordArtVertRtl:堆积(从右到左)
window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); initSpread(spread); initEvent(spread); }; var textDirections = [ {text: 'Horizontal', value: GC.Spread.Sheets.Shapes.TextDirection.horz }, {text: 'Vertical(Ltr)', value: GC.Spread.Sheets.Shapes.TextDirection.eaVertLtr}, {text: 'Vertical', value: GC.Spread.Sheets.Shapes.TextDirection.eaVert}, {text: 'Rotate all text 90°', value: GC.Spread.Sheets.Shapes.TextDirection.vert}, {text: 'Rotate all text 270°', value: GC.Spread.Sheets.Shapes.TextDirection.vert270}, {text: 'Stacked', value: GC.Spread.Sheets.Shapes.TextDirection.wordArtVert}, {text: 'Stacked(Rtl)', value: GC.Spread.Sheets.Shapes.TextDirection.wordArtVertRtl} ]; var horizontalAlign = { left: 0, center: 1, right: 2 }; var verticalAlign = { top: 0, center: 1, bottom: 2 }; var resizeToFitTextOptions = { false: 0, true: 1 } var activeShape; function fillShapeTextDirectionList(dom){ var html = ""; textDirections.forEach(function (item) { html += '<option value="' + item.value + '">' + item.text + '</option>'; }); dom.innerHTML= html; } function fillShapeTypeList(type, dom) { var names = []; for (var name in type) { if(name === "none" || (parseInt(name, 10)) == name) { continue; } names.push({name: name, value: type[name]}); } names.sort(function (a, b) { return a.name > b.name ? 1 : -1 }); var html = ""; names.forEach(function (item) { html += '<option value="' + item.value + '">' + item.name + '</option>'; }); dom.innerHTML= html; } function getActiveConnectorShape(sheet) { return sheet.shapes.all().filter(function(sp){ return sp.isSelected() && sp instanceof GC.Spread.Sheets.Shapes.ConnectorShape; }); } function initSpread(spread) { setShapePropVisibility("none"); fillShapeTextDirectionList(_getElementById("txtDirection")); fillShapeTypeList(horizontalAlign, _getElementById("txtHAlign")); fillShapeTypeList(verticalAlign, _getElementById("txtVAlign")); fillShapeTypeList(resizeToFitTextOptions, _getElementById("resizeToFitText")); _getElementById("txtText").value = "abcdefgHIJKLMN\n" + "12356789\n" + "SpreadJSSpreadJS"; spread.getActiveSheet().shapes.add("rectangle", GC.Spread.Sheets.Shapes.AutoShapeType.rectangle, 40, 20, 150, 150); spread.getActiveSheet().shapes.add("rightTriangle", GC.Spread.Sheets.Shapes.AutoShapeType.rightTriangle, 40, 230, 150, 150); spread.getActiveSheet().shapes.add("hexagon", GC.Spread.Sheets.Shapes.AutoShapeType.hexagon, 250, 20, 150, 150); spread.getActiveSheet().shapes.add("oval", GC.Spread.Sheets.Shapes.AutoShapeType.oval, 250, 230, 150, 150); } function setShapePropVisibility(display) { var shapeTxtProp = _getElementById("shapeTxtProp"); shapeTxtProp.style.display = display; } function initEvent(spread) { var spreadNS = GC.Spread.Sheets; var sheet = spread.getActiveSheet(); sheet.bind(spreadNS.Events.ShapeSelectionChanged, function () { var selectedShape = sheet.shapes.all().filter(function(sp){ return sp.isSelected(); }); var isShapeSelected = false, isConnectorSelected = false; if (selectedShape.length > 0) { selectedShape.forEach(function (shape) { if (!isShapeSelected && shape instanceof spreadNS.Shapes.Shape) { isShapeSelected = true; } else if (!isConnectorSelected && shape instanceof spreadNS.Shapes.ConnectorShape) { isConnectorSelected = true; } }); if (isShapeSelected) { setShapePropVisibility("block"); } else { setShapePropVisibility("none"); } } else { setShapePropVisibility("none"); } }); _getElementById("textActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'text', _getElementById("txtText")); }); _getElementById("txtDirectionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'textDirection', _getElementById("txtDirection")); }); _getElementById("colorActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'color', _getElementById("txtTextColor")); }); _getElementById("transparencyTxtActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'transparencyTxt', _getElementById("txtTextTransparency")); }); _getElementById("fontActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'font', _getElementById("txtFont")); }); _getElementById("hAlignActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'hAlign', _getElementById("txtHAlign")); }); _getElementById("vAlignActionBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'vAlign', _getElementById("txtVAlign")); }); _getElementById("resizeToFitTextBtn").addEventListener('click', function() { _handleShapeStyleSetting(spread, 'resizeToFitText', _getElementById("resizeToFitText")); }); } function _handleShapeStyleSetting(spread, action, valueDom) { var sheet = spread.getActiveSheet(); activeShape = sheet.shapes.all().filter(function(sp){ return sp.isSelected(); }); if (activeShape.length > 0) { activeShape.forEach(function (shape) { if (shape instanceof GC.Spread.Sheets.Shapes.Shape) { _setShapeStyle(shape, action, valueDom.value); } }); sheet.repaint(); } } function _setShapeStyle(shape, action, value) { if (action === 'text') { shape.text(value); } else { var shapeStyle = shape.style(); if (action ==='color') { shapeStyle.textEffect.color = value; } else if (action === 'transparencyTxt') { shapeStyle.textEffect.transparency = value; } else if (action === 'font') { shapeStyle.textEffect.font = value; } else if(action === 'textDirection'){ const textDirection = parseInt(value); shapeStyle.textFrame.textDirection = textDirection; switch (textDirection) { case GC.Spread.Sheets.Shapes.TextDirection.vert: case GC.Spread.Sheets.Shapes.TextDirection.wordArtVertRtl: case GC.Spread.Sheets.Shapes.TextDirection.eaVert: shapeStyle.textFrame.hAlign = GC.Spread.Sheets.HorizontalAlign.right; break; case GC.Spread.Sheets.Shapes.TextDirection.vert270: case GC.Spread.Sheets.Shapes.TextDirection.wordArtVert: case GC.Spread.Sheets.Shapes.TextDirection.eaVertLtr: shapeStyle.textFrame.hAlign = GC.Spread.Sheets.HorizontalAlign.left; break; } } else if (action === 'hAlign') { shapeStyle.textFrame.hAlign = parseInt(value); } else if (action === 'vAlign') { shapeStyle.textFrame.vAlign = parseInt(value); } else if (action === 'resizeToFitText') { shapeStyle.textFrame.resizeToFitText = value === '1'; } shape.style(shapeStyle); } } function _getElementById(id){ return document.getElementById(id); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="spreadjs culture" content="zh-cn" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> <div class="options-container"> <div class="option-row"> 尝试选择一个形状并更改文本属性以查看效果: </div> <div id="divideLine" class="divide-line"></div> <div id="shapeTxtProp" class="option-row"> <label>文本: </label> <textarea id='txtText' type="text" placeholder="形状文本" rows="3"></textarea> <input type="button" id='textActionBtn' value="设置" /> <label>文本方向: </label> <select id="txtDirection"></select> <input type="button" id='txtDirectionBtn' value="设置"/> <label>文本颜色: </label> <input id='txtTextColor' type="color" value="#FFFF00" /> <input type="button" id='colorActionBtn' value="设置" /> <label>文本透明度: </label> <input id='txtTextTransparency' type="text" value="0.5" /> <input type="button" id='transparencyTxtActionBtn' value="设置" /> <label>文本字体: </label> <input id='txtFont' type="text" value="bold 15px Georgia" /> <input type="button" id='fontActionBtn' value="设置" /> <label> 水平对齐:</label> <select id="txtHAlign"></select> <input type="button" id='hAlignActionBtn' value="设置" /> <label>垂直对齐:</label> <select id="txtVAlign"></select> <input type="button" id='vAlignActionBtn' value="设置" /> <label>根据文本调整大小:</label> <select id="resizeToFitText"></select> <input type="button" id='resizeToFitTextBtn' value="设置" /> </div> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding-left: 5px; } .divide-line { width: 100%; height: 1px; background: #cbcbcb; margin-top: 10px; margin-bottom: 3px; } .title { text-align: center; font-weight: bold; } label { display: block; margin-top: 15px; margin-bottom: 5px; } p { padding: 2px 10px; background-color: #F4F8EB; } input { width: 160px; margin-left: 10px; display: inline; } input[type=button] { width: 50px; margin-left: 1px; } select { width: 160px; margin-left: 10px; display: inline; } textarea { width: 160px; margin-left: 10px; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }