ionic2 - Ionic 2 with Paper JS - Flickering canvas and white box -
i'm having issue ionic 2 (beta.7) , paper js: white box appears @ top left corner of canvas when start drawing. see example picture here.the canvas flickers when drawing.
a short description i'm trying do: take picture device camera , draw image on canvas , allow user draw on image.
any ideas i'm doing wrong? or suggestions on how fix this?
my code:
taking picture (using ionic native):
public takepicture(): void { // options camera plugin let options = { quality: 20, destinationtype: camera.destinationtype.file_uri, sourcetype: 1, encodingtype: camera.encodingtype.jpeg, mediatype: camera.mediatype.picture, correctorientation: true }; camera.getpicture(options).then((imagedata) => { this.nav.push(drawpicturepage, { imagepath: imagedata }); }, (err) => { }); }
drawpicturepage (picturedraw.ts):
import {platform, page, navcontroller, navparams} 'ionic-angular'; import {elementref, viewchild, ngzone} '@angular/core'; import * paper 'paper'; @page({ templateurl: 'build/pages/picturedraw/picturedraw.html', }) export class drawpicturepage { @viewchild("thecanvas") thecanvas: elementref; @viewchild("content") content: elementref; private path; private ctx: canvasrenderingcontext2d; // canvas context private imagepath: string = ''; private canvaswidth: number = 100; private canvasheight: number = 100; private canvasinnerwidth: number = 0; private canvasinnerheight: number = 0; private width: string = '0%'; private height: string = '0%'; constructor( public navparams: navparams, private zone: ngzone) { this.imagepath = navparams.get('imagepath'); } public ngafterviewinit(): void { this.ctx = this.thecanvas.nativeelement.getcontext("2d"); this.loadimage(); } private loadimage(): void { let image = new image(); image.src = this.imagepath; image.onload = () => { // count image ratio let ratio: number = image.width / image.height; // create canvas , context image resizing let oc = document.createelement('canvas'); let octx = oc.getcontext('2d'); oc.width = image.width; oc.height = image.height; // resize max size 1600x900 if (image.width > image.height && image.width > 1600) { oc.width = 1600; oc.height = 1600 / ratio; if (oc.height > 900) { oc.height = 900; oc.width = 900 * ratio; } } else if (image.height > 1600) { oc.height = 1600; oc.width = 1600 * ratio; if (oc.width > 900) { oc.width = 900; oc.height = 900 / ratio; } } octx.drawimage(image, 0, 0, oc.width, oc.height); // calculate ui size of canvas if (image.width > image.height) { // landscape this.canvaswidth = this.content.nativeelement.offsetwidth; this.canvasheight = this.canvaswidth / ratio; } else { // portrait this.canvasheight = this.content.nativeelement.offsetheight; this.canvaswidth = this.canvasheight * ratio; } // set canvas ui width , height this.zone.run(() => { this.width = math.round(this.canvaswidth) + 'px'; this.height = math.round(this.canvasheight) + 'px'; }); // set canvas inner width , height this.canvasinnerwidth = oc.width; this.canvasinnerheight = oc.height; this.setuppaperjs(oc); }; } /** setup paper js */ private setuppaperjs(canvas: = null): void { paper.install(window); paper.setup(this.thecanvas.nativeelement); this.thecanvas.nativeelement.width = this.canvasinnerwidth; this.thecanvas.nativeelement.height = this.canvasinnerheight; // draw image this.ctx.drawimage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, this.thecanvas.nativeelement.width, this.thecanvas.nativeelement.height); } private downevent(event: touchevent): void { console.info('downevent'); let touch: { x: number, y: number } = this.touchcoordtocanvascoord(event.touches[0].screenx, event.touches[0].screeny); let point: paper.point = new paper.point(); point.x = touch.x; point.y = touch.y; if (this.path) { this.path.selected = false; } // create new path this.path = new paper.path({ segments: [point], strokecolor: 'red', strokewidth: 10 }); } private dragevent(event: touchevent): void { console.info('dragevent'); let touch: { x: number, y: number } = this.touchcoordtocanvascoord(event.touches[0].screenx, event.touches[0].screeny); let point: paper.point = new paper.point(); point.x = touch.x; point.y = touch.y; this.path.lineto(point); } private upevent(event: touchevent): void { console.info('upevent'); this.path.simplify(10); } /** converts touch coordinate canvas coordinates */ private touchcoordtocanvascoord(touchx: number, touchy: number): { x: number, y: number } { let rv: { x: number, y: number } = { x: 0, y: 0 }; let x0: number = 0, y0: number = 0; x0 = this.thecanvas.nativeelement.getboundingclientrect().left; y0 = this.thecanvas.nativeelement.getboundingclientrect().top + 45; rv.x = this.canvasinnerwidth / (window.screen.width - 2 * x0) * (touchx - x0); rv.y = this.canvasinnerheight / (window.screen.height - 2 * y0) * (touchy - y0); if (rv.x < 0) rv.x = 0; if (rv.y < 0) rv.y = 0 if (rv.x > this.canvasinnerwidth) rv.x = this.canvasinnerwidth; if (rv.y > this.canvasinnerheight) rv.y = this.canvasinnerheight; return rv; } /*------------------------------- functions called template -------------------------------*/ private getwidth(): string { return this.width; } private getheight(): string { return this.height; } }
the template:
<ion-navbar primary *navbar> <ion-title>my title</ion-title> </ion-navbar> <ion-content> <div #content style="width: 100%; height: 100%;"> <canvas #thecanvas class="canvasstyle" [style.width]="getwidth()" [style.height]="getheight()" (touchstart)="downevent($event)" (touchend)="upevent($event)" (touchmove)="dragevent($event)"></canvas> </div> </ion-content>
and "canvasstyle" class:
.canvasstyle{ top: 50%; left: 50%; margin-right: -50%; transform: translate(-50%, -50%); position: absolute; background-color: rgba(0,0,0,0); -webkit-tap-highlight-color:rgba(0,0,0,0); }
any feedback appreciated.
the drawing wasn't working correctly because canvas wasn't set right paperjs. "flickering" seemed caused large size of canvas.
what ended doing drawing image on 1 canvas , using paperjs on another, smaller, canvas. before saving final image drew paper canvas on top of image canvas.
so in html have:
<canvas #imagecanvas class="canvasstyle" [style.width]="getwidth()" [style.height]="getheight()"></canvas> <canvas #papercanvas class="canvasstyle" [style.width]="getwidth()" [style.height]="getheight()" (touchstart)="downevent($event)" (touchend)="upevent($event)" (touchmove)="dragevent($event)"></canvas>
and in .ts:
@viewchild("imagecanvas") imagecanvas: elementref; @viewchild("papercanvas") papercanvas: elementref; ... public ngafterviewinit(): void { this.ctx = this.imagecanvas.nativeelement.getcontext('2d'); } ... private setuppaperjs(canvas): void { paper.install(window); paper.setup(this.papercanvas.nativeelement); this.imagecanvas.nativeelement.width = this.canvasinnerwidth; this.imagecanvas.nativeelement.height = this.canvasinnerheight; // draw image this.ctx.drawimage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, this.imagecanvas.nativeelement.width, this.imagecanvas.nativeelement.height); } ... private combinecanvases() { this.ctx.drawimage(this.papercanvas.nativeelement, 0, 0, this.papercanvas.nativeelement.width, this.papercanvas.nativeelement.height, 0, 0, this.imagecanvas.nativeelement.width, this.imagecanvas.nativeelement.height); }
don't know if best way working solution.
Comments
Post a Comment