当前位置:网站首页>Cyclic multiple scatter
Cyclic multiple scatter
2022-07-24 08:34:00 【lvxinaidou】
markline & max min yAsix
import {
Component, OnInit } from '@angular/core';
import {
WelcomeService } from './services/welcome.service';
import * as _ from 'lodash';
import {
NzFormatEmitEvent } from 'ng-zorro-antd/tree';
import * as echarts from 'echarts';
import {
HttpClient } from '@angular/common/http';
import {
cloneDeep } from 'lodash';
import {
saveAs } from 'file-saver';
interface TreeNodes {
title: string;
key: string;
expanded?: boolean;
children?: Array<TreeNodes>;
isLeaf?:boolean;
}
export interface TableColumn {
level1: string;
level2: string;
level3: string;
level4: string;
level5: string;
level6: string;
level7: string;
level8: string;
rowspan0?:number;
rowspan1?:number;
rowspan2?:number;
rowspan3?:number;
rowspan4?:number;
isWarning?: any;
}
@Component({
selector: 'app-welcome',
templateUrl: './welcome.component.html',
styleUrls: ['./welcome.component.less']
})
export class WelcomeComponent implements OnInit{
public myTreeChart: any;
public treeCharts: any[] = [];
public chartNames: Array<string> = [];
public nodeValueByTime:Array<any>= [];
public optionsData:any = {
};
public nodes:Array<TreeNodes> = [];
defaultExpandedKeys:Array<string> = [];
defaultCheckedKeys: Array<string> = [];
public startTime:any = new Date(new Date().getTime() - 60*60*24*6*1000);
public endTime:any = new Date(new Date().getTime() - 60*60*24*1000);
date = [this.startTime, this.endTime];
public keyIndex:number = 0;
public tempEquipmentSelectionList: Array<any> = [' Machine 1', ' Machine 2']
public colors: Array<string> = ['#d223e7', '#4962FC', '#4962FC', '#18D070', '#3F77FE', '#01C2F9', '#4962FC', '#4B7CF3' , '#dd3ee5', '#12e78c', '#fe8104', '#01C2F9', '#F4CB29', '#FD9E06']
constructor(
private welcomeService: WelcomeService,
private http: HttpClient
) {
}
ngOnInit() {
// Get the tree list
this.getTreeLists();
// this.getTableData();
}
tableViewData:any = [];
getTableData() {
this.http.get('../assets/jsons/test.json').subscribe((data:any) => {
this.transferTableData(data.table, data.merge);
});
}
transferTableData(table:any, merge:any) {
let tableArray:Array<TableColumn> = [];
table.forEach((item: any) => {
const keysArr = Object.keys(item);
tableArray.push({
level1: item[keysArr[0]],
level2: item[keysArr[1]],
level3: item[keysArr[2]],
level4: item[keysArr[3]],
level5: item[keysArr[4]],
level6: item[keysArr[5]],
level7: item[keysArr[6]],
level8: item[keysArr[7]],
isWarning: true
});
});
merge.forEach((item:any) => {
const rowspanData = item.endRow - item.startRow + 1;
if (item.startCol === 4 && item.endCol === 4) {
tableArray[item.startRow].rowspan4 = rowspanData;
} else if(item.startCol === 3 && item.endCol === 3) {
tableArray[item.startRow].rowspan3 = rowspanData;
} else if(item.startCol === 2 && item.endCol === 2) {
tableArray[item.startRow].rowspan2 = rowspanData;
} else if(item.startCol === 1 && item.endCol === 1) {
tableArray[item.startRow].rowspan1 = rowspanData;
} else if(item.startCol === 0 && item.endCol === 0) {
tableArray[item.startRow].rowspan0 = rowspanData;
this.tableViewData.push(cloneDeep(tableArray).splice(item.startRow, rowspanData));
}
});
console.log( this.tableViewData);
}
public showMarkLineStatus: boolean = false;
showMarkLine() : void {
this.showMarkLineStatus = !this.showMarkLineStatus;
console.log(this.showMarkLineStatus);
this.getEchartOptions();
setTimeout(() => {
this.initCharts(this.nodeValueByTime);
},0);
}
initValue(): void {
this.defaultExpandedKeys = [];
this.defaultCheckedKeys = [];
this.chartNames = [];
this.treeCharts = [];
}
getTreeLists() {
this.welcomeService.getTreesList().subscribe((res:any) => {
this.nodes = res;
this.defaultExpandedKeys = []; // init value
this.defaultCheckedKeys = []; // init value
this.addTreeKey(this.nodes);
this.getDefaultKkeys(this.nodes[0]);
this.defaultCheckedKeys = [this.nodes[0].key];
// Get the data of nodes in different time periods
this.getNodeValueByTime();
});
}
addTreeKey(nodes:any) {
nodes.forEach(((item:any) => {
item.key = this.keyIndex++;
if (item?.children) {
item?.children.forEach((e:any) => {
e.key = this.keyIndex++;
this.addTreeKey((e?.children || []));
})
}
}))
}
getDefaultKkeys(currentNode:any) {
if(currentNode) {
currentNode.checked = true;
}
if (currentNode?.children) {
this.defaultExpandedKeys.push(currentNode.key);
currentNode?.children.forEach((item:any) => {
item.checked = true;
this.getDefaultKkeys(item);
})
}
}
getNodeValueByTime() {
// console.log(this.nodes);
const [startTime, endTime]=[this.startTime.getTime(), this.endTime.getTime()]
// this.initValue();
this.welcomeService.getNodeValueByTime(this.nodes, startTime, endTime, this.tempEquipmentSelectionList).subscribe((res:any) => {
this.nodeValueByTime = res;
console.log(this.nodeValueByTime)
this.getEchartOptions();
setTimeout(() => {
this.initCharts(this.nodeValueByTime);
// console.log(this.nodeValueByTime);
},0)
});
}
initCharts(data:any) {
this.treeCharts = []; // init value
data.forEach((item:any, index:number) => {
const className = `.diagram${
index}`;
// console.log(className);
this.treeCharts.push({
index: index,chartNames: this.chartNames[index], chart: echarts.init(document.querySelector(className) as any)})
});
this.nodeValueByTime.forEach((item:any,index: number) => {
console.log(this.treeCharts[index]);
this.setEchartOptions(this.treeCharts[index].chart, index);
});
}
getEchartOptions() {
let options:any = {
seriesData: [],
legendData:[],
xAxisData: [],
keyTexts: [],
sDatasss:[],
maxValues:[],
minValues: []
}
this.chartNames = []; // init value
this.nodeValueByTime.forEach((item:any, index:number) => {
let sDatas:any = [];
let xDatas:any = [];
let lDatas:any = [];
let sDatass: any = [];
let maxData:any = [];
let minData:any = [];
this.chartNames.push(item.nodeName);
options.keyTexts.push(item.nodeName);
if(item.max) {
maxData.push(item.max);
}
if(item.min){
minData.push(item.min)
}
item.nodeValues.forEach((node:any, index: number) => {
lDatas.push(node.equipment);
let sDatasTemp:any = [];
node.value.forEach((v:any) => {
xDatas.push(this.transferStingDate(v.date)),
v.points.forEach((p:any) => {
sDatasTemp.push([this.transferStingDate(p.time), p.value]);
sDatass.push(p.value);
if (p.value) {
maxData.push(p.value);
minData.push(p.value);
}
const sDatasObj = {
name:node.equipment,
itemStyle: {
color: this.colors[index],
borderColor: '#f00',
borderWidth:5
},
type: 'scatter',
symbolSize: 20,
data: [[this.transferStingDate(p.time), p.value]],
}
const marklineOjb = {
symbol: 'none',
lineStyle:{
type:'solid',color:'red'},
data:[
{
name:'top',yAxis:2},
{
name:'bottom',yAxis: -10}
]
}
if (this.showMarkLineStatus) {
sDatas.push(Object.assign(cloneDeep(sDatasObj), {
markLine:marklineOjb
}))
} else {
sDatas.push(sDatasObj);
}
// sDatas.push({
// name:node.equipment,
// itemStyle: {
// color: this.colors[index],
// borderColor: '#f00',
// borderWidth:5
// },
// type: 'scatter',
// symbolSize: 20,
// data: [[this.transferStingDate(p.time), p.value]],
// markLine: {
// symbol: 'none',
// lineStyle:{type:'solid',color:'red'},
// data:[
// {name:'top',yAxis:-10},
// {name:'bottom',yAxis: 2}
// ]
// }
// })
});
})
// sDatas.push({name:node.equipment, type: 'scatter', symbolSize: 20, data: sDatasTemp})
});
options.seriesData.push(sDatas);
options.xAxisData.push([...new Set(xDatas)]);
options.legendData.push(lDatas);
options.sDatasss.push(sDatass);
options.maxValues.push(maxData);
options.minValues.push(minData);
});
if (this.showMarkLineStatus) {
options.seriesData.forEach((sItem:any, index: number) => {
let maxV:any = Math.max.apply(null,options.maxValues[index].map(Number));
let minV:any = Math.min.apply(null,options.minValues[index].map(Number));
sItem.forEach((currentSeries:any) => {
console.log(currentSeries);
currentSeries.markLine.data[0].yAxis = this.nodeValueByTime[index].max?this.nodeValueByTime[index].max:'none';
currentSeries.markLine.data[1].yAxis = this.nodeValueByTime[index].min?this.nodeValueByTime[index].min:'none';;
})
this.yAxisMax.push(maxV);
this.yAxisMin.push(minV);
})
// console.log(options.seriesData);
// console.log(this.yAxisMax);
// console.log(this.yAxisMin);
}
this.optionsData = options;
// console.log(this.optionsData);
// console.log(this.optionsData.sDatasss);
// console.log(this.optionsData.maxValues);
// console.log(this.optionsData.minValues);
}
public yAxisMax: Array<number> = [];
public yAxisMin: Array<number> = [];
setEchartOptions(myTreeChart:any, index:number){
let yMax:number | null, yMin:number | null;
if(this.yAxisMax[index] && this.yAxisMin[index] && this.showMarkLineStatus) {
yMax = this.yAxisMax[index] + (this.yAxisMax[index]-this.yAxisMin[index])/2;
yMin = this.yAxisMin[index] - (this.yAxisMax[index]-this.yAxisMin[index])/2;
// yMax = this.yAxisMax[index];
// yMin = this.yAxisMin[index];
} else {
yMax = null;
yMin = null;
}
if(typeof yMax === 'number') {
yMax = parseInt(yMax.toString(), 10)
}
if(typeof yMin === 'number') {
yMin = parseInt(yMin.toString(), 10)
}
myTreeChart.showLoading();
let setOptionData = {
key: {
text: this.optionsData.keyTexts[index]
},
tooltip: {
trigger: 'axis'
},
legend: {
data: this.optionsData.legendData[index],
itemStyle: {
borderColor: 'none'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
name: ' date ',
nameLocation: 'end',
axisTick: {
alignWithLabel: true },
axisLine: {
symbol: ['none', 'arrow'], symbolOffset: 10, symbolSize: [6, 15], onZero: true },
data: this.optionsData.xAxisData[index]
},
yAxis: {
type: 'value',
grid: {
top: '200' },
axisLine: {
symbol: ['none', 'arrow'], show: true, symbolOffset: 10, symbolSize: [6, 15], onZero: true },
max: yMax,
min: yMin
},
series: this.optionsData.seriesData[index],
graphic: {
type: 'text', // type : Text
left: 'center',
top: 'middle',
silent: true, // Not responding to events
invisible: this.optionsData.sDatasss[index].every((item:any)=>{
return item!==""}), // Data is hidden
style: {
fill: '#9d9d9d',
fontWeight: 'bold',
text: ' Temporarily no data ',
fontFamily: 'Microsoft YaHei',
fontSize: '25px'
}
}
}
console.log(setOptionData);
myTreeChart.clear();
myTreeChart.setOption(setOptionData);
myTreeChart.hideLoading();
}
downloadImage() {
const canvasLists = document.querySelectorAll('canvas');
console.log(canvasLists);
if (canvasLists && canvasLists.length) {
const mainCanvas = document.createElement('canvas');
const mcContext = mainCanvas.getContext('2d');
if (mcContext) {
mainCanvas.width = 1500;
mainCanvas.height = 500 * canvasLists.length;
mcContext.fillStyle = 'white';
mcContext.fillRect(0, 0 , mainCanvas.width, mainCanvas.height);
(canvasLists || []).forEach((item:any, index: number) => {
let row = index;
let column = 0;
mcContext.drawImage(item, column * 600 + 50, row * 400 + 100);
})
let url = mainCanvas.toDataURL('image/png');
let a = document.createElement('a');
a.download = 'test Screenshot of chart ';
a.href = url;
a.click();
}
}
}
nzEvent(event: NzFormatEmitEvent): void {
// console.log(this.nodes);
this.getNodeValueByTime();
}
onChange(result: Date[]): void {
[this.startTime, this.endTime]=[...this.date];
this.getNodeValueByTime();
}
transferStingDate(timestamp:any) {
let date = new Date(timestamp);
return `${
date.getFullYear()}-${
(date.getMonth() + 1 )}-${
date.getDate()}`
}
}
tree.json
[
{
"title": "Ws Base version ",
"children": [
{
"title": "EMBMWA-C1",
"children": [
{
"title": "RA1",
"children": [
{
"title": "Rot", "isLeaf": true },
{
"title": "Mag", "isLeaf": true }
]
},
{
"title": "RA2",
"children": [
{
"title": "Trans X", "isLeaf": true },
{
"title": "Rot", "isLeaf": true },
{
"title": "Mag", "isLeaf": true }
]
},
{
"title": "IS",
"children": [
{
"title": "Trans X", "isLeaf": true },
{
"title": "Rot", "isLeaf": true },
{
"title": "Mag", "isLeaf": true }
]
}
]
}
]
},
{
"title": " Environmental stability check ",
"children": [
{
"title": " from ctlog Extract the following test items ",
"children": [
{
"title": "Plans_ref", "isLeaf": true },
{
"title": "Thens", "isLeaf": true }
]
}
]
}
]
The query value json
[
{
"nodeName": "Rot",
"nodeValues": [
{
"equipment": "mot-008",
"value": [
{
"date": 1640966400000,
"points": [
{
"time": 1640988007000,
"value": "0.98"
},
{
"time": 1640995209000,
"value": "0.38"
}
]
},
{
"date": 1641052800000,
"points": [
{
"time": 1641070809000,
"value": "1.98"
},
{
"time": 1641078008000,
"value": "2.38"
},
{
"time": 1641085207000,
"value": "3.48"
}
]
},
{
"date": 1641139200000,
"points": [
{
"time": 1641175200000,
"value": "2.98"
},
{
"time": 1641168000000,
"value": "4.38"
}
]
},
{
"date": 1641254400000,
"points": [
{
"time": 1641254400000,
"value": "4.98"
},
{
"time": 1641261600000,
"value": "5.38"
}
]
},
{
"date": 1641348000000,
"points": [
{
"time": 1641348000000,
"value": "6.98"
},
{
"time": 1641344400000,
"value": "7.38"
}
]
}
]
},
{
"equipment": "mot-009",
"value": [
{
"date": 1640966400000,
"points": [
{
"time": 1640988007000,
"value": "0.98"
},
{
"time":1640995209000,
"value": "0.38"
},
{
"time": 1641002402000,
"value": "0.48"
},
{
"time": 1641009604000,
"value": "0.58"
}
]
},
{
"date": 1641052800000,
"points": [
{
"time": 1641070809000,
"value": "0.98"
},
{
"time": 1641078008000,
"value": "0.38"
},
{
"time": 1641085207000,
"value": "0.48"
}
]
}
]
}
]
},
{
"nodeName": "Mot",
"nodeValues": [
{
"equipment": "mot-008",
"value": [
{
"date": 1640966400000,
"points": [
{
"time": 1640988007000,
"value": "0.98"
},
{
"time": 1640995209000,
"value": "0.38"
}
]
},
{
"date": 1641052800000,
"points": [
{
"time": 1641070809000,
"value": "1.98"
},
{
"time": 1641078008000,
"value": "2.38"
},
{
"time": 1641085207000,
"value": "3.48"
}
]
},
{
"date": 1641139200000,
"points": [
{
"time": 1641175200000,
"value": "2.98"
},
{
"time": 1641168000000,
"value": "4.38"
}
]
},
{
"date": 1641254400000,
"points": [
{
"time": 1641254400000,
"value": "4.98"
},
{
"time": 1641261600000,
"value": "5.38"
}
]
},
{
"date": 1641348000000,
"points": [
{
"time": 1641348000000,
"value": "6.98"
},
{
"time": 1641344400000,
"value": "7.38"
}
]
}
]
},
{
"equipment": "mot-009",
"value": [
{
"date": 1640966400000,
"points": [
{
"time": 1640988007000,
"value": "0.98"
},
{
"time":1640995209000,
"value": "0.38"
},
{
"time": 1641002402000,
"value": "0.48"
},
{
"time": 1641009604000,
"value": "0.58"
}
]
},
{
"date": 1641052800000,
"points": [
{
"time": 1641070809000,
"value": "0.98"
},
{
"time": 1641078008000,
"value": "0.38"
},
{
"time": 1641085207000,
"value": "0.48"
}
]
}
]
}
]
}
]
html
<section class="welcome-page">
<div>
<nz-range-picker [(ngModel)]="date" (ngModelChange)="onChange($event)"></nz-range-picker>
</div>
<span class="tree">
<nz-tree
[nzData]="nodes"
nzCheckable
nzMultiple
(nzCheckBoxChange)="nzEvent($event)"
[nzExpandedKeys]="defaultExpandedKeys"
[nzCheckedKeys]="defaultCheckedKeys"
></nz-tree>
</span>
<span *ngFor="let echartItem of chartNames; let i = index;" class="{
{'diagram'+ ' ' + 'diagram' + i}}"></span>
<div>
</div>
</section>
ts
import {
Component, OnInit } from '@angular/core';
import {
WelcomeService } from './services/welcome.service';
import * as _ from 'lodash';
import {
NzFormatEmitEvent } from 'ng-zorro-antd/tree';
import * as echarts from 'echarts';
import {
HttpClient } from '@angular/common/http';
interface TreeNodes {
title: string;
key: string;
expanded?: boolean;
children?: Array<TreeNodes>;
isLeaf?:boolean;
}
@Component({
selector: 'app-welcome',
templateUrl: './welcome.component.html',
styleUrls: ['./welcome.component.less']
})
export class WelcomeComponent implements OnInit{
public myTreeChart: any;
public treeCharts: any[] = [];
public chartNames: Array<string> = [];
public nodeValueByTime = [];
public optionsData:any = {
};
public nodes:Array<TreeNodes> = [];
defaultExpandedKeys:Array<string> = [];
defaultCheckedKeys: Array<string> = [];
public startTime:any = new Date(new Date().getTime() - 60*60*24*6*1000);
public endTime:any = new Date(new Date().getTime() - 60*60*24*1000);
date = [this.startTime, this.endTime];
public keyIndex:number = 0;
public tempEquipmentSelectionList: Array<any> = [' Machine 1', ' Machine 2']
constructor(
private welcomeService: WelcomeService,
private http: HttpClient
) {
}
ngOnInit() {
// Get the tree list
this.getTreeLists();
}
initValue() {
this.defaultExpandedKeys = [];
this.defaultCheckedKeys = [];
this.chartNames = [];
this.treeCharts = [];
}
getTreeLists() {
this.welcomeService.getTreesList().subscribe((res:any) => {
this.nodes = res;
this.defaultExpandedKeys = []; // init value
this.defaultCheckedKeys = []; // init value
this.addTreeKey(this.nodes);
this.getDefaultKkeys(this.nodes[0]);
this.defaultCheckedKeys = [this.nodes[0].key];
// Get the data of nodes in different time periods
this.getNodeValueByTime();
});
}
addTreeKey(nodes:any) {
nodes.forEach(((item:any) => {
item.key = this.keyIndex++;
if (item?.children) {
item?.children.forEach((e:any) => {
e.key = this.keyIndex++;
this.addTreeKey((e?.children || []));
})
}
}))
}
getDefaultKkeys(currentNode:any) {
if (currentNode?.children) {
this.defaultExpandedKeys.push(currentNode.key);
currentNode?.children.forEach((item:any) => {
this.getDefaultKkeys(item);
})
}
}
getNodeValueByTime() {
console.log(this.nodes);
const [startTime, endTime]=[this.startTime.getTime(), this.endTime.getTime()]
// this.initValue();
this.welcomeService.getNodeValueByTime(this.nodes, startTime, endTime, this.tempEquipmentSelectionList).subscribe((res:any) => {
this.nodeValueByTime = res;
console.log(this.nodeValueByTime)
this.getEchartOptions();
setTimeout(() => {
this.initCharts(this.nodeValueByTime);
console.log(this.nodeValueByTime);
},0)
});
}
initCharts(data:any) {
this.treeCharts = []; // init value
data.forEach((item:any, index:number) => {
const className = `.diagram${
index}`;
console.log(className);
this.treeCharts.push({
index: index,chartNames: this.chartNames[index], chart: echarts.init(document.querySelector(className) as any)})
});
this.nodeValueByTime.forEach((item:any,index: number) => {
this.setEchartOptions(this.treeCharts[index].chart, index);
});
}
getEchartOptions() {
let options:any = {
seriesData: [],
legendData:[],
xAxisData: [],
keyTexts: [],
}
this.chartNames = []; // init value
this.nodeValueByTime.forEach((item:any, index:number) => {
let sDatas:any = [];
let xDatas:any = [];
let lDatas:any = [];
this.chartNames.push(item.nodeName);
options.keyTexts.push(item.nodeName);
item.nodeValues.forEach((node:any) => {
lDatas.push(node.equipment);
let sDatasTemp:any = [];
node.value.forEach((v:any) => {
xDatas.push(this.transferStingDate(v.date)),
v.points.forEach((p:any) => {
sDatasTemp.push([this.transferStingDate(p.time), p.value]);
});
})
sDatas.push({
name:node.equipment, type: 'scatter', symbolSize: 20, data: sDatasTemp})
});
options.seriesData.push(sDatas);
options.xAxisData.push([...new Set(xDatas)]);
options.legendData.push(lDatas);
});
this.optionsData = options;
console.log(this.optionsData);
}
setEchartOptions(myTreeChart:any, index:number){
myTreeChart.showLoading();
let setOptionData = {
key: {
text: this.optionsData.keyTexts[index]
},
tooltip: {
trigger: 'axis'
},
legend: {
data: this.optionsData.legendData[index]
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
name: ' date ',
nameLocation: 'end',
axisTick: {
alignWithLabel: true },
axisLine: {
symbol: ['none', 'arrow'], symbolOffset: 10, symbolSize: [6, 15], onZero: true },
data: this.optionsData.xAxisData[index]
},
yAxis: {
type: 'value',
grid: {
top: '200' },
axisLine: {
symbol: ['none', 'arrow'], show: true, symbolOffset: 10, symbolSize: [6, 15], onZero: true },
},
series: this.optionsData.seriesData[index]
}
console.log(setOptionData);
myTreeChart.setOption(setOptionData);
myTreeChart.hideLoading();
}
nzEvent(event: NzFormatEmitEvent): void {
console.log(this.nodes);
this.getNodeValueByTime();
}
onChange(result: Date[]): void {
[this.startTime, this.endTime]=[...this.date];
this.getNodeValueByTime();
}
transferStingDate(timestamp:any) {
let date = new Date(timestamp);
return `${
date.getFullYear()}-${
(date.getMonth() + 1 )}-${
date.getDate()}`
}
}
servcies
getNodeValueByTime(nodes:Array<any>, startTime:any, endTime:any, tempEquipmentSelectionList: Array<any>) {
const params = {
startTime: startTime,
endTime: endTime,
nodes: nodes,
tempEquipmentSelectionList:tempEquipmentSelectionList
}
console.log(params);
// let url = `${environment.ASSETS_URL}/${WelcomeConstant.NODE_VALUE_BY_TIME}`
let url = `${
environment.ASSETS_URL}/${
WelcomeConstant.NODE_VLAUE_BY_TIMETAP}`
return this.http.get(url)
// return this.http.post(url, params)
.pipe(
catchError((error => {
return throwError({
errorMessage: 'test error http'})}))
)
}
getTreesList() {
let url = `${
environment.ASSETS_URL}/${
WelcomeConstant.TREE_LIST}`
return this.http.get(url)
.pipe(
catchError((error => {
return throwError({
errorMessage: 'test error http'})}))
)
}
Running effect :
Bulk download echarts chart
downloadImage() {
const canvasLists = document.querySelectorAll('canvas');
console.log(canvasLists);
if (canvasLists && canvasLists.length) {
const mainCanvas = document.createElement('canvas');
const mcContext = mainCanvas.getContext('2d');
if (mcContext) {
mainCanvas.width = 1500;
mainCanvas.height = 500 * canvasLists.length;
mcContext.fillStyle = 'white';
mcContext.fillRect(0, 0 , mainCanvas.width, mainCanvas.height);
(canvasLists || []).forEach((item:any, index: number) => {
let row = index;
let column = 0;
mcContext.drawImage(item, column * 600 + 50, row * 400 + 100);
})
let url = mainCanvas.toDataURL('image/png');
let a = document.createElement('a');
a.download = 'test Screenshot of chart ';
a.href = url;
a.click();
}
}
}
边栏推荐
- [wechat applet development] (IV) uni app from getting started to giving up
- [wechat applet development] (III) homepage banner component uses swiper
- JS string interception
- Digital collections "chaos", 100 billion market changes are coming?
- Is it safe to open an account online in Beijing
- What is the difference between domestic "rocket heart" artificial heart and different artificial heart?
- Confusing defer, return, named return value, anonymous return value in golang
- Kotlin学习笔记1——变量、函数
- Wechat payment V3 version of openresty implementation and pit avoidance Guide (service side)
- [Google play access] payment server token acquisition
猜你喜欢

