The render management system tells the renderer when to rerender the blocks. It makes sure that when a block is modified (e.g. field values are set, or inputs are added) the shape of the block gets updated to match.
When to care
You need to interact with this system if you are:
- Adding methods to Blockly that modify the shape of the block.
- Adding methods to Blockly that rely on updated size or positioning information about a block.
How it works
Automatically queue. Whenever a block gets modified, Blockly "queues" a render for that block. Some examples of modifications that queue a render are:
- Setting a field's value
- Adding or removing an input
- Connecting or disconnecting a child block
Create a set. When a block gets queued, the render management system adds it, and all of its parent blocks, to a set of blocks that need to be rerendered.
Request a callback. Then the render management system requests a callback using
requestAnimationFrame
. This callback gets called by the browser right before the current frame is drawn.Rerender the set (as a tree). When the
requestAnimationFrame
callback gets called, the render management system renders every block in the set from leaf blocks to root blocks. This makes sure that child blocks have accurate size information before their parent blocks are rendered so the parent blocks can stretch around their children.
Why it works how it does
Waiting to rerender blocks until right before the current frame is drawn allows the render management system to deduplicate rendering requests. If blocks were always rendered immediately, the same block might unnecessarily be rendered multiple times in a row. Instead the render requests are batched, and each changed block only gets drawn once at the end of the frame, after its state is finalized. Deduping rendering operations makes Blockly much more efficient.
For example, inserting one block between two others queues 11 renders, but only 3 actually occur (one for each block). That's a 3.6x performance boost.
How to use it
You shouldn't usually have to care about the render management system, because it works automatically when you modify a block. But there are a few cases where you have to interact with it directly.
Queue renders
If you are adding a new method to Blockly that should update the shape of a
block, you need to call BlockSvg.prototype.queueRender
to queue rendering the
block.
Wait for renders to finish
If you are adding a new method to Blockly that requires having updated sizing or
positioning information about a block, you should await the
renderManagement.finishQueuedRenders()
promise. This promise resolves after
any queued renders are completed, or immediately if there are no queued renders.
import * as renderManagement from './renderManagement.js';
function async myNewMethod() {
block.somethingThatModifiesTheShape();
// Await the promise.
await renderManagement.finishQueuedRenders();
myThingThatReliesOnPositioningInfo();
}
Trigger queued renders immediately
If you are adding a new method to Blockly that requires having updated sizing or
positioning information about a block, and you cannot wait until the next
frame for any renders to complete, you can call
renderManagement.triggerQueuedRenders
to force any queued renders to happen
immediately.
import * as renderManagement from './renderManagement.js';
function async myNewMethod() {
block.somethingThatModifiesTheShape();
// Trigger an immediate render.
renderManagement.triggerQueuedRenders();
myThingThatReliesOnPositioningInfo();
}
In general, you don't want to do this because it's less performant. It's only necessary in cases where a delay causes a bad user experience. For example, insertion markers need positioning information, and it's important that insertion markers give users immediate feedback, so they trigger an immediate render.
There are also a few places in core where it triggers immediate renders for backwards compatibility reasons. These are planned to be removed in v11.