How to address an Image in Fabric.js - fabricjs

Sorry for the maybe stupid question. I start to get my head into Fabric.js, but it´s hard for me because of the documentation.
Please look at the code below:
var canvas = new fabric.Canvas('c');
var iminst = new fabric.Image.fromURL ('./images/1stback.jpg', function(myimage){
myimage.left=0;
myimage.top=0;
canvas.add(myimage);
});
iminst.set('angle', 45);
The image is loaded and shown, but how do I address it afterwards.
I just get an Error
"TypeError: 'undefined' is not a function (evaluating 'iminst.set('angle', 45)')"

You're missing the basics. It seems like you haven't gone through the great tutorials available on the Fabric site.
The simple code to solve your issue would be:
var canvas = new fabric.Canvas('c');
var iminst;
fabric.Image.fromURL ('./images/1stback.jpg', function(myimage){
iminst=myimage;
myimage.left=0;
myimage.top=0;
canvas.add(myimage);
canvas.renderAll();
test();
});
function test(){
iminst.set('angle', 45); // you can refer it but not before the callback finished
}
Hope it helps if you haven't yet figured out the answer by yourself... gl

Related

Problem with canvas using vega with nodejs (server side only)

I've been working for a few weeks now on a Discord bot that basically compiles stats on the server and deduces patterns. In order to improve it, I wanted to make it generate graphs as PNGs in order to send them back to the user - in short, no DOM.
In order to achieve this, I'm currenlty using vega (version 5.10.1 - latest) and node-canvas (version 2.6.1 - latest), with nodejs v12.16.1.
I've been scouring the web for help on vega usage, and found a couple contradicting sources. I've been using the example code provided here :
https://vega.github.io/vega/usage/
The thing is that I keep getting this error :
TypeError: Cannot read property 'getContext' of null
message:"Cannot read property 'getContext' of null"
stack:"TypeError: Cannot read property 'getContext' of null
at resize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3665:28)
at CanvasRenderer.prototype$6.resize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3714:5)
at CanvasRenderer.prototype$4.initialize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3294:17)
at CanvasRenderer.prototype$6.initialize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3709:28)
at initializeRenderer (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-view\build\vega-view.js:657:8)
at renderHeadless (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-view\build\vega-view.js:780:12)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async View.renderToCanvas [as toCanvas] (e:\DEV\GIT REPOS\GITHUB\P...
Here is the code which is giving me trouble :
// Imports
const vega = require('vega');
// Render image from given graph spec (statsObject)
async function graphToImage (statsObject) {
graphObject = new vega.View(vega.parse(statsObject), { renderer: 'none'});
const pngName = generateFileName(10);
removeExistingFile(pngName);
graphObject.toCanvas().then(canvas => {
console.log('Writing PNG to file...');
writeFile(`../../../../generated/${pngName}.png`, canvas.toBuffer());
}).catch(err => {
console.log("Error writing PNG to file:");
console.error(err);
});
return pngName;
}
I don't really know how canvas or vega work, and so I have no idea what could be causing this issue and how to fix it... However, the problem seems to be located inside of the toCanvas() method. Any help is much appreciated !
Thanks in advance !
// Using view.toSVG() along with the npm package sharp worked well for me
const view = new vega.View(vega.parse(templateObject), {renderer: 'none'});
view.toSVG().then(async function (svg) {
await sharp(Buffer.from(svg))
.toFormat('png')
.toFile('fileName.png')
}).catch(function(err) {
console.error(err);
});
Edit : I managed to fix my issue, and I am posting the anwser here for future notice :
I succeeded to actually generate a graph picture by rendering the View object straight to an SVG string, by using view.toSVG() instead of the buggy view.toCanvas(), which worked great.
Then, all that was left to do was to convert the obtained SVG string into a PNG file, and that was it.
Here is the updated, working code :
// Imports
const vega = require('vega');
// Render image from given graph object
async function graphToImage (statsObject) {
// Generate a new 10-char hex string
const pngName = generateHexStringName(10);
// Remove any existing file with the same name in order to prevent confusion
removeExistingFile(pngName);
var view = new vega.View(vega.parse(statsObject), {renderer: 'none'});
// Generate an SVG string
view.toSVG().then(async function (svg) {
// Working SVG string
console.log(svg);
// Process obtained SVG string, e. g. write it to PNG file
}).catch(function(err) {
console.error(err);
});
// Return the name of the generated PNG file
return pngName;
}

How can i use ‚momentjs‘ in a ‚binary-parser‘ formatter?

Can anybody help me please. How can i use moment in a formatter?
i think this is not a problem from node or binary parser. it is my understanding i think.
const Parser = require("binary-parser").Parser;
const moment = require('moment');
let time = function(timestamp) {
return moment(timestamp, 'YYMMDDHHmmssSS').format('YYYY-MM-DD HH:mm:ss.SS');
};
let Telegram = new Parser()
.string('timestamp', {encoding: 'hex', length: 7, formatter: time});
The Exception is:
evalmachine.:9
return moment(timestamp, 'YYMMDDHHmmssSS').format('YYYY-MM-DD HH:mm:ss.SS');
^
ReferenceError: moment is not defined
at Parser. (evalmachine.:9:2)
...
I think the Problem is that Parser don't know moment. But how can i realize that?
i have tried to import moment directly in the binary-parser module. But it doesn't working.
If i run moment outside of Parser then it is working.
Maybe anybody can help me.
The formatter function runs without the momentjs context. I am guessing because of the way it consumes the formatter property. In the code found here, the code is:
if (this.code.formatter) {
... (ctx, varName, this.options.formatter)
Because of the funny way the this keyword works, it's bound to the object (options) and because that declaration does not contain momentjs, it says that it is not defined.
You can get a better understanding of this by looking at line 735:
ctx.pushCode("{0} = ({1}).call(this, {0});", varName, formatter);
It's bound to the current object.
P.S.: I copied the code and pasted it on Node.js and it's working perfectly. ^That is a possible explanation.

Electron app: Reference mainWindow object in another module?

I am building an electron app, where the mainWindow object is created following the quick start: http://electron.atom.io/docs/tutorial/quick-start/.
As per this quick start, it is created asynchronously. The problem that I run into, is that for instance when I want to send messages from main to renderer process, I need to reference the mainWindow object. If this happens to be in a module that I require, then I need a means to make this module know of the mainWindow object.
I could of course prepend it with global., but I know that this is very much advised against. So I wish to do it more elegantly.
I came across this post: Asynchronous nodejs module exports; which appears to offer a solution. Taking the main.js file from the quick start (see above link, it's explicitly shown there), it appears I would add to the createWindow function
if( typeof callback === 'function' ){
callback(mainWindow);
}
and export the main.js module as
module.exports = function(cb){
if(typeof mainWindow !== 'undefined'){
cb(mainWindow);
} else {
callback = cb;
}
}
Then, in a higher-level script, I would require as follows:
let main = require('./main.js');
let lib = require('./lib.js'); // Library where I need a mainWindow reference
main(function(window) {
lib.doSomething(window);
});
where lib.js looks like
module.exports.doSomething = function(window) {
// Do something with window object, like sending ipc messages to it
window.webContents.send('hello-from-main', "hi!");
}
Although the simple case in the original post 'Asynchronous nodejs module exports' works fine, I cannot get it to work like described above; running the app it complains Uncaught Exception: TypeError: Cannot read property 'webContents' of null. This is also the case if I directly require lib.js within main()'s callback (which I know is also advised against).
I confess that I do not fully understand the simple case of the post, as I am rather new to node. This prevents me from fixing my own implementation of it, which I agree is blunt copy/pasting which reasonably should be expected to fail. Could somebody help me with how to correct above method, or advise me of a different approach to make it work? Thank you!
I have created the npm package electron-main-window for the same.
Install:
$ npm install electron-main-window
or
$ yarn add electron-main-window
Usage:
// Import ES6 way
import { getMainWindow } from 'electron-main-window';
const mainWindow = getMainWindow();
// Import ES5 way
const mainWindow = require('electron-main-window').getMainWindow();
// e.g:
if(mainWindow !== null ){
mainWindow.webContents.send('mainWindowCommunication', "This is a test message");
}
Whooops! The devil is in the details... I had defined on top of main.js
let mainWindow = null, callback;
which caused the error! Should be
let mainWindow, callback;
then it works perfectly!
P.s. Instead of deleting my post, I opted for keeping it and answering myself for future reference of other people who need asynchronous exporting.

Fabricjs+Node.js: fabric's canvas toDataURL calling toBuffer() not a method

I'm using the following code to try to see if I can load a canvas from a json string then generate a dataURL png for it:
var fabric=require('fabric');
var canvas = new fabric.fabric.Canvas();
var jsonStr='{"objects":[],"background":"rgba(0, 0, 0,0)","backgroundImage":"http://entropy.tmok.com/~gauze/canvas/any.gif","backgroundImageOpacity":1,"backgroundImageStretch":true,"overlayImage":"http://entropy.tmok.com/~gauze/canvas/frame.png","overlayImageLeft":0,"overlayImageTop":0}';
canvas.loadFromJSON(jsonStr);
img=canvas.toDataURL('png');
it errors on the toDataURL() line with:
/root/node-v0.8.16-linux-x86/node_modules/canvas/lib/canvas.js:190
return prefix + this.toBuffer().toString('base64');
^
which tells me 'this' (which is a Canvas according to console.log) doesn't have a .toBuffer() method. am I doing something wrong or is this a bug in fabric's node module?
thanks.
never mind I missed : .createCanvasForNode()
cant wait for documentation of this :P

instantiate sound clips dynamically in as3

How can i call and instantiate soundclips in my library dynamically
here is the code i have so far
function soundbutton_Handler (e:MouseEvent):void {
trace(e.target.name);
var mySound:Sound = new e.target();
mySound.play();
}
and the error i get is :
Error #1007: Instantiation attempted on a non-constructor.
at quiz_fla::MainTimeline/soundbutton_Handler()
I got it, for future reference if any one needs help i 'm posting the solution here
var classRef:Class = getDefinitionByName(e.target.name) as Class;
var mysound:Sound = new classRef();
mysound.play();

Resources