Web3≠NFT? A digital Renaissance?

Enterprises love hybrid app development, and applet container technology can improve efficiency by 100%

M-dao creates a one-stop Dao platform, allowing hundreds of millions of players to join Dao space

Typora提示【This beta version of Typora is expired, please download and install a newer version】的解决方案

Encryption market ushers in a new historical cycle. Look at jpex's "stability" and "health"
![[wechat applet development] (II) wechat native bottom tabbar configuration](/img/74/5f5da7ea47f95a25011ba52959f480.png)
[wechat applet development] (II) wechat native bottom tabbar configuration

FPGA integrated project - image edge detection system

Mysql database advanced

Wechat applet host environment, applet architecture, concise operation structure

Learn the rxjs operator
随机推荐
MySQL counts the total sales data of each month
Wechat applet file types and functions
Wechat applet subscription message development process
M-dao creates a one-stop Dao platform, allowing hundreds of millions of players to join Dao space
table-rowspan
Shanghai issued a document to support the entry of NFT cultural exchange: the trend of digital collections has arrived!
Classic problems of binary tree
MySQL date formatting
Digital collections "chaos", 100 billion market changes are coming?
JS string interception
Play to earn: a new and more promising game paradigm in the future
Hack the box - File Inclusion module detailed Chinese tutorial
5、 Use of environment variables in midway
From starfish OS' continued deflationary consumption of SFO, the value of SFO in the long run
In the next bull market, can platofarm, the leading project in the Web3 world, set foot on the top of the mountain
Is gamefi in decline or in the future?
Several development frameworks based on openresty
Optimization of MySQL paging query
【MySQL】08:聚合函数
The code is tired. Stop and enjoy the top color matching~