From 975e919d2236ce00c3e5445abb0f4919bacd90eb Mon Sep 17 00:00:00 2001 From: Diego Rey <diego.despaux@izundo.com> Date: Wed, 15 Aug 2018 20:08:49 -0300 Subject: [PATCH] Added export and center graph functionalities for graph2D Component --- Frontend Angular 4/package-lock.json | 2 +- .../plotter/graph2D/graph2D.component.html | 7 +- .../plotter/graph2D/graph2D.component.ts | 124 +++++++++++++++--- .../layout/plotter/graph2D/graph2D.helper.ts | 44 +++---- 4 files changed, 132 insertions(+), 45 deletions(-) diff --git a/Frontend Angular 4/package-lock.json b/Frontend Angular 4/package-lock.json index 19ab35b2..bc975140 100644 --- a/Frontend Angular 4/package-lock.json +++ b/Frontend Angular 4/package-lock.json @@ -4139,7 +4139,7 @@ "dev": true }, "function-plot": { - "version": "git://github.com/diego-rey/function-plot.git#d8b7147168ab7a595f8323d28ffc944735117606", + "version": "git://github.com/diego-rey/function-plot.git#1543ff3b723285e0119c53a9bd3d37ab7e671ca9", "from": "git://github.com/diego-rey/function-plot.git#feature/integration-domain-shape", "requires": { "array-range": "^1.0.1", diff --git a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.html b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.html index 4cc1455a..b99d1328 100755 --- a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.html +++ b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.html @@ -2,7 +2,12 @@ <div class="card-block contenedor-canvas" > <button ngbPopover="Zoom +" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" style="float:right; margin-right: 165px; margin-top: -55px" (click)=zoomIn() ><i class="fa fa-plus"></i></button> <button ngbPopover="Zoom -" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" style="float:right; margin-right: 132px; margin-top: -55px" (click)=zoomOut() ><i class="fa fa-minus"></i></button> - + <button ngbPopover="Centrar" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" style=" float:right; margin-right: 99px; margin-top: -55px" (click)="recenterPlot()" ><i class="fa fa-arrows"></i></button> + <button ngbPopover="Borrar" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" style=" float:right; margin-right: 66px; margin-top: -55px" (click)="cleanPlot()" ><i class="fa fa-trash"></i></button> + + <button ngbPopover="Descargar PNG" triggers="mouseenter:mouseleave" data-placement="bottom" class="btn btn-sm btn-secondary" style="float:right; margin-right: 33px; margin-top: -55px" (click)=exportPlot() ><i class="fa fa-download"></i></button> + <a id="download-plot" class="download-plot" href="#" download="Plot.svg" style="display: none">Download Canvas</a> + <button class="btn btn-sm btn-secondary" data-placement="bottom" *ngIf="!animation.playing && animation.data.length>0" style=" float:left; margin-top: -5px; margin-right: 5px" (click)="runAnimation()" ><i class="fa fa-play"></i></button> <button class="btn btn-sm btn-secondary" data-placement="bottom" *ngIf="animation.playing && animation.data.length>0" style=" float:left; margin-top: -5px; margin-right: 5px" (click)="pauseAnimation()" ><i class="fa fa-pause"></i></button> diff --git a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.ts b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.ts index 41f79f8c..4a48313e 100755 --- a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.ts +++ b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { GHCIService } from '../../../shared/services/ghci.service'; import functionPlot from 'function-plot'; -import { Animation } from './graph2D.helper'; +import { Animation, toJSON, triggerDownload } from './graph2D.helper'; @Component({ moduleId: module.id, @@ -99,10 +99,9 @@ export class Graph2DComponent { break; } case 'canvas': { - console.log('TIPO', canvas.tipo); - var shapesData = JSON.parse(canvas.resultado); + var shapesData = JSON.parse(toJSON(canvas.resultado)); var shapesDataNormalized = this.normalizeShapesData(shapesData); - + this.instance = null; this.instance = functionPlot({ target: '#graph2D-container', width: 800, @@ -122,9 +121,7 @@ export class Graph2DComponent { }) break; } - case 'animacion': { - console.log('TIPO', canvas.tipo); - + case 'animacion': { if(!this.animation.init) { this.animation.init = true; var animationData = canvas.resultado.map(res => JSON.parse(res)); @@ -142,6 +139,42 @@ export class Graph2DComponent { ) } + /** + * Angular lifecycle hook. + * called after Angular has fully initialized a component's view. + */ + ngAfterViewInit() { + if (!this.instance) { + this.instance = functionPlot({ + target: '#graph2D-container', + width: 800, + height: 700, + xAxis: { + label: 'x - axis', + scale: 'linear', + domain: { + initial: [-10, 10], + type: 'discrete' + } + }, + data: [], + plugins: [ + functionPlot.plugins.zoomBox() + ] + }) + } + } + + /** + * Angular lifecycle hook. + * called when a directive, pipe, or service is destroyed. + */ + ngOnDestroy() { + if (this.ghciServiceSub) { + this.ghciServiceSub.unsubscribe(); + } + } + /** * @name updateFrame * @desc update data for Function Plot and redraw the graph @@ -170,7 +203,6 @@ export class Graph2DComponent { }) } } - /** * @name runAnimation * @desc Run Shapes Animation @@ -209,6 +241,58 @@ export class Graph2DComponent { public zoomIn = function () { this.instance.zoomIn(); } + /** + * @name recenterPlot + * @desc center the plot and it returns to the initial state. + */ + public recenterPlot = function () { + this.instance.recenter(); + } + /** + * @name cleanPlot + * @desc remove all the graph from the instance. + */ + public cleanPlot = function () { + } + + /** + * @name exportPlot + * @desc Download Plot as an SVG image. + */ + public exportPlot = function() { + // Objects + var svg = document.querySelector('svg'); + var canvas = document.createElement("canvas"); + + // Set dimensions of the image + var svgSize = svg.getBoundingClientRect(); + canvas.width = svgSize.width; + canvas.height = svgSize.height; + + // Convert SVG DOM structure to xml + var ctx = canvas.getContext('2d'); + var data = new XMLSerializer().serializeToString(svg); + + // URL Object used to parse, construct, normalise, and encode URLs. + var DOMURL = window.URL || (<any>window).webkitURL || window; + + var img = new Image(); + var svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' }); + var url = DOMURL.createObjectURL(svgBlob); + + img.onload = function () { + ctx.drawImage(img, 0, 0); + DOMURL.revokeObjectURL(url); + + var imgURI = canvas + .toDataURL('image/png') + .replace('image/png', 'image/octet-stream'); + + triggerDownload(imgURI); + }; + img.src = url; + } + /** * @name normalizeRectData @@ -275,10 +359,10 @@ export class Graph2DComponent { return $textNormalized; } - /** - * @name normalizeTextData - * @desc Normalize Text data for Function Plot Library - * @param {Object} textData Data of Text to be normalized + /** + * @name normalizeLineData + * @desc Normalize Line data for Function Plot Library + * @param {Object} lineData Data of Line to be normalized * @returns {Object} */ // public normalizeLineData = function ($lineData) { @@ -296,10 +380,10 @@ export class Graph2DComponent { // return $lineNormalized; // } - /** - * @name normalizeTextData - * @desc Normalize Text data for Function Plot Library - * @param {Object} textData Data of Text to be normalized + /** + * @name normalizePolygonData + * @desc Normalize Polygon data for Function Plot Library + * @param {Object} textData Data of Polygon to be normalized * @returns {Object} */ // public normalizePolygonData = function ($textData) { @@ -354,6 +438,8 @@ export class Graph2DComponent { return normalized; } + + getRandomArbitrary = function (min, max) { return Math.round(Math.random() * (max - min) + min); } @@ -571,11 +657,7 @@ export class Graph2DComponent { return funcionString; } - ngOnDestroy() { - if (this.ghciServiceSub) { - this.ghciServiceSub.unsubscribe(); - } - } + } diff --git a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.helper.ts b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.helper.ts index 18bd27ed..28b6f40a 100644 --- a/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.helper.ts +++ b/Frontend Angular 4/src/app/layout/plotter/graph2D/graph2D.helper.ts @@ -7,27 +7,27 @@ export interface Animation { init: boolean } +export function toJSON(data: string) : string { + console.log('data',data); + const regexPts = /(?:\"pts\"\:\[(?:\((x),(y)\))+,?\])/g; + var dataJSON = data.replace(regexPts, (match, x, y) => { + return `"points": [[${x},${y}]]` + }) + console.log('dataJSON', dataJSON); + return dataJSON; +} + +export function triggerDownload(imgURI: string) { + var evt = new MouseEvent('click', { + view: window, + bubbles: false, + cancelable: true + }); -// export function toJSON(data: any) : string { -// var $points = data.pts; -// var $pointsJson = []; -// for (var p of $points) { -// $pointsJson.push([p[0],p[1]]); -// } - -// var dataJson = data; -// dataJson.pts -// } + var a = document.createElement('a'); + a.setAttribute('download', 'Matefun_2D_plot.png'); + a.setAttribute('href', imgURI); + a.setAttribute('target', '_blank'); -// return jsonString -// .replace( -// regexRot, (match, x, y, z) => { -// return `"rot": { "x": ${x}, "y": ${y}, "z": ${z} }` -// } -// ) -// .replace( -// regexPts, (match, x1, y1, z1, x2, y2, z2) => { -// return `"pts": [{ "x": ${x1}, "y": ${y1}, "z": ${z1} },{ "x": ${x2}, "y": ${y2}, "z": ${z2} }]` -// } -// ) -// } \ No newline at end of file + a.dispatchEvent(evt); +} \ No newline at end of file -- GitLab