Open Shohin93 opened 4 years ago
If you are retriving the buffer from a service, is probably coming in a format that is not Buffer. What format is it? I would imagine is a url or a data url.
@asturur it's something like this:
{ AcceptRanges: 'bytes',
LastModified: 2019-12-26T16:10:00.000Z,
ContentLength: 220518,
ETag: '"c6288cc91a3993c207a96d169a4921ab"',
ContentType: 'application/octet-stream',
Metadata:
{ extension: 'png',
mime: 'image/png',
width: '1019',
height: '776',
name: 'Screen_Shot_2019_12_18_at_11_01_04_AM' },
Body: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 03 fb 00 00 03 08 08 06 00 00 00 97 7e f5 8d 00 00 0a b6 69 43 43 50 49 43 43 20 50 72 6f 66 69 ... > }
So, body
is Buffer
. Is there any api in in Fabric that works with buffers? fromObject
doesn't really do the job
oh ok you are getting the file itself. if the api returning you the file is GET and not authenticated, you can pass that URL to the fromURL image method and you should be fine.
Otherwise, assuming you are running under node, the only thing you could try to do is to instantiate a new HTMLImageElement using fabric.util.createImage
, then you could then try to access the node-canvas implementation of that image using fabric.util.getNodeCanvas
and then check the node-canvas docs on how to load an image from Buffer.
(i think is image.src = Buffer but i may be wrong )
@asturur is it something like this:
const createdImage = fabric.util.createImage();
const nodeCanvas = fabric.util.getNodeCanvas(createdImage);
nodeCanvas.src = url;
?
nodeCanvas
returns undefined
Also, tried:
let image = fabric.util.createImage();
image.onload = function() {
let nodeCanvasImage = fabric.util.getNodeCanvas(image);
nodeCanvasImage.src = url;
}
and it doesn't seem to go inside the function()
I'm using "fabric": "2.7.0"
Are you sure node-canvas is properly installed in your app?
Normally having an undefined from that function means that the node canvas didn t install properly.
fabric 2 uses node-canvas 1.6.x, i would suggest you to give a test to fabric 3, changes are really small and node experience should be improved, also node canvas 2 is so much better.
Create a basic index.js that reproduces the failure if you can t solve ( that 3 or 4 lines of code, but with the requires and everything that is necessary for them to fail ) and post it here
@asturur upgraded packages to the latest (tried also upgrading fabric
to 3.0.0
), but no luck.
First issue is it still gives undefined
on fabric.util.getNodeCanvas(image)
. Second one is fabric.util.createImage()
for fabric 3.x.x
returns empty object HTMLImageElement {}
and for fabric 2.x.x
returns the following:
HTMLImageElement {
[Symbol(impl)]:
HTMLImageElementImpl {
_eventListeners: {},
_core:
{ DOMException: [Object],
NamedNodeMap: [Function: NamedNodeMap],
Attr: [Function: Attr],
Node: [Object],
Element: [Function: Element],
DocumentFragment: [Function: DocumentFragment],
HTMLDocument: [Function: Document],
Document: [Function: Document],
XMLDocument: [Function: XMLDocument],
CharacterData: [Function: CharacterData],
Text: [Function: Text],
CDATASection: [Function: CDATASection],
ProcessingInstruction: [Function: ProcessingInstruction],
Comment: [Function: Comment],
DocumentType: [Function: DocumentType],
DOMImplementation: [Function: DOMImplementation],
Event: [Object],
CustomEvent: [Function: CustomEvent],
MessageEvent: [Function: MessageEvent],
ErrorEvent: [Function: ErrorEvent],
HashChangeEvent: [Function: HashChangeEvent],
FocusEvent: [Function: FocusEvent],
PopStateEvent: [Function: PopStateEvent],
UIEvent: [Function: UIEvent],
MouseEvent: [Function: MouseEvent],
KeyboardEvent: [Object],
TouchEvent: [Function: TouchEvent],
ProgressEvent: [Function: ProgressEvent],
EventTarget: [Function: EventTarget],
Location: [Function: Location],
History: [Function: History],
Blob: [Function: Blob],
File: [Function: File],
FileList: [Function: FileList],
DOMParser: [Function: DOMParser],
FormData: [Function: FormData],
HTMLElement: [Function: HTMLElement],
HTMLAnchorElement: [Function: HTMLAnchorElement],
HTMLAppletElement: [Function: HTMLAppletElement],
HTMLAreaElement: [Function: HTMLAreaElement],
HTMLAudioElement: [Function: HTMLAudioElement],
HTMLBaseElement: [Function: HTMLBaseElement],
HTMLBodyElement: [Function: HTMLBodyElement],
HTMLBRElement: [Function: HTMLBRElement],
HTMLButtonElement: [Function: HTMLButtonElement],
HTMLCanvasElement: [Function: HTMLCanvasElement],
HTMLDataElement: [Function: HTMLDataElement],
HTMLDataListElement: [Function: HTMLDataListElement],
HTMLDialogElement: [Function: HTMLDialogElement],
HTMLDirectoryElement: [Function: HTMLDirectoryElement],
HTMLDivElement: [Function: HTMLDivElement],
HTMLDListElement: [Function: HTMLDListElement],
HTMLEmbedElement: [Function: HTMLEmbedElement],
HTMLFieldSetElement: [Function: HTMLFieldSetElement],
HTMLFontElement: [Function: HTMLFontElement],
HTMLFormElement: [Function: HTMLFormElement],
HTMLFrameElement: [Function: HTMLFrameElement],
HTMLFrameSetElement: [Function: HTMLFrameSetElement],
HTMLHeadingElement: [Function: HTMLHeadingElement],
HTMLHeadElement: [Function: HTMLHeadElement],
HTMLHRElement: [Function: HTMLHRElement],
HTMLHtmlElement: [Function: HTMLHtmlElement],
HTMLIFrameElement: [Function: HTMLIFrameElement],
HTMLImageElement: [Function: HTMLImageElement],
HTMLInputElement: [Function: HTMLInputElement],
HTMLLabelElement: [Function: HTMLLabelElement],
HTMLLegendElement: [Function: HTMLLegendElement],
HTMLLIElement: [Function: HTMLLIElement],
HTMLLinkElement: [Function: HTMLLinkElement],
HTMLMapElement: [Function: HTMLMapElement],
HTMLMediaElement: [Object],
HTMLMenuElement: [Function: HTMLMenuElement],
HTMLMetaElement: [Function: HTMLMetaElement],
HTMLMeterElement: [Function: HTMLMeterElement],
HTMLModElement: [Function: HTMLModElement],
HTMLObjectElement: [Function: HTMLObjectElement],
HTMLOListElement: [Function: HTMLOListElement],
HTMLOptGroupElement: [Function: HTMLOptGroupElement],
HTMLOptionElement: [Function: HTMLOptionElement],
HTMLOutputElement: [Function: HTMLOutputElement],
HTMLParagraphElement: [Function: HTMLParagraphElement],
HTMLParamElement: [Function: HTMLParamElement],
HTMLPreElement: [Function: HTMLPreElement],
HTMLProgressElement: [Function: HTMLProgressElement],
HTMLQuoteElement: [Function: HTMLQuoteElement],
HTMLScriptElement: [Function: HTMLScriptElement],
HTMLSelectElement: [Function: HTMLSelectElement],
HTMLSourceElement: [Function: HTMLSourceElement],
HTMLSpanElement: [Function: HTMLSpanElement],
HTMLStyleElement: [Function: HTMLStyleElement],
HTMLTableCaptionElement: [Function: HTMLTableCaptionElement],
HTMLTableCellElement: [Function: HTMLTableCellElement],
HTMLTableColElement: [Function: HTMLTableColElement],
HTMLTableDataCellElement: [Function: HTMLTableDataCellElement],
HTMLTableElement: [Function: HTMLTableElement],
HTMLTableHeaderCellElement: [Function: HTMLTableHeaderCellElement],
HTMLTimeElement: [Function: HTMLTimeElement],
HTMLTitleElement: [Function: HTMLTitleElement],
HTMLTableRowElement: [Function: HTMLTableRowElement],
HTMLTableSectionElement: [Function: HTMLTableSectionElement],
HTMLTemplateElement: [Function: HTMLTemplateElement],
HTMLTextAreaElement: [Function: HTMLTextAreaElement],
HTMLTrackElement: [Object],
HTMLUListElement: [Function: HTMLUListElement],
HTMLUnknownElement: [Function: HTMLUnknownElement],
HTMLVideoElement: [Function: HTMLVideoElement],
StyleSheet: [Function: StyleSheet],
MediaList: [Function: MediaList],
CSSStyleSheet: [Function: CSSStyleSheet],
CSSRule: [Object],
CSSStyleRule: [Object],
CSSMediaRule: [Function: CSSMediaRule],
CSSImportRule: [Function: CSSImportRule],
CSSStyleDeclaration: [Function: CSSStyleDeclaration],
StyleSheetList: [Function: StyleSheetList],
XPathException: [Object],
XPathExpression: [Function: XPathExpression],
XPathResult: [Object],
XPathEvaluator: [Function: XPathEvaluator],
HTMLCollection: [Function: HTMLCollection],
NodeFilter: [Object],
NodeIterator: [Function: NodeIterator],
NodeList: [Function: NodeList],
XMLHttpRequestEventTarget: [Function: XMLHttpRequestEventTarget],
XMLHttpRequestUpload: [Function: XMLHttpRequestUpload],
DOMTokenList: [Function: DOMTokenList],
URL: [Function: URL],
Window: [Function: Window] },
_ownerDocument:
DocumentImpl {
_eventListeners: {},
_core: [Object],
_ownerDocument: [Circular],
_childNodesList: [Object],
_childrenList: null,
_version: 4,
_memoizedQueries: {},
nodeType: 9,
_parsingMode: 'html',
_htmlToDom: [Object],
_implementation: [Object],
_defaultView: [Object],
_global: [Object],
_documentElement: [Object],
_ids: {},
_attached: true,
_currentScript: null,
_cookieJar: [Object],
_contentType: undefined,
_encoding: 'UTF-8',
_URL: [Object],
_origin: 'null',
_location: [Object],
_history: [Object],
_activeNodeIterators: [],
_activeNodeIteratorsMax: 10,
_referrer: '',
_lastModified: '12/29/2019 21:57:47',
_queue: [Object],
_customResourceLoader: undefined,
_pool: [Object],
_agentOptions: [Object],
_strictSSL: true,
_proxy: undefined,
_requestManager: [Object],
readyState: 'complete',
_lastFocusedElement: null,
[Symbol(DOM SymbolTree)]: [Object],
[Symbol(wrapper)]: [Object] },
_childNodesList: null,
_childrenList: null,
_version: 0,
_memoizedQueries: {},
nodeType: 1,
scrollTop: 0,
scrollLeft: 0,
_namespaceURI: 'http://www.w3.org/1999/xhtml',
_prefix: null,
_localName: 'img',
_attributes: NamedNodeMap { [Symbol(NamedNodeMap internal)]: [Object] },
_tabIndex: 0,
_settingCssText: false,
_clickInProgress: false,
_style:
CSSStyleDeclaration {
_values: {},
_importants: {},
_length: 0,
_onChange: [Function] },
[Symbol(DOM SymbolTree)]:
SymbolTreeNode {
parent: null,
previousSibling: null,
nextSibling: null,
firstChild: null,
lastChild: null,
childrenVersion: 0,
childIndexCachedUpTo: null,
cachedIndex: -1,
cachedIndexVersion: NaN },
[Symbol(wrapper)]: [Circular] } }
Not sure what causes this ^
Upgraded packages:
When my app was on fabric: 1.x
(before upgrading it to 2.x), passing buffer to fabric.Image.fromURL
would work just fine 😄.
"dependencies": {
"fabric": "3.6.0"
},
"peerDependencies": {
"canvas": "^2.6.1",
"jsdom": "^15.2.1"
}
Sample code:
const createdImage = fabric.util.createImage();
console.log("\n createdImage", createdImage, "\n");
const nodeCanvas = fabric.util.getNodeCanvas(createdImage);
console.log("\n nodeCanvas", nodeCanvas, "\n");
Output:
createdImage HTMLImageElement {
[Symbol(impl)]:
HTMLImageElementImpl {
_eventListeners: {},
_core:
{ DOMException: [Object],
NamedNodeMap: [Function: NamedNodeMap],
.......
.......
....... // Shows an empty object HTMLImageElement {} for fabric 3.x
nodeCanvas undefined // For both fabric 2.x and 3.x it returns undefined
@asturur actually, i don't see any _canvas
or _image
property returned from fabric.jsdomImplForWrapper(element)
(which is called from getNodeCanvas()
):
HTMLImageElementImpl {
_eventListeners: [Object: null prototype] {},
_ownerDocument:
DocumentImpl {
_eventListeners: [Object: null prototype] { load: [Array] },
_ownerDocument: [Circular],
_childNodesList:
NodeListImpl {
_list: [Array],
_isLive: true,
_version: 6,
_element: [Circular],
_query: [Function: query],
[Symbol(wrapper)]: [NodeList] },
_childrenList: null,
_version: 6,
_memoizedQueries: {},
_registeredObserverList: [],
_registeredHandlers: Set {},
_eventHandlers: [Object: null prototype] {},
nodeType: 9,
_parsingMode: 'html',
_implementation:
DOMImplementationImpl {
_ownerDocument: [Circular],
[Symbol(wrapper)]: DOMImplementation {} },
_defaultView:
Window {
onafterprint: [Getter/Setter],
onbeforeprint: [Getter/Setter],
onbeforeunload: [Getter/Setter],
onhashchange: [Getter/Setter],
onlanguagechange: [Getter/Setter],
onmessage: [Getter/Setter],
onmessageerror: [Getter/Setter],
onoffline: [Getter/Setter],
ononline: [Getter/Setter],
onpagehide: [Getter/Setter],
onpageshow: [Getter/Setter],
onpopstate: [Getter/Setter],
onrejectionhandled: [Getter/Setter],
onstorage: [Getter/Setter],
onunhandledrejection: [Getter/Setter],
onunload: [Getter/Setter],
onblur: [Getter/Setter],
onerror: [Getter/Setter],
onfocus: [Getter/Setter],
onload: [Getter/Setter],
onresize: [Getter/Setter],
onscroll: [Getter/Setter],
onabort: [Getter/Setter],
onautocomplete: [Getter/Setter],
onautocompleteerror: [Getter/Setter],
oncancel: [Getter/Setter],
oncanplay: [Getter/Setter],
oncanplaythrough: [Getter/Setter],
onchange: [Getter/Setter],
onclick: [Getter/Setter],
onclose: [Getter/Setter],
oncontextmenu: [Getter/Setter],
oncuechange: [Getter/Setter],
ondblclick: [Getter/Setter],
ondrag: [Getter/Setter],
ondragend: [Getter/Setter],
ondragenter: [Getter/Setter],
ondragexit: [Getter/Setter],
ondragleave: [Getter/Setter],
ondragover: [Getter/Setter],
ondragstart: [Getter/Setter],
ondrop: [Getter/Setter],
ondurationchange: [Getter/Setter],
onemptied: [Getter/Setter],
onended: [Getter/Setter],
oninput: [Getter/Setter],
oninvalid: [Getter/Setter],
onkeydown: [Getter/Setter],
onkeypress: [Getter/Setter],
onkeyup: [Getter/Setter],
onloadeddata: [Getter/Setter],
onloadedmetadata: [Getter/Setter],
onloadstart: [Getter/Setter],
onmousedown: [Getter/Setter],
onmouseenter: [Getter/Setter],
onmouseleave: [Getter/Setter],
onmousemove: [Getter/Setter],
onmouseout: [Getter/Setter],
onmouseover: [Getter/Setter],
onmouseup: [Getter/Setter],
onwheel: [Getter/Setter],
onpause: [Getter/Setter],
onplay: [Getter/Setter],
onplaying: [Getter/Setter],
onprogress: [Getter/Setter],
onratechange: [Getter/Setter],
onreset: [Getter/Setter],
onsecuritypolicyviolation: [Getter/Setter],
onseeked: [Getter/Setter],
onseeking: [Getter/Setter],
onselect: [Getter/Setter],
onsort: [Getter/Setter],
onstalled: [Getter/Setter],
onsubmit: [Getter/Setter],
onsuspend: [Getter/Setter],
ontimeupdate: [Getter/Setter],
ontoggle: [Getter/Setter],
onvolumechange: [Getter/Setter],
onwaiting: [Getter/Setter],
_registeredHandlers: Set {},
_eventHandlers: [Object: null prototype] {},
_resourceLoader: [ResourceLoader],
_globalProxy: [Circular],
_document: [Document],
_sessionHistory: [SessionHistory],
_virtualConsole: [VirtualConsole],
_runScripts: undefined,
_top: [Circular],
_parent: [Circular],
_frameElement: null,
_length: 0,
_pretendToBeVisual: false,
_storageQuota: 5000000,
_commonForOrigin: [Object],
_currentOriginData: [Object],
_localStorage: Storage {},
_sessionStorage: Storage {},
length: [Getter],
window: [Getter],
frameElement: [Getter],
frames: [Getter],
self: [Getter],
parent: [Getter],
top: [Getter],
document: [Getter],
external: [Getter],
location: [Getter],
history: [Getter],
navigator: [Getter],
locationbar: [Getter],
menubar: [Getter],
personalbar: [Getter],
scrollbars: [Getter],
statusbar: [Getter],
toolbar: [Getter],
performance: [Getter],
screen: [Getter],
localStorage: [Getter],
sessionStorage: [Getter],
addEventListener: [Function: bound addEventListener],
removeEventListener: [Function: bound removeEventListener],
dispatchEvent: [Function: bound dispatchEvent],
setTimeout: [Function],
setInterval: [Function],
clearInterval: [Function: bound stopTimer],
clearTimeout: [Function: bound stopTimer],
__stopAllTimers: [Function],
postMessage: [Function],
atob: [Function],
btoa: [Function],
FileReader: [Function],
WebSocket: [Function],
AbortSignal: [Function: AbortSignal],
AbortController: [Function: AbortController],
XMLHttpRequest: [Function],
ArrayBuffer: [Function: ArrayBuffer],
Int8Array: [Function: Int8Array],
Uint8Array: [Function: Uint8Array],
Uint8ClampedArray: [Function: Uint8ClampedArray],
Int16Array: [Function: Int16Array],
Uint16Array: [Function: Uint16Array],
Int32Array: [Function: Int32Array],
Uint32Array: [Function: Uint32Array],
Float32Array: [Function: Float32Array],
Float64Array: [Function: Float64Array],
stop: [Function],
close: [Function],
getComputedStyle: [Function],
captureEvents: [Function],
releaseEvents: [Function],
console: [Object],
name: '',
status: '',
devicePixelRatio: 1,
innerWidth: 1024,
innerHeight: 768,
outerWidth: 1024,
outerHeight: 768,
pageXOffset: 0,
pageYOffset: 0,
screenX: 0,
screenLeft: 0,
screenY: 0,
screenTop: 0,
scrollX: 0,
scrollY: 0,
alert: [Function],
blur: [Function],
confirm: [Function],
focus: [Function],
moveBy: [Function],
moveTo: [Function],
open: [Function],
print: [Function],
prompt: [Function],
resizeBy: [Function],
resizeTo: [Function],
scroll: [Function],
scrollBy: [Function],
scrollTo: [Function],
[Symbol(named property tracker)]: [NamedPropertiesTracker] },
_global:
Window {
onafterprint: [Getter/Setter],
onbeforeprint: [Getter/Setter],
onbeforeunload: [Getter/Setter],
onhashchange: [Getter/Setter],
onlanguagechange: [Getter/Setter],
onmessage: [Getter/Setter],
onmessageerror: [Getter/Setter],
onoffline: [Getter/Setter],
ononline: [Getter/Setter],
onpagehide: [Getter/Setter],
onpageshow: [Getter/Setter],
onpopstate: [Getter/Setter],
onrejectionhandled: [Getter/Setter],
onstorage: [Getter/Setter],
onunhandledrejection: [Getter/Setter],
onunload: [Getter/Setter],
onblur: [Getter/Setter],
onerror: [Getter/Setter],
onfocus: [Getter/Setter],
onload: [Getter/Setter],
onresize: [Getter/Setter],
onscroll: [Getter/Setter],
onabort: [Getter/Setter],
onautocomplete: [Getter/Setter],
onautocompleteerror: [Getter/Setter],
oncancel: [Getter/Setter],
oncanplay: [Getter/Setter],
oncanplaythrough: [Getter/Setter],
onchange: [Getter/Setter],
onclick: [Getter/Setter],
onclose: [Getter/Setter],
oncontextmenu: [Getter/Setter],
oncuechange: [Getter/Setter],
ondblclick: [Getter/Setter],
ondrag: [Getter/Setter],
ondragend: [Getter/Setter],
ondragenter: [Getter/Setter],
ondragexit: [Getter/Setter],
ondragleave: [Getter/Setter],
ondragover: [Getter/Setter],
ondragstart: [Getter/Setter],
ondrop: [Getter/Setter],
ondurationchange: [Getter/Setter],
onemptied: [Getter/Setter],
onended: [Getter/Setter],
oninput: [Getter/Setter],
oninvalid: [Getter/Setter],
onkeydown: [Getter/Setter],
onkeypress: [Getter/Setter],
onkeyup: [Getter/Setter],
onloadeddata: [Getter/Setter],
onloadedmetadata: [Getter/Setter],
onloadstart: [Getter/Setter],
onmousedown: [Getter/Setter],
onmouseenter: [Getter/Setter],
onmouseleave: [Getter/Setter],
onmousemove: [Getter/Setter],
onmouseout: [Getter/Setter],
onmouseover: [Getter/Setter],
onmouseup: [Getter/Setter],
onwheel: [Getter/Setter],
onpause: [Getter/Setter],
onplay: [Getter/Setter],
onplaying: [Getter/Setter],
onprogress: [Getter/Setter],
onratechange: [Getter/Setter],
onreset: [Getter/Setter],
onsecuritypolicyviolation: [Getter/Setter],
onseeked: [Getter/Setter],
onseeking: [Getter/Setter],
onselect: [Getter/Setter],
onsort: [Getter/Setter],
onstalled: [Getter/Setter],
onsubmit: [Getter/Setter],
onsuspend: [Getter/Setter],
ontimeupdate: [Getter/Setter],
ontoggle: [Getter/Setter],
onvolumechange: [Getter/Setter],
onwaiting: [Getter/Setter],
_registeredHandlers: Set {},
_eventHandlers: [Object: null prototype] {},
_resourceLoader: [ResourceLoader],
_globalProxy: [Circular],
_document: [Document],
_sessionHistory: [SessionHistory],
_virtualConsole: [VirtualConsole],
_runScripts: undefined,
_top: [Circular],
_parent: [Circular],
_frameElement: null,
_length: 0,
_pretendToBeVisual: false,
_storageQuota: 5000000,
_commonForOrigin: [Object],
_currentOriginData: [Object],
_localStorage: Storage {},
_sessionStorage: Storage {},
length: [Getter],
window: [Getter],
frameElement: [Getter],
frames: [Getter],
self: [Getter],
parent: [Getter],
top: [Getter],
document: [Getter],
external: [Getter],
location: [Getter],
history: [Getter],
navigator: [Getter],
locationbar: [Getter],
menubar: [Getter],
personalbar: [Getter],
scrollbars: [Getter],
statusbar: [Getter],
toolbar: [Getter],
performance: [Getter],
screen: [Getter],
localStorage: [Getter],
sessionStorage: [Getter],
addEventListener: [Function: bound addEventListener],
removeEventListener: [Function: bound removeEventListener],
dispatchEvent: [Function: bound dispatchEvent],
setTimeout: [Function],
setInterval: [Function],
clearInterval: [Function: bound stopTimer],
clearTimeout: [Function: bound stopTimer],
__stopAllTimers: [Function],
postMessage: [Function],
atob: [Function],
btoa: [Function],
FileReader: [Function],
WebSocket: [Function],
AbortSignal: [Function: AbortSignal],
AbortController: [Function: AbortController],
XMLHttpRequest: [Function],
ArrayBuffer: [Function: ArrayBuffer],
Int8Array: [Function: Int8Array],
Uint8Array: [Function: Uint8Array],
Uint8ClampedArray: [Function: Uint8ClampedArray],
Int16Array: [Function: Int16Array],
Uint16Array: [Function: Uint16Array],
Int32Array: [Function: Int32Array],
Uint32Array: [Function: Uint32Array],
Float32Array: [Function: Float32Array],
Float64Array: [Function: Float64Array],
stop: [Function],
close: [Function],
getComputedStyle: [Function],
captureEvents: [Function],
releaseEvents: [Function],
console: [Object],
name: '',
status: '',
devicePixelRatio: 1,
innerWidth: 1024,
innerHeight: 768,
outerWidth: 1024,
outerHeight: 768,
pageXOffset: 0,
pageYOffset: 0,
screenX: 0,
screenLeft: 0,
screenY: 0,
screenTop: 0,
scrollX: 0,
scrollY: 0,
alert: [Function],
blur: [Function],
confirm: [Function],
focus: [Function],
moveBy: [Function],
moveTo: [Function],
open: [Function],
print: [Function],
prompt: [Function],
resizeBy: [Function],
resizeTo: [Function],
scroll: [Function],
scrollBy: [Function],
scrollTo: [Function],
[Symbol(named property tracker)]: [NamedPropertiesTracker] },
_documentElement:
HTMLHtmlElementImpl {
_eventListeners: [Object: null prototype] {},
_ownerDocument: [Circular],
_childNodesList: null,
_childrenList: null,
_version: 4,
_memoizedQueries: {},
_registeredObserverList: [],
_slotableName: '',
nodeType: 1,
scrollTop: 0,
scrollLeft: 0,
_namespaceURI: 'http://www.w3.org/1999/xhtml',
_prefix: null,
_localName: 'html',
_shadowRoot: null,
_attributeList: [],
_attributesByNameMap: Map {},
_attributes: [NamedNodeMapImpl],
_tabIndex: 0,
_dataset: [DOMStringMapImpl],
_settingCssText: false,
_style: [CSSStyleDeclaration],
_registeredHandlers: Set {},
_eventHandlers: [Object: null prototype] {},
_clickInProgress: false,
_hasActivationBehavior: false,
_attached: true,
[Symbol(DOM SymbolTree)]: [SymbolTreeNode],
[Symbol(wrapper)]: [HTMLHtmlElement] },
_ids: [Object: null prototype] {},
_attached: true,
_currentScript: null,
_pageShowingFlag: true,
_cookieJar: CookieJar { enableLooseMode: true, store: { idx: {} } },
_parseOptions: { sourceCodeLocationInfo: false },
_scriptingDisabled: undefined,
contentType: 'text/html',
_encoding: 'UTF-8',
_URL:
{ scheme: 'about',
username: '',
password: '',
host: null,
port: null,
path: [Array],
query: null,
fragment: null,
cannotBeABaseURL: true },
origin: 'null',
_location:
LocationImpl {
_relevantDocument: [Circular],
url: null,
[Symbol(wrapper)]: [Location] },
_history:
HistoryImpl {
_window: [Window],
_document: [Circular],
_actAsIfLocationReloadCalled: [Function: actAsIfLocationReloadCalled],
_state: null,
[Symbol(wrapper)]: History {} },
_workingNodeIterators: [],
_workingNodeIteratorsMax: 10,
_referrer: '',
_lastModified: '01/02/2020 11:14:14',
_asyncQueue: AsyncResourceQueue { items: Set {}, dependentItems: Set {} },
_queue:
ResourceQueue { paused: false, _asyncQueue: [AsyncResourceQueue], tail: null },
_deferQueue: ResourceQueue { paused: true, _asyncQueue: undefined },
_requestManager: RequestManager { openedRequests: [] },
_currentDocumentReadiness: 'complete',
_lastFocusedElement: null,
_resourceLoader:
PerDocumentResourceLoader {
_document: [Circular],
_defaultEncoding: 'UTF-8',
_resourceLoader: [ResourceLoader],
_requestManager: [RequestManager],
_queue: [ResourceQueue],
_deferQueue: [ResourceQueue],
_asyncQueue: [AsyncResourceQueue] },
_latestEntry: null,
_mode: 'no-quirks',
[Symbol(DOM SymbolTree)]:
SymbolTreeNode {
parent: null,
previousSibling: null,
nextSibling: null,
firstChild: [DocumentTypeImpl],
lastChild: [HTMLHtmlElementImpl],
childrenVersion: 2,
childIndexCachedUpTo: null,
cachedIndex: -1,
cachedIndexVersion: NaN },
[Symbol(wrapper)]:
Document {
location: [Getter/Setter],
[Symbol(SameObject caches)]: [Object],
[Symbol(DOM SymbolTree)]: [SymbolTreeNode] } },
_childNodesList: null,
_childrenList: null,
_version: 0,
_memoizedQueries: {},
_registeredObserverList: [],
_slotableName: '',
nodeType: 1,
scrollTop: 0,
scrollLeft: 0,
_namespaceURI: 'http://www.w3.org/1999/xhtml',
_prefix: null,
_localName: 'img',
_shadowRoot: null,
_attributeList: [],
_attributesByNameMap: Map {},
_attributes:
NamedNodeMapImpl { _element: [Circular], [Symbol(wrapper)]: NamedNodeMap {} },
_tabIndex: 0,
_dataset:
DOMStringMapImpl { _element: [Circular], [Symbol(wrapper)]: DOMStringMap {} },
_settingCssText: false,
_style:
CSSStyleDeclaration {
_values: {},
_importants: {},
_length: 0,
_onChange: [Function] },
_registeredHandlers: Set {},
_eventHandlers: [Object: null prototype] {},
_clickInProgress: false,
_hasActivationBehavior: false,
[Symbol(DOM SymbolTree)]:
SymbolTreeNode {
parent: null,
previousSibling: null,
nextSibling: null,
firstChild: null,
lastChild: null,
childrenVersion: 0,
childIndexCachedUpTo: null,
cachedIndex: -1,
cachedIndexVersion: NaN },
[Symbol(wrapper)]: HTMLImageElement {} }
Well to me it seems that you do not have node-canvas installed. Are you sure you have node-canvas correctly installed? can you render something on node?
@asturur, looks like node-canvas works fine on my machine: just ran a couple of examples from https://github.com/Automattic/node-canvas/tree/master/examples and all render into files just fine.
Also tried fabric.util.getNodeCanvas(fabric.util.createImage())
both in Mac and Ubuntu (following the installation process of node-canvas from https://www.npmjs.com/package/canvas), but still, it's been returning undefined
ok i ll try to help. first thing i do i ll create an index.js to run on my machine. Maybe something is broken.
ok so the point is this.
JSDOM will instantiate a proper node-canvas backed implementation only when some atteributes are changed.
In the case of the Canvas, this happens very easily, for the Image you have to change the SRC first.
I have no clean solution for now that does not involve copying the JSDOM implementation code and run it arbitrarly when you use the getNodeCanvas
utils.
for now i could get it work doing by setting a non usefull src property to the image. This will make mine impl.onload function run twice tho.
const { fabric } = require('fabric');
const { createWriteStream, readFileSync } = require('fs')
const imgEl2 = new fabric.util.createImage();
const out2 = createWriteStream(`${__dirname}/output2.png`);
const fileBuffer = readFileSync(`${__dirname}/test.jpg`);
// trigger a load.
imgEl2.src = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==`;
const impl = fabric.util.getNodeCanvas(imgEl2);
impl.onload = function() {
console.log('loaded2', imgEl2.src);
const canvas = new fabric.StaticCanvas(null, { width: 300, height: 300 });
const fabricImage = new fabric.Image(imgEl2);
canvas.add(fabricImage);
canvas.renderAll();
var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
out2.write(chunk);
});
}
impl.src = fileBuffer;
i label it as possible feature. Is comfortable to use, i m not sure if we can solve it entirely from outside.
Thanks a lot for all the help @asturur!
@asturur one more question: could you please explain why the line const fabricImage = new fabric.Image(imgEl2);
returns first the following (from fileBuffer
???):
klass {
filters: [],
cacheKey: 'texture0',
_element: HTMLImageElement {},
_originalElement: HTMLImageElement {},
width: 225,
height: 245 }
and then this:
klass {
filters: [],
cacheKey: 'texture1',
_element: HTMLImageElement {},
_originalElement: HTMLImageElement {},
width: 1,
height: 1 }
?
I understand onload
is called twice, but not sure why fabric.Image(imgEl2)
returns in that order. Is impl.src = fileBuffer;
being read first 😕 ?
imgEl2.src has a fetcher from jsdom that is async somehow, assigning a buffer to the implementation of jsdom is ready immediately.
Is there a way to build a Fabric instance from Buffer object, for example, from the following buffer:
<Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 48 89 95 97 ... >
. I'm passing a buffer (fetched from S3 bucket) from another service/application to my current application where I do image manipulations. There's this APIfromObject(object, callback)
(http://fabricjs.com/docs/fabric.Image.html), but passing the above buffer does not seem to be doing job. Anybody knows how to do it?