Shape Text

SpreadJS allows you to add text in shapes. By using textEffect, and textFrame you will have the possibility to format the added text to your liking.

You can customize the properties of autoShapes using the Shape API: text: Gets or sets the text of the shape. You can use the textDirection property of the textFrame in the Style: this property is used to get or set the text direction of the shape. The TextDirection enum defines the direction of the text in the shape.
<template> <div class="sample-tutorial"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> </gc-spread-sheets> <shape-panel @updateShapeStyle="updateShapeStyle" :showShapeTxtPanelRef="showShapeTxtPanelRef"> </shape-panel> </div> </template> <script setup> import GC from "@mescius/spread-sheets"; import { ref, createApp } from "vue"; import "@mescius/spread-sheets-vue"; import '@mescius/spread-sheets-shapes'; const spreadRef = ref(null); const showShapeTxtPanelRef = ref(false); const updateShapeStyle = (action, value) => { let sheet = spreadRef.value.getActiveSheet(); let activeShape = sheet.shapes.all().filter(function (sp) { return sp.isSelected(); }); if (activeShape.length > 0) { activeShape.forEach((shape) => { if (shape instanceof GC.Spread.Sheets.Shapes.Shape) { _setShapeStyle(shape, action, value); } }); sheet.repaint(); } } const _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); } } const bindSpreadEvent = () => { spreadRef.value.bind(GC.Spread.Sheets.Events.ShapeSelectionChanged, function () { let sheet = spreadRef.value.getActiveSheet(); var selectedShape = sheet.shapes.all().filter(function (sp) { return sp.isSelected(); }); var isShapeSelected = false, isConnectorSelected = false; if (selectedShape.length > 0) { selectedShape.forEach((shape) => { if (!isShapeSelected && shape instanceof GC.Spread.Sheets.Shapes.Shape) { isShapeSelected = true; } else if (!isConnectorSelected && shape instanceof GC.Spread.Sheets.Shapes.ConnectorShape) { isConnectorSelected = true; } }); setShapePropVisibility(isShapeSelected); } else { setShapePropVisibility(false); } }) } const setShapePropVisibility = (isShow) => { showShapeTxtPanelRef.value = isShow; } const initSpread = (spread) => { spreadRef.value = spread; 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); bindSpreadEvent(); } </script> <style scoped> .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; } #app { height: 100%; } </style>
<template> <div class="options-container"> <div class="option-row"> Try selecting a shape and change the text properties to see the outcome: </div> <div id="divideLine" class="divide-line"></div> <div v-show="showShapeTxtPanelRef" class="option-row"> <label>Text: </label> <textarea v-model="textRef" type="text" placeholder="Shape text" rows="3"></textarea> <input type="button" @click="_handleShapeStyleSetting('text', textRef)" value="Set" /> <label>Text Direction:</label> <select v-model.number="textDirectionRef"> <option v-bind:value="item.value" v-for="item in textDirectionList" :key="item.text">{{ item.text }}</option> </select> <input type="button" @click="_handleShapeStyleSetting('textDirection', textDirectionRef)" value="Set" /> <label>Text Color: </label> <input v-model="textColorRef" type="color" value="#FFFF00" /> <input type="button" @click="_handleShapeStyleSetting('color', textColorRef)" value="Set" /> <label>Text Transparency: </label> <input v-model.number="transparencyTxtRef" type="text" value="0.5" /> <input type="button" @click="_handleShapeStyleSetting('transparencyTxt', transparencyTxtRef)" value="Set" /> <label>Text Font: </label> <input v-model="fontRef" type="text" /> <input type="button" @click="_handleShapeStyleSetting('font', fontRef)" value="Set" /> <label> Horizontal Align:</label> <select v-model.number="hAlignRef"> <option v-bind:value="item.value" v-for="item in horizontalAlignListRef" :key="item.name">{{ item.name }} </option> </select> <input type="button" @click="_handleShapeStyleSetting('hAlign', hAlignRef)" value="Set" /> <label>Vertical Align:</label> <select v-model.number="vAlignRef"> <option v-bind:value="item.value" v-for="item in verticalAlignListRef" :key="item.name">{{ item.name }}</option> </select> <input type="button" @click="_handleShapeStyleSetting('vAlign', vAlignRef)" value="Set" /> <label>Resize To Fit Text:</label> <select v-model.number="resizeToFitTextRef"> <option v-bind:value="item.value" v-for="item in resizeToFitTextListRef" :key="item.name">{{ item.name }} </option> </select> <input type="button" @click="_handleShapeStyleSetting('resizeToFitText', resizeToFitTextRef)" value="Set" /> </div> </div> </template> <script setup> import GC from "@mescius/spread-sheets"; import "@mescius/spread-sheets-shapes"; import { defineEmits, ref } from 'vue'; let horizontalAlign = { left: 0, center: 1, right: 2 }; let verticalAlign = { top: 0, center: 1, bottom: 2 }; let resizeToFitTextOptions = { false: 0, true: 1 }; const textRef = ref(`abcdefgHIJKLMN 12356789 SpreadJSSpreadJS`); const textColorRef = ref("#FFFF00"); const transparencyTxtRef = ref(0.5); const fontRef = ref("bold 15px Georgia"); const textDirectionRef = ref(0); const hAlignRef = ref(1); const vAlignRef = ref(1); const resizeToFitTextRef = ref(0); const textDirectionList = [ {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} ]; const horizontalAlignListRef = ref(getEnumList(horizontalAlign)); const verticalAlignListRef = ref(getEnumList(verticalAlign)); const resizeToFitTextListRef = ref(getEnumList(resizeToFitTextOptions)); const props = defineProps({ showShapeTxtPanelRef: Boolean }); const emits = defineEmits(['updateShapeStyle']); const _handleShapeStyleSetting = (action, value) => { emits("updateShapeStyle", action, value); } function getEnumList(enumObject) { let names = []; for (var name in enumObject) { if (name === "none" || (parseInt(name, 10)) == name) { continue; } names.push({ name: name, value: enumObject[name] }); } names.sort(function (a, b) { return a.name > b.name ? 1 : -1 }); return names; } </script> <style scoped></style>
<!DOCTYPE html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>SpreadJS VUE</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/data/inventory-tracker.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script> <script src="./systemjs.config.js"></script> <script src="./compiler.js" type="module"></script> <script> var System = SystemJS; System.import("./src/app.js"); System.import('$DEMOROOT$/en/lib/vue3/license.js'); </script> </head> <body> <div id="app"></div> </body> </html>
(function (global) { SystemJS.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, packageConfigPaths: [ './node_modules/*/package.json', "./node_modules/@mescius/*/package.json", "./node_modules/@babel/*/package.json", "./node_modules/@vue/*/package.json" ], map: { 'vue': "npm:vue/dist/vue.esm-browser.js", 'tiny-emitter': 'npm:tiny-emitter/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', "systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js", '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js' }, meta: { '*.css': { loader: 'systemjs-plugin-css' }, '*.vue': { loader: "../plugin-vue/index.js" } } }); })(this);