External canvas refresh

Hi, I’m using an external canvas to draw some charts… and I need them displayed on a goJS node… so I’m using this Picture element:

                    $GO(go.Picture, {
                            alignment: go.Spot.Center,
                            stretch: go.GraphObject.Fill,
                            imageStretch: go.GraphObject.Fill,
                            background: 'transparent'
                        },
                        new go.Binding('element', '', (data: FlowStep, pict: go.Picture) => {
                            const bounds = pict.naturalBounds;
                            return data.getIconElement(bounds.width, bounds.height);
                        }),
                        new go.Binding('opacity', 'iconOpacity')
                    )

problem is… when external canvas refreshes goJS doesn’t pick it up until there is another event that would cause a visual refresh… like hovering a node, selecting etc…

also when the diagram initially loads the canvas contents is not displayed until such a refresh event happens.
that’s probably because the chart is drawn async and is not there at the time when the canvas is set on the Picture element.

I’ve seen the example with WebGL and that seems to work just fine… so… is there something I need to turn on for this to work?.. or not turn off?.. or anything that might affect/cause this behaviour in any way?

thanks,
CF

Yes, it appears that no state has changed within the Diagram, so there’s no reason to redraw.

I suppose after you have finished drawing on all of your canvases, you could call Diagram.redraw().

how come the WebGL one in examples works fine then?

I see…
The WebGL node is animated by calling myDiagram.redraw() every animation frame.

:)
wasn’t in the source code…

ok… thanks

this thing seems to be back in 2.0.6…

it used to work right until we updated to 2.0

the issue is… we use an external charting library… that renders on a canvas…
when the chart draw is done we call requestUpdate(true)…

but the charts don’t show on diagram unless you resize the canvas… :(

and I see the OpenGL sample was removed… so… how can I tell the Picture to redraw itself?

We updated the samples/canvases.html sample to be more useful to more people – since creating and showing more realistic charts is by far the most common need for putting complex content in nodes, without re-implementing everything in GoJS.

So you are sure that a Canvas element has been completely drawn at the time you call Diagram.requestUpdate, and that that Canvas element is the value of some Picture.element being shown in some Node in your Diagram?

Is there a difference in behavior if you call Diagram.redraw instead of Diagram.requestUpdate?

there is no redraw method… :(

or is it just missing from .d.ts?

oh yeah… missing from .d.ts… redraw() seems to work just fine.

Hmmm. Now I’d like to know what the situation is when you were calling Diagram.requestUpdate. At the time of that call, has an “InitialLayoutCompleted” DiagramEvent already been raised for the diagram? In other words, do all of the Nodes and Links exist in the whole diagram, and are they all laid out as expected (but those Pictures showing charts are still blank), and have the scrollbars been updated, and can the user do things such as select or scroll or whatever?

that’s complicated :D

so… when I create the diagram I do:

            this.addDiagramEventListener('InitialLayoutCompleted', () => {
                diagramListener && diagramListener();
                this.initialized = true;
            });

then, on chart I do:

                        this.chart.on('draw', () => {
                            this.step && this.step.flowDiagram && this.step.flowDiagram.initialized && this.step.flowDiagram.goDiagram && (<any>this.step.flowDiagram.goDiagram).redraw();
                        });

so… in theory… the diagram is initialized when that call is made from charts.

but the whole thing is pretty much instant from the point of view of whoever is looking at it… it all happens on load.

I’m wondering if there’s a possible problem trying to call requestUpdate during or immediately after initialization. There shouldn’t be any problem a little later, so I’m betting if you just called

this.chart.on("draw", () => setTimeout(() => this.step.flowDiagram.goDiagram.requestUpdate(true), 1))

things would work.

I did try with setTimeout(..., 1000)… didn’t help.

OK, thanks. I guess we’ll investigate this on our own, at lower priority since you have a work-around.

yup… thanks!!

@catface what chart library are you using? I’d like to reproduce this.

Using myDiagram.redraw() when the canvas draws, this seems to work OK for me. What’s different about my example?

https://codepen.io/simonsarris/pen/bZXRgX

true… redraw works… problems are:
1.redraw doesn’t show up in .d.ts
2. I was using requestUpdate
:)

I see, we’ll put redraw() in the .d.ts file, sorry about that. You’ll have to use a

(diagram as any).redraw()

style of workaround for now.

requestUpdate() only updates if there is something to update: If the Diagram DIV changed size, or a part or layout became invalid. It does not know about that state of a canvas outside the diagram, in this case your go.Picture’s element. This canvas is already fully “loaded”, rgraph just draws different pixels to it, and we do not go trying to detect something like that, so you gotta tell GoJS with a call to redraw().

That requestUpdate() worked before for this was something of a bug, it was doing too much work and should not have been.

Sorry for all the trouble.

no problem… just happy that I have a fix :)