diff --git a/ide/build.js b/ide/build.js new file mode 100644 index 0000000000000000000000000000000000000000..17ea40aa71d11a237975315293478e11c628e01d --- /dev/null +++ b/ide/build.js @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const path = require('path'); +const fs = require('fs'); +const childProcess = require('child_process'); +const os = require('os'); +const log4js = require('log4js'); + +const compileServer = true; +const outDir = 'dist'; + +const sdkWams = [ + 'trace_streamer_sdk_builtin.js', + 'trace_streamer_sdk_builtin.wasm', + 'trace_streamer_dubai_builtin.js', + 'trace_streamer_dubai_builtin.wasm', + 'trace_converter_builtin.js', + 'trace_converter_builtin.wasm', +]; + +const necessaryWams = [ + 'trace_streamer_builtin.js', + 'trace_streamer_builtin.wasm', + 'trace_converter_builtin.js', + 'trace_converter_builtin.wasm', +]; + +const staticPath = ['/src/img', '/server/cert', '/src/doc', '/src/figures']; + +const staticFiles = [ + '/server/version.txt', + '/src/index.html', + '/src/base-ui/icon.svg', + '/server/wasm.json', + '/server/server-config.txt', +]; + +const thirdParty = [ + { + srcFilePath: '/third-party/sql-wasm.wasm', + distFilePath: '/trace/database/sql-wasm.wasm', + }, + { + srcFilePath: '/third-party/sql-wasm.js', + distFilePath: '/trace/database/sql-wasm.js', + }, + { + srcFilePath: '/third-party/worker.sql-wasm.js', + distFilePath: '/trace/database/worker.sql-wasm.js', + }, +]; + +let log; + +function cpFile(from, to) { + if (fs.existsSync(from)) { + fs.writeFileSync(to, fs.readFileSync(from)); + log.info('cp file %s to %s', from, to); + } else { + log.warn('file %s is not exists', from, to); + } +} + +function checkEnvironment() { + let goVersion = childProcess.execSync('go version', { + encoding: 'utf-8', + }); + log.info('go is', goVersion); + let nodeVersion = childProcess.execSync('node -v', { + encoding: 'utf-8', + }); + log.info('node version is', nodeVersion); + let tscVersion = childProcess.execSync('tsc -v', { + encoding: 'utf-8', + }); + log.info('tsc version is', tscVersion); + if (goVersion == '' || nodeVersion == '' || tscVersion == '') { + return false; + } + let traceStreamer = path.normalize(path.join(__dirname, '/bin')); + if (!checkDirExist(traceStreamer + '/trace_streamer_builtin.js')) { + log.error(traceStreamer + '/trace_streamer_builtin.js' + ' Must exist'); + return false; + } + if (!checkDirExist(traceStreamer + '/trace_streamer_builtin.wasm')) { + log.error(traceStreamer + '/trace_streamer_builtin.wasm' + ' Must exist'); + return false; + } + return true; +} + +function initLog() { + log4js.configure({ + appenders: { + out: { type: 'stdout' }, + }, + categories: { + default: { appenders: ['out'], level: 'debug' }, + }, + }); + return log4js.getLogger('smartPerf'); +} + +function main() { + log = initLog(); + if (!checkEnvironment()) { + return; + } + // clean outDir + let outPath = path.normalize(path.join(__dirname, '/', outDir)); + if (checkDirExist(outPath)) { + log.info('delete the last compilation result'); + removeDir(outPath); + log.info('delete the last compilation success'); + } + // run tsc compile + log.info('start compiling typeScript code'); + let rootPath = path.join(__dirname, '/'); + childProcess.execSync('tsc -p ' + rootPath, { + encoding: 'utf-8', + }); + log.info('compiling typeScript code success'); + // run cp to mv all staticFile + staticFiles.forEach((value) => { + let filePath = path.join(__dirname, value); + let distFile; + if (value.startsWith('/src')) { + distFile = path.join(__dirname, outDir, value.substring(4, value.length + 1)); + } else if (value.startsWith('/server')) { + distFile = path.join(__dirname, outDir, value.substring(7, value.length + 1)); + } + cpFile(filePath, distFile); + }); + staticPath.forEach((value) => { + let pa = path.join(__dirname, value); + let distPath; + if (value.startsWith('/src')) { + distPath = path.join(__dirname, outDir, value.substring(4, value.length + 1)); + } else if (value.startsWith('/server')) { + distPath = path.join(__dirname, outDir, value.substring(7, value.length + 1)); + } + copyDirectory(pa, distPath); + }); + thirdParty.forEach((value) => { + let thirdFile = path.join(__dirname, value.srcFilePath); + let thirdDistFile = path.join(__dirname, outDir, value.distFilePath); + cpFile(thirdFile, thirdDistFile); + }); + let traceStreamer = path.normalize(path.join(__dirname, '/bin')); + if (checkDirExist(traceStreamer)) { + let dest = path.normalize(path.join(__dirname, outDir, '/bin')); + copyDirectory(traceStreamer, dest); + // to mv traceStream Wasm and js + if (sdkWams.length > 0) { + sdkWams.forEach((fileName) => { + cpFile(traceStreamer + '/' + fileName, rootPath + outDir + '/trace/database/' + fileName); + }); + } + if (necessaryWams.length > 0) { + necessaryWams.forEach((fileName) => { + cpFile(traceStreamer + '/' + fileName, rootPath + outDir + '/trace/database/' + fileName); + }); + } + } else { + log.error('traceStreamer dir is not Exits'); + return; + } + // compile server + if (compileServer) { + log.log('start compile server'); + let serverSrc = path.normalize(path.join(__dirname, '/server/main.go')); + let rs; + if (os.type() === 'Windows_NT') { + rs = childProcess.spawnSync('go', ['build', '-o', outPath, serverSrc], { + encoding: 'utf-8', + }); + } else { + rs = childProcess.spawnSync('go', ['build', '-o', outPath + '/main', serverSrc], { + encoding: 'utf-8', + }); + } + if (rs.status == 0) { + log.log('compile server success'); + } else { + log.error('compile server failed', rs); + } + } else { + log.warn('skip compile server'); + } + log.log('smartPerf compile success'); +} + +function copyDirectory(src, dest) { + if (checkDirExist(dest) == false) { + fs.mkdirSync(dest); + } + if (checkDirExist(src) == false) { + return false; + } + let directories = fs.readdirSync(src); + directories.forEach((value) => { + let filePath = path.join(src, value); + let fileSys = fs.statSync(filePath); + if (fileSys.isFile()) { + let destPath = path.join(dest, value); + log.info('cp file %s to %s', filePath, destPath); + fs.copyFileSync(filePath, destPath); + } else if (fileSys.isDirectory()) { + copyDirectory(filePath, path.join(dest, value)); + } + }); +} + +function checkDirExist(dirPath) { + return fs.existsSync(dirPath); +} + +function removeDir(outPath) { + let files = []; + if (fs.existsSync(outPath)) { + files = fs.readdirSync(outPath); + files.forEach((file, index) => { + let curPath = outPath + '/' + file; + if (fs.statSync(curPath).isDirectory()) { + removeDir(curPath); + } else { + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(outPath); + } +} + +main(); diff --git a/ide/src/base-ui/button/LitButton.ts b/ide/src/base-ui/button/LitButton.ts index e04eb065bbc1bf135fead4bd69ca46a18ecb66f9..9c2c9b12db41cebea0d3d78c6742cb277ba0b344 100644 --- a/ide/src/base-ui/button/LitButton.ts +++ b/ide/src/base-ui/button/LitButton.ts @@ -128,19 +128,10 @@ export class LitButton extends BaseElement { initHtml(): string { return ` - ${this.initHtmlStyle()} -
- -
- `; - } - - private initHtmlStyle(): string { - return ` - - ` +
+ +
+ `; } initElements(): void { diff --git a/ide/src/base-ui/chart/column/LitChartColumn.ts b/ide/src/base-ui/chart/column/LitChartColumn.ts index 7aff26a18a59da7fa8e8804b24f27deb168144d3..9686adff97a3241eb4d28e16a63c9507e5762b50 100644 --- a/ide/src/base-ui/chart/column/LitChartColumn.ts +++ b/ide/src/base-ui/chart/column/LitChartColumn.ts @@ -193,102 +193,62 @@ export class LitChartColumn extends BaseElement { return this.litChartColumnCfg?.data || []; } - dataSort():void{ - if (!this.litChartColumnCfg!.notSort) { - this.litChartColumnCfg?.data.sort( - (a, b) => b[this.litChartColumnCfg!.yField] - a[this.litChartColumnCfg!.yField] - ); - } - } - - haveSeriesField():void{ - let maxValue = Math.max(...this.litChartColumnCfg!.data.map((it) => it[this.litChartColumnCfg!.yField])); - maxValue = Math.ceil(maxValue * 0.1) * 10; - let partWidth = (this.clientWidth - this.offset!.x!) / this.litChartColumnCfg!.data.length; - let partHeight = this.clientHeight - this.offset!.y!; - let gap = partHeight / 5; - let valGap = maxValue / 5; - for (let i = 0; i <= 5; i++) { - this.rowLines.push({ - y: gap * i, - label: - this.litChartColumnCfg!.removeUnit === true - ? `${maxValue - valGap * i}` - : `${getProbablyTime(maxValue - valGap * i)}`, - }); - } - this.dataSort(); - this.litChartColumnCfg?.data.forEach((litChartColumnItem, litChartColumnIndex, array) => { - this.data.push({ - color: this.litChartColumnCfg!.color(litChartColumnItem), - obj: litChartColumnItem, - root: true, - xLabel: litChartColumnItem[this.litChartColumnCfg!.xField], - yLabel: litChartColumnItem[this.litChartColumnCfg!.yField], - bgFrame: { - x: this.offset!.x! + partWidth * litChartColumnIndex, - y: 0, - w: partWidth, - h: partHeight, - }, - centerX: this.offset!.x! + partWidth * litChartColumnIndex + partWidth / 2, - centerY: - partHeight - - (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue + - (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 2, - frame: { - x: this.offset!.x! + partWidth * litChartColumnIndex + partWidth / 6, - y: partHeight - (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue, - w: partWidth - partWidth / 3, - h: (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue, - }, - height: 0, - heightStep: Math.ceil((litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 60), - process: true, - }); - }); - } - - noSeriesField(itemEl:any,y:number,initH:number,maxValue:number,partWidth:number,partHeight:number,reduceGroupIndex:number):void{ - this.data.push({ - color: this.litChartColumnCfg!.color(itemEl), - obj: itemEl, - root: y === 0, - type: itemEl[this.litChartColumnCfg!.seriesField], - xLabel: itemEl[this.litChartColumnCfg!.xField], - yLabel: itemEl[this.litChartColumnCfg!.yField], - bgFrame: { - x: this.offset!.x! + partWidth * reduceGroupIndex, - y: 0, - w: partWidth, - h: partHeight, - }, - centerX: this.offset!.x! + partWidth * reduceGroupIndex + partWidth / 2, - centerY: - partHeight - - initH - - (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue + - (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 2, - frame: { - x: this.offset!.x! + partWidth * reduceGroupIndex + partWidth / 6, - y: partHeight - (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue - initH, - w: partWidth - partWidth / 3, - h: (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue, - }, - height: 0, - heightStep: Math.ceil((itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 60), - process: true, - }); - } - measure() { if (!this.litChartColumnCfg) return; this.data = []; this.rowLines = []; if (!this.litChartColumnCfg.seriesField) { - this.haveSeriesField(); + let maxValue = Math.max(...this.litChartColumnCfg.data.map((it) => it[this.litChartColumnCfg!.yField])); + maxValue = Math.ceil(maxValue * 0.1) * 10; + let partWidth = (this.clientWidth - this.offset!.x!) / this.litChartColumnCfg.data.length; + let partHeight = this.clientHeight - this.offset!.y!; + let gap = partHeight / 5; + let valGap = maxValue / 5; + for (let i = 0; i <= 5; i++) { + this.rowLines.push({ + y: gap * i, + label: + this.litChartColumnCfg.removeUnit === true + ? `${maxValue - valGap * i}` + : `${getProbablyTime(maxValue - valGap * i)}`, + }); + } + if (!this.litChartColumnCfg.notSort) { + this.litChartColumnCfg?.data.sort( + (a, b) => b[this.litChartColumnCfg!.yField] - a[this.litChartColumnCfg!.yField] + ); + } + this.litChartColumnCfg?.data.forEach((litChartColumnItem, litChartColumnIndex, array) => { + this.data.push({ + color: this.litChartColumnCfg!.color(litChartColumnItem), + obj: litChartColumnItem, + root: true, + xLabel: litChartColumnItem[this.litChartColumnCfg!.xField], + yLabel: litChartColumnItem[this.litChartColumnCfg!.yField], + bgFrame: { + x: this.offset!.x! + partWidth * litChartColumnIndex, + y: 0, + w: partWidth, + h: partHeight, + }, + centerX: this.offset!.x! + partWidth * litChartColumnIndex + partWidth / 2, + centerY: + partHeight - + (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue + + (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 2, + frame: { + x: this.offset!.x! + partWidth * litChartColumnIndex + partWidth / 6, + y: partHeight - (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue, + w: partWidth - partWidth / 3, + h: (litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue, + }, + height: 0, + heightStep: Math.ceil((litChartColumnItem[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 60), + process: true, + }); + }); } else { - let reduceGroup = this.litChartColumnCfg!.data.reduce((pre, current, index, arr) => { + let reduceGroup = this.litChartColumnCfg.data.reduce((pre, current, index, arr) => { (pre[current[this.litChartColumnCfg!.xField]] = pre[current[this.litChartColumnCfg!.xField]] || []).push( current ); @@ -318,7 +278,35 @@ export class LitChartColumn extends BaseElement { let elements = reduceGroup[reduceGroupKey]; let initH = 0; elements.forEach((itemEl: any, y: number) => { - this.noSeriesField(itemEl,y,initH,maxValue,partWidth,partHeight,reduceGroupIndex); + this.data.push({ + color: this.litChartColumnCfg!.color(itemEl), + obj: itemEl, + root: y == 0, + type: itemEl[this.litChartColumnCfg!.seriesField], + xLabel: itemEl[this.litChartColumnCfg!.xField], + yLabel: itemEl[this.litChartColumnCfg!.yField], + bgFrame: { + x: this.offset!.x! + partWidth * reduceGroupIndex, + y: 0, + w: partWidth, + h: partHeight, + }, + centerX: this.offset!.x! + partWidth * reduceGroupIndex + partWidth / 2, + centerY: + partHeight - + initH - + (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue + + (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 2, + frame: { + x: this.offset!.x! + partWidth * reduceGroupIndex + partWidth / 6, + y: partHeight - (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue - initH, + w: partWidth - partWidth / 3, + h: (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue, + }, + height: 0, + heightStep: Math.ceil((itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue / 60), + process: true, + }); initH += (itemEl[this.litChartColumnCfg!.yField] * partHeight) / maxValue; }); }); diff --git a/ide/src/base-ui/chart/pagenation/PageNation.ts b/ide/src/base-ui/chart/pagenation/PageNation.ts index 5c6da0e9b8fa2c8340f924ace127f137cacea61c..77bd3c95a0d19a4dc1b9dd0849f07385c367f0f8 100644 --- a/ide/src/base-ui/chart/pagenation/PageNation.ts +++ b/ide/src/base-ui/chart/pagenation/PageNation.ts @@ -14,7 +14,7 @@ */ export class PageNation { - element: any; + element: any; pageInfo: any; first: any; prev: any; @@ -91,44 +91,6 @@ export class PageNation { }); } - createElement(jumpDiv:HTMLElement):void{ - // Create input field - this.inputBox = document.createElement('input'); - this.inputBox.value = this.pageInfo.current; - this.setElementStyles(this.inputBox, { - width: '35px', - height: '30px', - textAlign: 'center', - outline: 'none', - padding: '0', - border: '0', - 'border-radius': '5px', - }); - jumpDiv.appendChild(this.inputBox); - let span = document.createElement('span'); - span.style.width = '1px'; - span.style.height = '24px'; - span.style.alignSelf = 'center'; - span.style.backgroundColor = '#999999'; - jumpDiv.appendChild(span); - // Create button - this.btn = document.createElement('button'); - this.btn.innerText = ''; - this.btn.name = 'goto'; - this.setElementStyles(this.btn, { - height: '32px', - width: '30px', - cursor: 'pointer', - backgroundColor: '#FFF', - border: '0', - 'border-radius': '5px', - }); - this.btn.style.background = `url('img/arrowright.png') no-repeat 98% center var(--dark-background3,#FFFFFF)`; - this.btn.style.backgroundPosition = 'center'; - jumpDiv.appendChild(this.btn); - this.element.appendChild(jumpDiv); - } - // 创建元素 首页 上一页 按钮组 下一页 尾页 输入框 按钮 createPageElement() { //首页 @@ -140,15 +102,18 @@ export class PageNation { cursor: 'pointer', margin: '0 5px', }); + this.first = this.origin.cloneNode(true); this.first.innerText = this.pageInfo.first; this.first.name = 'first'; this.element.appendChild(this.first); + this.prev = this.origin.cloneNode(true); this.prev.innerText = '<'; this.prev.name = 'prev'; this.prev.style.padding = '5px 10px'; this.element.appendChild(this.prev); + // 创建ul this.list = document.createElement('ul'); this.setElementStyles(this.list, { @@ -176,7 +141,41 @@ export class PageNation { jumpDiv.style.height = '32px'; jumpDiv.style.marginLeft = '10px'; - this.createElement(jumpDiv); + // 创建输入框 + this.inputBox = document.createElement('input'); + this.inputBox.value = this.pageInfo.current; + this.setElementStyles(this.inputBox, { + width: '35px', + height: '30px', + textAlign: 'center', + outline: 'none', + padding: '0', + border: '0', + 'border-radius': '5px', + }); + jumpDiv.appendChild(this.inputBox); + let span = document.createElement('span'); + span.style.width = '1px'; + span.style.height = '24px'; + span.style.alignSelf = 'center'; + span.style.backgroundColor = '#999999'; + jumpDiv.appendChild(span); + // 创建按钮 + this.btn = document.createElement('button'); + this.btn.innerText = ''; + this.btn.name = 'goto'; + this.setElementStyles(this.btn, { + height: '32px', + width: '30px', + cursor: 'pointer', + backgroundColor: '#FFF', + border: '0', + 'border-radius': '5px', + }); + this.btn.style.background = `url('img/arrowright.png') no-repeat 98% center var(--dark-background3,#FFFFFF)`; + this.btn.style.backgroundPosition = 'center'; + jumpDiv.appendChild(this.btn); + this.element.appendChild(jumpDiv); } // 判断首页 上一页 下一页 尾页 是否可以点击 @@ -210,8 +209,10 @@ export class PageNation { } bindPageList() { - this.list.innerHTML = '';// clear ul its contents - const { pageSize, current, totalpage } = this.pageInfo;//Clean the ul before each load + // clear ul里面的内容 + this.list.innerHTML = ''; + //每次加载之前先清空ul里面的内容 + const { pageSize, current, totalpage } = this.pageInfo; const origin = document.createElement('li'); origin.dataset.name = 'item'; this.setElementStyles(origin, { @@ -228,11 +229,11 @@ export class PageNation { } return; } - // Five on the left... Two on the right + // 左边5个 中间 ... 右边2个 if (this.bindLeftList(current, totalpage, origin)) { return; } - // The current page is larger than 5 pages and smaller than the last 5 pages + // 当前页面 大于5页 小于倒数第5页 for (let index = 0; index < 2; index++) { this.buildLi(origin, index, current); } @@ -308,24 +309,20 @@ export class PageNation { } if (current == totalpage - 4) { // 左边5个 中间 ... 右边2个 - this.nodeAppendChild(origin,current,span,totalpage); + for (let i = 0; i < 2; i++) { + this.buildLi(origin, i, current); + } + span = document.createElement('span'); + span.innerText = '...'; + this.list.appendChild(span); + for (let i = totalpage - 7; i < totalpage; i++) { + this.buildLi(origin, i, current); + } return true; } return false; } - nodeAppendChild(origin: HTMLElement,current: number,span: any,totalpage: number):void{ - for (let i = 0; i < 2; i++) { - this.buildLi(origin, i, current); - } - span = document.createElement('span'); - span.innerText = '...'; - this.list.appendChild(span); - for (let i = totalpage - 7; i < totalpage; i++) { - this.buildLi(origin, i, current); - } - } - bindPageEvent() { this.element.addEventListener( 'click', @@ -336,7 +333,26 @@ export class PageNation { innerText: number; }; }) => { - this.targetName(event); + if (event.target.name === 'first') { + if (this.pageInfo.current === 1) return; + this.pageInfo.current = 1; + this.bindPageHtml(); + } + if (event.target.name === 'prev') { + if (this.pageInfo.current === 1) return; + this.pageInfo.current--; + this.bindPageHtml(); + } + if (event.target.name === 'next') { + if (this.pageInfo.current === this.pageInfo.totalpage) return; + this.pageInfo.current++; + this.bindPageHtml(); + } + if (event.target.name === 'last') { + if (this.pageInfo.current === this.pageInfo.totalpage) return; + this.pageInfo.current = this.pageInfo.totalpage; + this.bindPageHtml(); + } if (event.target.name === 'goto') { // 拿到你文本的内容 let page = this.inputBox.value - 0; @@ -359,33 +375,4 @@ export class PageNation { } ); } - - targetName(event:{ - target: { - name: string; - dataset: { name: string }; - innerText: number; - }; - }):void{ - if (event.target.name === 'first') { - if (this.pageInfo.current === 1) return; - this.pageInfo.current = 1; - this.bindPageHtml(); - } - if (event.target.name === 'prev') { - if (this.pageInfo.current === 1) return; - this.pageInfo.current--; - this.bindPageHtml(); - } - if (event.target.name === 'next') { - if (this.pageInfo.current === this.pageInfo.totalpage) return; - this.pageInfo.current++; - this.bindPageHtml(); - } - if (event.target.name === 'last') { - if (this.pageInfo.current === this.pageInfo.totalpage) return; - this.pageInfo.current = this.pageInfo.totalpage; - this.bindPageHtml(); - } - } } diff --git a/ide/src/base-ui/chart/pie/LitChartPie.ts b/ide/src/base-ui/chart/pie/LitChartPie.ts index ffa1e6c9ca78e511e2831bea45b7519904653d80..55d6fe23efeaed93db3aa1e0d15f21a75e409b97 100644 --- a/ide/src/base-ui/chart/pie/LitChartPie.ts +++ b/ide/src/base-ui/chart/pie/LitChartPie.ts @@ -45,97 +45,6 @@ class Sector { }; } -const initHtmlStyle = ` - - ` - @element('lit-chart-pie') export class LitChartPie extends BaseElement { private eleShape: Element | null | undefined; @@ -189,15 +98,10 @@ export class LitChartPie extends BaseElement { this.render(); } - measureInitialize():void{ - this.data = []; - this.radius = (Math.min(this.clientHeight, this.clientWidth) * 0.65) / 2 - 10; - this.labelsEL!.textContent = ''; - } - measure() { if (!this.litChartPieConfig) return; - this.measureInitialize(); + this.data = []; + this.radius = (Math.min(this.clientHeight, this.clientWidth) * 0.65) / 2 - 10; let pieCfg = this.litChartPieConfig!; let startAngle = 0; let startDegree = 0; @@ -207,6 +111,7 @@ export class LitChartPie extends BaseElement { (previousValue, currentValue) => currentValue[pieCfg.angleField] + previousValue, 0 ); + this.labelsEL!.textContent = ''; let labelArray: string[] = []; this.litChartPieConfig.data.forEach((pieItem, index) => { let item: Sector = { @@ -249,38 +154,6 @@ export class LitChartPie extends BaseElement { return this.litChartPieConfig; } - addCanvasOnmousemoveEvent():void{ - this.canvas!.onmousemove = (ev) => { - let rect = this.getBoundingClientRect(); - let x = ev.pageX - rect.left - this.centerX!; - let y = ev.pageY - rect.top - this.centerY!; - if (isPointIsCircle(0, 0, x, y, this.radius!)) { - let degree = this.computeDegree(x, y); - this.data.forEach((it) => { - it.hover = degree >= it.startDegree! && degree <= it.endDegree!; - this.updateHoverItemStatus(it); - it.obj.isHover = it.hover; - if (it.hover && this.litChartPieConfig) { - this.litChartPieConfig.hoverHandler?.(it.obj); - this.showTip( - ev.pageX - rect.left + 10, - ev.pageY - this.offsetTop - 10, - this.litChartPieConfig.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}` - ); - } - }); - } else { - this.hideTip(); - this.data.forEach((it) => { - it.hover = false; - it.obj.isHover = false; - this.updateHoverItemStatus(it); - }); - this.litChartPieConfig?.hoverHandler?.(undefined); - } - this.render(); - }; - } connectedCallback() { super.connectedCallback(); this.eleShape = this.shadowRoot!.querySelector('#shape'); @@ -315,7 +188,36 @@ export class LitChartPie extends BaseElement { }); } }; - this.addCanvasOnmousemoveEvent(); + this.canvas!.onmousemove = (ev) => { + let rect = this.getBoundingClientRect(); + let x = ev.pageX - rect.left - this.centerX!; + let y = ev.pageY - rect.top - this.centerY!; + if (isPointIsCircle(0, 0, x, y, this.radius!)) { + let degree = this.computeDegree(x, y); + this.data.forEach((it) => { + it.hover = degree >= it.startDegree! && degree <= it.endDegree!; + this.updateHoverItemStatus(it); + it.obj.isHover = it.hover; + if (it.hover && this.litChartPieConfig) { + this.litChartPieConfig.hoverHandler?.(it.obj); + this.showTip( + ev.pageX - rect.left + 10, + ev.pageY - this.offsetTop - 10, + this.litChartPieConfig.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}` + ); + } + }); + } else { + this.hideTip(); + this.data.forEach((it) => { + it.hover = false; + it.obj.isHover = false; + this.updateHoverItemStatus(it); + }); + this.litChartPieConfig?.hoverHandler?.(undefined); + } + this.render(); + }; this.render(); } @@ -353,40 +255,6 @@ export class LitChartPie extends BaseElement { }).observe(this); } - handleData():void{ - this.textRects = []; - if (this.litChartPieConfig!.showChartLine) { - this.data.forEach((dataItem) => { - let text = `${dataItem.value}`; - let metrics = this.ctx!.measureText(text); - let textWidth = metrics.width; - let textHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; - this.ctx!.beginPath(); - this.ctx!.strokeStyle = dataItem.color!; - this.ctx!.fillStyle = '#595959'; - let deg = dataItem.startDegree! + (dataItem.endDegree! - dataItem.startDegree!) / 2; - let dep = 25; - let x1 = 0 + this.radius! * Math.cos((deg * Math.PI) / 180); - let y1 = 0 + this.radius! * Math.sin((deg * Math.PI) / 180); - let x2 = 0 + (this.radius! + 13) * Math.cos((deg * Math.PI) / 180); - let y2 = 0 + (this.radius! + 13) * Math.sin((deg * Math.PI) / 180); - let x3 = 0 + (this.radius! + dep) * Math.cos((deg * Math.PI) / 180); - let y3 = 0 + (this.radius! + dep) * Math.sin((deg * Math.PI) / 180); - this.ctx!.moveTo(x1, y1); - this.ctx!.lineTo(x2, y2); - this.ctx!.stroke(); - let rect = this.correctRect({ - x: x3 - textWidth / 2, - y: y3 + textHeight / 2, - w: textWidth, - h: textHeight, - }); - this.ctx?.fillText(text, rect.x, rect.y); - this.ctx?.closePath(); - }); - } - } - render(ease: boolean = true) { if (!this.canvas || !this.litChartPieConfig) return; if (this.radius! <= 0) return; @@ -419,10 +287,7 @@ export class LitChartPie extends BaseElement { this.ctx!.stroke(); this.ctx?.closePath(); }); - this.setData(ease); - } - setData(ease: boolean):void{ this.data .filter((it) => it.hover) .forEach((it) => { @@ -436,7 +301,38 @@ export class LitChartPie extends BaseElement { this.ctx!.stroke(); this.ctx?.closePath(); }); - this.handleData(); + + this.textRects = []; + if (this.litChartPieConfig.showChartLine) { + this.data.forEach((dataItem) => { + let text = `${dataItem.value}`; + let metrics = this.ctx!.measureText(text); + let textWidth = metrics.width; + let textHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; + this.ctx!.beginPath(); + this.ctx!.strokeStyle = dataItem.color!; + this.ctx!.fillStyle = '#595959'; + let deg = dataItem.startDegree! + (dataItem.endDegree! - dataItem.startDegree!) / 2; + let dep = 25; + let x1 = 0 + this.radius! * Math.cos((deg * Math.PI) / 180); + let y1 = 0 + this.radius! * Math.sin((deg * Math.PI) / 180); + let x2 = 0 + (this.radius! + 13) * Math.cos((deg * Math.PI) / 180); + let y2 = 0 + (this.radius! + 13) * Math.sin((deg * Math.PI) / 180); + let x3 = 0 + (this.radius! + dep) * Math.cos((deg * Math.PI) / 180); + let y3 = 0 + (this.radius! + dep) * Math.sin((deg * Math.PI) / 180); + this.ctx!.moveTo(x1, y1); + this.ctx!.lineTo(x2, y2); + this.ctx!.stroke(); + let rect = this.correctRect({ + x: x3 - textWidth / 2, + y: y3 + textHeight / 2, + w: textWidth, + h: textHeight, + }); + this.ctx?.fillText(text, rect.x, rect.y); + this.ctx?.closePath(); + }); + } if (this.data.filter((it) => it.ease!.process).length > 0) { requestAnimationFrame(() => this.render(ease)); } @@ -487,34 +383,55 @@ export class LitChartPie extends BaseElement { crossH: number; } { let cross: boolean; - let direction: string = ''; + let direction: string; let crossW: number; let crossH: number; let maxX = r1.x + r1.w > rect.x + rect.w ? r1.x + r1.w : rect.x + rect.w; let maxY = r1.y + r1.h > rect.y + rect.h ? r1.y + r1.h : rect.y + rect.h; let minX = r1.x < rect.x ? r1.x : rect.x; let minY = r1.y < rect.y ? r1.y : rect.y; - cross = maxX - minX < rect.w + r1.w && maxY - minY < r1.h + rect.h; + if (maxX - minX < rect.w + r1.w && maxY - minY < r1.h + rect.h) { + cross = true; + } else { + cross = false; + } crossW = Math.abs(maxX - minX - (rect.w + r1.w)); crossH = Math.abs(maxY - minY - (rect.y + r1.y)); if (rect.x > r1.x) { + //right if (rect.y > r1.y) { + //bottom direction = 'Right-Bottom'; } else if (rect.y == r1.y) { + //middle direction = 'Right'; } else { + //top direction = 'Right-Top'; } } else if (rect.x < r1.x) { + //left if (rect.y > r1.y) { + //bottom direction = 'Left-Bottom'; } else if (rect.y == r1.y) { + //middle direction = 'Left'; } else { + //top direction = 'Left-Top'; } } else { - direction = this.rectSuperposition(rect,r1); + if (rect.y > r1.y) { + //bottom + direction = 'Bottom'; + } else if (rect.y == r1.y) { + //middle + direction = 'Right'; //superposition default right + } else { + //top + direction = 'Top'; + } } return { cross, @@ -524,16 +441,6 @@ export class LitChartPie extends BaseElement { }; } - rectSuperposition(rect: Rectangle,r1: Rectangle):string{ - if (rect.y > r1.y) { - return 'Bottom'; - } else if (rect.y == r1.y) { - return 'Right'; //superposition default right - } else { - return 'Top'; - } - } - showTip(x: number, y: number, msg: string) { this.pieTipEL!.style.display = 'flex'; this.pieTipEL!.style.top = `${y}px`; @@ -547,7 +454,94 @@ export class LitChartPie extends BaseElement { initHtml(): string { return ` - ${initHtmlStyle} +
diff --git a/ide/src/base-ui/chart/scatter/LitChartScatter.ts b/ide/src/base-ui/chart/scatter/LitChartScatter.ts new file mode 100644 index 0000000000000000000000000000000000000000..c50a70605ef7f6d8b943bfaaa02c43a7ddae9835 --- /dev/null +++ b/ide/src/base-ui/chart/scatter/LitChartScatter.ts @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { resizeCanvas } from '../helper'; +import { BaseElement, element } from '../../BaseElement'; +import { LitChartScatterConfig } from './LitChartScatterConfig'; + +@element('lit-chart-scatter') +export class LitChartScatter extends BaseElement { + private scatterTipEL: HTMLDivElement | null | undefined; + private labelsEL: HTMLDivElement | null | undefined; + canvas: HTMLCanvasElement | undefined | null; + canvas2: HTMLCanvasElement | undefined | null; + ctx: CanvasRenderingContext2D | undefined | null; + originX: number = 0; + finalX: number = 0; + originY: number = 0; + finalY: number = 0; + options: LitChartScatterConfig | undefined; + + set config(LitChartScatterConfig: LitChartScatterConfig) { + this.options = LitChartScatterConfig; + } + + connectedCallback(): void { + super.connectedCallback(); + this.canvas = this.shadowRoot!.querySelector('#canvas'); + this.scatterTipEL = this.shadowRoot!.querySelector('#tip'); + this.ctx = this.canvas!.getContext('2d', { alpha: true }); + this.labelsEL = this.shadowRoot!.querySelector('#shape'); + resizeCanvas(this.canvas!); + this.originX = this.clientWidth * 0.1; + this.originY = this.clientHeight * 0.9; + this.finalX = this.clientWidth; + this.finalY = this.clientHeight * 0.1; + /*hover效果*/ + this.canvas!.onmousemove = (event) => { + let pos: Object = { + x: event.offsetX, + y: event.offsetY, + }; + let hoverPoint: Object | boolean = this.checkHover(this.options, pos); + /** + * 如果当前有聚焦点 + */ + if (hoverPoint) { + this.showTip(hoverPoint); + let samePoint: boolean = + this.options!.hoverData === hoverPoint ? true : false; + if (!samePoint) { + this.resetHoverWithOffScreen(); + this.options!.hoverData = hoverPoint; + } + this.paintHover(); + } else { + //使用离屏canvas恢复 + this.resetHoverWithOffScreen(); + this.hideTip(); + } + }; + } + + initElements(): void { + new ResizeObserver((entries, observer) => { + entries.forEach((it) => { + resizeCanvas(this.canvas!); + this.originX = this.clientWidth * 0.1; + this.originY = this.clientHeight * 0.95; + this.finalX = this.clientWidth * 0.9; + this.finalY = this.clientHeight * 0.1; + this.labelsEL!.innerText = ''; + }); + }).observe(this); + } +} diff --git a/ide/src/base-ui/chart/scatter/LitChartScatterConfig.ts b/ide/src/base-ui/chart/scatter/LitChartScatterConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..eb3b9daa588d795902778a5babfd86485367b25f --- /dev/null +++ b/ide/src/base-ui/chart/scatter/LitChartScatterConfig.ts @@ -0,0 +1,45 @@ + +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface LitChartScatterConfig { + // y轴坐标数组 + yAxisLabel: Array; + // x轴坐标数组 + xAxisLabel: Array; + // 坐标轴名称 + axisLabel: Array; + // 用于判断是否绘制负载线及均衡线 + drawload: boolean; + // 用于存放最大负载线及均衡线的参数值 + load: Array; + // 打点数据 + data: Array>>; + // 用于存放绘图数据 + paintingData: Array; + // 用于存放移入点数据 + hoverData: Object | null; + // 渐变色信息 + globalGradient: CanvasGradient | undefined; + // 颜色池 + colorPool: () => Array; + // 移入事件 + hoverEvent: void; + // 图表名称 + title: string; + // 颜色数据名称 + colorPoolText: () => Array; + // 提示信息 + tip: (a: any) => string; +} diff --git a/ide/src/base-ui/checkbox/LitCheckBox.ts b/ide/src/base-ui/checkbox/LitCheckBox.ts index 9a52bf4638513254ea7948a6ab0c30104b1e00c8..3a808a64a851dd1375ed27e9a1ba6a5c7fa1c47a 100644 --- a/ide/src/base-ui/checkbox/LitCheckBox.ts +++ b/ide/src/base-ui/checkbox/LitCheckBox.ts @@ -15,9 +15,62 @@ import { BaseElement, element } from '../BaseElement'; -const initHtmlStyle = ` - - `; - -@element('lit-check-box') -export class LitCheckBox extends BaseElement { - private checkbox: HTMLInputElement | undefined; - - static get observedAttributes() { - return ['checked', 'value', 'disabled']; - } - - set disabled(value) { - if (value === null || value === false) { - this.removeAttribute('disabled'); - } else { - this.setAttribute('disabled', ''); - } - } - - get indeterminate() { - return this.checkbox!.indeterminate; - } - - set indeterminate(value) { - if (value === null || value === false) { - this.checkbox!.indeterminate = false; - } else { - this.checkbox!.indeterminate = true; - } - } - - get disabled() { - return this.getAttribute('disabled') !== null; - } - - get checked() { - return this.getAttribute('checked') !== null; - } - - set checked(boxCheck: boolean) { - if (boxCheck === null || !boxCheck) { - this.removeAttribute('checked'); - } else { - this.setAttribute('checked', ''); - } - } - - get value() { - return this.getAttribute('value') || ''; - } - - set value(value: string) { - this.setAttribute('value', value); - } - - initHtml(): string { - return ` - ${initHtmlStyle}