You can create a custom shape with a model, as shown below:
For path, the meaning of each parameter is:
"M": means moveTo(x,y)
"L": means lineTo(x,y)
"B": means bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
"Q": means quadraticCurveTo(cpx, cpy, x, y)
"A": means arc(x, y, r, startAngle, endAngle)
"A":' means arcTo(x1, y1, x2, y2, r)
"Z": means closePath
<template>
<div class="sample-tutorial">
<gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread">
<gc-worksheet :name="'Car Insurance Claim'"></gc-worksheet>
<gc-worksheet :name="'Damage_Areas'"></gc-worksheet>
</gc-spread-sheets>
</div>
</template>
<script>
import Vue from "vue";
import "@mescius/spread-sheets-vue";
import "@mescius/spread-sheets-shapes";
import GC from "@mescius/spread-sheets";
let App = Vue.extend({
name: "app",
data: function () {
return {
spread: null,
};
},
methods: {
initSpread(spread) {
initDamageAreaShapes(spread);
let activeSheet = spread.getActiveSheet();
let workbookShapes = activeSheet.shapes.all();
for (let s = 0; s < workbookShapes.length; s++) {
workbookShapes[s].allowMove(false);
workbookShapes[s].allowResize(false);
}
}
}
});
function initDamageAreaShapes(spread) {
let sheet = spread.getSheet(0);
let damageAreaSheet = spread.getSheet(1);
damageAreaSheet.setColumnWidth(0,120);
var table = damageAreaSheet.tables.add("table1", 0, 0, 7, 4, GC.Spread.Sheets.Tables.TableThemes.medium4);
table.filterButtonVisible(false);
var damageAreas = ["Area", "Left", "Top", "Color"],
carFront = ["carFront", 50, 50, "orange"],
carFrontDoor = ["carFrontDoor", 197, 23, "orange"],
carBackDoor = ["carBackDoor", 332, 23, "orange"],
carBack = ["carBack", 405, 24, "orange"],
carFrontWheel = ["carFrontWheel", 45, 64, "orange"],
carBackWheel = ["carBackWheel", 361, 64, "orange"];
damageAreaSheet.setArray(0, 0, [
damageAreas,
carFront,
carFrontDoor,
carBackDoor,
carBack,
carFrontWheel,
carBackWheel
]);
let carFrontModel = {
left: "=Damage_Areas!B2",
top: "=Damage_Areas!C2",
width: 157,
height: 85,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D2",
transparency: "0.5"
}
},
path: [
[
["M", 6, 48],
["L", 21, 29],
["L", 59, 20],
["L", 136, 14],
["L", 157, 8],
["L", 150, 24],
["L", 148, 47],
["L", 150, 69],
["L", 157, 85],
["L", 140, 85],
//Wheel well
["L", 136, 71],
["L", 128, 58],
["L", 119, 52],
["L", 107, 47],
["L", 94, 46],
["L", 83, 47],
["L", 68, 52],
["L", 60, 61],
["L", 54, 70],
["L", 50, 85],
["L", 21, 85],
["L", 13, 71],
["L", 2, 67],
["Z"]
]
]
};
let carFrontDoorModel = {
left: "=Damage_Areas!B3",
top: "=Damage_Areas!C3",
width: 140,
height: 112,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D3",
transparency: "0.5"
}
},
path: [
[
["M", 9, 36],
["L", 84, 2],
["L", 116, 0],
["L", 140, 0],
["L", 134, 74],
["L", 140, 112],
["L", 12, 112],
["L", 7, 105],
["L", 4, 96],
["L", 1, 81],
["L", 2, 64],
["L", 5, 49],
["Z"]
]
]
};
let carBackDoorModel = {
left: "=Damage_Areas!B4",
top: "=Damage_Areas!C4",
width: 121,
height: 111,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D4",
transparency: "0.5"
}
},
path: [
[
["M", 6, 0],
["L", 71, 1],
["L", 95, 20],
["L", 115, 44],
["L", 121, 53],
["L", 117, 62],
["L", 105, 68],
["L", 87, 85],
["L", 78, 100],
["L", 75, 111],
["L", 5, 111],
["L", 2, 97],
["L", 0, 79],
["L", 1, 61],
["L", 3, 38],
["Z"]
]
]
};
let carBackModel = {
left: "=Damage_Areas!B5",
top: "=Damage_Areas!C5",
width: 168,
height: 110,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D5",
transparency: "0.5"
}
},
path: [
[
["M", 0, 0],
["L", 51, 9],
["L", 110, 34],
["L", 154, 43],
["L", 163, 49],
["L", 166, 55],
["L", 152, 55],
["L", 149, 73],
["L", 168, 80],
["L", 168, 91],
["L", 164, 97],
["L", 159, 97],
["L", 153, 110],
["L", 100, 110],
//Wheel well
["L", 96, 97],
["L", 86, 84],
["L", 69, 74],
["L", 60, 72],
["L", 50, 73],
["L", 40, 73],
["L", 32, 78],
["L", 24, 85],
["L", 19, 92],
["L", 14, 101],
["L", 13, 110],
["L", 3, 110],
["L", 9, 96],
["L", 17, 81],
["L", 31, 69],
["L", 44, 61],
["L", 49, 55],
["L", 44, 44],
["L", 29, 27],
["L", 14, 12],
["Z"]
]
]
};
let carFrontWheelModel = {
left: "=Damage_Areas!B6",
top: "=Damage_Areas!C6",
width: 168,
height: 168,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D6",
transparency: "0.5"
}
},
path: [
[
["A", 100, 75, 40, 0, 2 * Math.PI],
["Z"]
]
]
};
let carBackWheelModel = {
left: "=Damage_Areas!B7",
top: "=Damage_Areas!C7",
width: 168,
height: 168,
options: {
fill: {
type: 1,
color: "=Damage_Areas!D7",
transparency: "0.5"
}
},
path: [
[
["A", 100, 75, 40, 0, 2 * Math.PI],
["Z"]
]
]
};
sheet.shapes.add('carFront', carFrontModel);
sheet.shapes.add('carFrontDoor', carFrontDoorModel);
sheet.shapes.add('carBackDoor', carBackDoorModel);
sheet.shapes.add('carBack', carBackModel);
sheet.shapes.add('carFrontWheel', carFrontWheelModel);
sheet.shapes.add('carBackWheel', carBackWheelModel);
}
new Vue({
render: h => h(App)
}).$mount("#app");
</script>
<style scoped>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
.sample-spreadsheets {
width: 100%;
height: 100%;
overflow: hidden;
float: left;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
<!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$/en/vue/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- SystemJS -->
<script src="$DEMOROOT$/en/vue/node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('./src/app.vue');
System.import('$DEMOROOT$/en/lib/vue/license.js');
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
meta: {
'*.css': { loader: 'css' },
'*.vue': { loader: 'vue-loader' }
},
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-vue': 'npm:@mescius/spread-sheets-vue/index.js',
'@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'jszip': 'npm:jszip/dist/jszip.js',
'css': 'npm:systemjs-plugin-css/css.js',
'vue': 'npm:vue/dist/vue.min.js',
'vue-loader': 'npm:systemjs-vue-browser/index.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'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
"node_modules": {
defaultExtension: 'js'
}
}
});
})(this);