andyhill Posted May 30, 2021 Share Posted May 30, 2021 Using a TUniCanvas (cArea), how can I get the toDataURL data (required for image of canvas later)? UniSession.AddJS('var context = fMain.cArea._cc_; '+ // CONTEXT WORKS FINE 'var dataURL = fMain.cArea.toDataURL(); '+ // FAILS 'var dataURL = fMain.cArea._cc_.toDataURL(); '+ // FAILS 'var dataURL = fMain.cArea.BitmapCanvas.toDataURL(); '+ // FAILS 'var dataURL = context.toDataURL(); '+ // FAILS Please advise how - thanks in advance Quote Link to comment Share on other sites More sharing options...
Sherzod Posted May 31, 2021 Share Posted May 31, 2021 4 hours ago, andyhill said: fMain.cArea._cc_ frMain.cArea._c_.toDataURL() _c_, not _cc_ Quote Link to comment Share on other sites More sharing options...
andyhill Posted May 31, 2021 Author Share Posted May 31, 2021 Great, I am trying to save and retrieve canvas with the following code which executes but fails to go back to (paint) the original canvas contents after drawing the circle ? UniSession.AddJS('var context = fMain.cArea._cc_; '+ ' // Save Canvas to img '+ 'var dataURL = fMain.cArea._c_.toDataURL(); '+ 'var img = new Image; img.onload = () => '+ '{ '+ ' context.drawImage(img, 0, 0, '+IntToStr(cArea.width)+', '+IntToStr(cArea.height)+'); '+ ' img.src = dataURL; '+ '}; '+ ' // Draw Circle On Top Of Canvas contents '+ '{ '+ ' context.beginPath(); '+ ' context.arc(150, 150, 105, 0, Math.PI * 2, false); '+ ' context.stroke(); '+ ' // Retrieve Original Canvas after 2 seconds '+ ' setTimeout(() => { context.drawImage(img, 0, 0, '+IntToStr(cArea.width)+', '+IntToStr(cArea.height)+'); }, 2000); '+ '}; '); Please advise ? Logic would dictate img -> context but not possible img.drawImage(context, 0, 0, '+IntToStr(cArea.width)+', '+IntToStr(cArea.height)) ??? Quote Link to comment Share on other sites More sharing options...
Sherzod Posted May 31, 2021 Share Posted May 31, 2021 There are errors in the code. Quote Link to comment Share on other sites More sharing options...
Sherzod Posted May 31, 2021 Share Posted May 31, 2021 And use such comments /* ... */, instead of // procedure TMainForm.UniButton15Click(Sender: TObject); begin UniSession.AddJS('var context = '+ UniCanvas1.JSName +'._cc_; '+ ' /*Save Canvas to img */'+ 'var dataURL = '+ UniCanvas1.JSName +'._c_.toDataURL(); '+ 'var img = new Image(); img.onload = () => '+ '{ '+ ' context.drawImage(img, 0, 0, '+IntToStr(UniCanvas1.width)+', '+IntToStr(UniCanvas1.height)+'); '+ ' img.src = dataURL; '+ '}; '+ //' // Draw Circle On Top Of Canvas contents '+ ' context.beginPath(); '+ ' context.arc(150, 150, 105, 0, Math.PI * 2, false); '+ ' context.stroke(); '+ //' // Retrieve Original Canvas after 2 seconds '+ ' setTimeout(() => { context.drawImage(img, 0, 0, '+IntToStr(UniCanvas1.width)+', '+IntToStr(UniCanvas1.height)+'); }, 2000); ' ); end; Quote Link to comment Share on other sites More sharing options...
andyhill Posted May 31, 2021 Author Share Posted May 31, 2021 Sherzod, I appreciate the pointers HOWEVER same issue, canvas does not return to the state before the circle ??? Quote Link to comment Share on other sites More sharing options...
Sherzod Posted May 31, 2021 Share Posted May 31, 2021 2 hours ago, andyhill said: I appreciate the pointers HOWEVER same issue, canvas does not return to the state before the circle ??? Hello, The canvas does not have a method that stores state. But you can use the techniques shown here. Quote Link to comment Share on other sites More sharing options...
Sherzod Posted May 31, 2021 Share Posted May 31, 2021 4 minutes ago, Sherzod said: But you can use the techniques shown here. I mean save the state before the canvas is changed. Quote Link to comment Share on other sites More sharing options...
andyhill Posted May 31, 2021 Author Share Posted May 31, 2021 I will try this code but Sherzod I thought my logic above was sound, save, change, restore ( contect.drawImage ). Quote Link to comment Share on other sites More sharing options...
andyhill Posted May 31, 2021 Author Share Posted May 31, 2021 Sherzod, this is what I understood but obviously have failed in my understanding to implement, please help (my canvas object is cArea) - thanks:- FORM CREATE ... s:= 'eventOnDraw=function eventOnDraw(ctx, eventName) '+ '{ '+ ' var fireEvent = function() '+ ' { '+ ' var evt = document.createEvent("Events"); '+ ' evt.initEvent(''_completed_'', true, true); '+ // was eventName ' ctx.canvas.dispatchEvent(evt); '+ ' } '+ ' var stroke = ctx.stroke; '+ ' ctx.stroke = function() '+ ' { '+ ' stroke.call(this); '+ ' fireEvent(); '+ ' }; '+ ' var fillRect = ctx.fillRect; '+ ' ctx.fillRect = function(x, y, w, h) '+ ' { '+ ' fillRect.call(this, x, y, w, h); '+ ' fireEvent(); '+ ' }; '+ ' var fill = ctx.fill; '+ ' ctx.fill = function() '+ ' { '+ ' fill.call(this); '+ ' fireEvent(); '+ ' }; '+ '} '; cArea.ClientEvents.ExtEvents.Add(s); // here ??? UniSession.AddJS(cArea.JSName +'.addEventListener(''_completed_'', completedHandler, false); '); // ??? ... CANVAS AJAXEVENT ////////////////////////////////////////////////////////////////////////////// if EventName = 'completedHandler' then begin ShowMessage('Done'); end; ... BUTTON CLICK UniSession.AddJS('var context = ' + cArea.JSName + '._cc_; '+ '{ '+ ' context.beginPath(); '+ ' context.arc(150, 150, 105, 0, Math.PI * 2, false); '+ ' eventOnDraw(context, ''stroke''); '+ // ??? also how do I do a fill with params x, y etc. '} '); Quote Link to comment Share on other sites More sharing options...
andyhill Posted June 2, 2021 Author Share Posted June 2, 2021 Asking for your help on this Sherzod - please Quote Link to comment Share on other sites More sharing options...
Sherzod Posted June 2, 2021 Share Posted June 2, 2021 7 minutes ago, andyhill said: Asking for your help on this Sherzod - please Hello, Sorry, this takes some extra time. Please specify again what you want. 1. Save - please specify in more detail. 2. An event when changing the canvas? 3. Restore states - please specify in more detail. Quote Link to comment Share on other sites More sharing options...
andyhill Posted June 2, 2021 Author Share Posted June 2, 2021 I want to preserve the current canvas with all of it's images and lines in JavaScript, then add new lines etc. in JavaScript, now much later (separate action) revert back to the preserved canvas in JavaScript (view it as a type of UnDo). Delphi, Server-Side and ajax-requests are to time intensive, we need to do all of this at the JavaScript/Local Browser level. My code some post back clearly showed:- Make a Copy of the current canvas Add More Drawings to the canvas Retrieve Copy at a later date and restore the canvas to it's previous condition Quote Link to comment Share on other sites More sharing options...
Sherzod Posted June 2, 2021 Share Posted June 2, 2021 14 minutes ago, andyhill said: I want to preserve the current canvas with all of it's images and lines in JavaScript, then add new lines etc. in JavaScript, now much later (separate action) revert back to the preserved canvas in JavaScript (view it as a type of UnDo). Delphi, Server-Side and ajax-requests are to time intensive, we need to do all of this at the JavaScript/Local Browser level. My code some post back clearly showed:- Make a Copy of the current canvas Add More Drawings to the canvas Retrieve Copy at a later date and restore the canvas to it's previous condition You'd better use this library: http://fabricjs.com/ Quote Link to comment Share on other sites More sharing options...
andyhill Posted June 2, 2021 Author Share Posted June 2, 2021 I appreciate your help Sherzod but I was trying to keep it to UniGUI as my needs are simple. Quote Link to comment Share on other sites More sharing options...
Sherzod Posted June 2, 2021 Share Posted June 2, 2021 3 minutes ago, andyhill said: but I was trying to keep it to UniGUI as my needs are simple. You can try using this library with UniGUI. Quote Link to comment Share on other sites More sharing options...
andyhill Posted June 2, 2021 Author Share Posted June 2, 2021 Here is a minimal example of fabric, is this how you would implement ? //(function() { //var canvas = this.__canvas = new fabric.StaticCanvas('c'); UniSession.AddJS('var canvas = ' + cArea.JSName + '._c_ = new fabric.StaticCanvas('c'); // ??? canvas.add( new fabric.Rect({ top: 100, left: 100, width: 50, height: 50, fill: '#f55' }), new fabric.Circle({ top: 140, left: 230, radius: 75, fill: 'green' }), new fabric.Triangle({ top: 300, left: 210, width: 100, height: 100, fill: 'blue' }) ); fabric.Image.fromURL('../lib/pug.jpg', function(img) { canvas.add(img.set({ left: 400, top: 350, angle: 30 }).scale(0.25)); }); function animate() { canvas.item(0).animate('top', canvas.item(0).get('top') === 500 ? '100' : '500', { duration: 1000, onChange: canvas.renderAll.bind(canvas), onComplete: animate }); } animate(); //})(); ); Quote Link to comment Share on other sites More sharing options...
Sherzod Posted June 2, 2021 Share Posted June 2, 2021 I mean you don't need to mix, but just embed this library inside the frame for example. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.