In this example, we will show you how to use the CreativeEditor SDK’s CreativeEngine to modify scenes layout through the block API.
Layout of Blocks#
The CreativeEngine supports three different modes for positioning blocks. These can be set for each block and both coordinates independently:
'Absolute': the position value is interpreted in the scene’s current design unit.'Percent': the position value is interpreted as percentage of the block’s parent’s size, where 1.0 means 100%.'Auto': the position is automatically determined.
Likewise there are also three different modes for controlling a block’s size. Again both dimensions can be set independently:
'Absolute': the size value is interpreted in the scene’s current design unit.'Percent': the size value is interpreted as percentage of the block’s parent’s size, where 1.0 means 100%.'Auto': the block’s size is automatically determined by the size of the block’s content.
Positioning#
getPositionX(id: DesignBlockId): numberQuery a block’s x position.
id: The block to query.- Returns The value of the x position.
getPositionY(id: DesignBlockId): numberQuery a block’s y position.
id: The block to query.- Returns The value of the y position.
getPositionXMode(id: DesignBlockId): PositionModeQuery a block’s mode for its x position.
id: The block to query.- Returns The current mode for the x position: absolute, percent or undefined.
getPositionYMode(id: DesignBlockId): PositionModeQuery a block’s mode for its y position.
id: The block to query.- Returns The current mode for the y position: absolute, percent or undefined.
setPositionX(id: DesignBlockId, value: number): voidUpdate a block’s x position. The position refers to the block’s local space, relative to its parent with the origin at the top left. Required scope: ‘layer/move’
id: The block to update.value: The value of the x position.
setPositionY(id: DesignBlockId, value: number): voidUpdate a block’s y position. The position refers to the block’s local space, relative to its parent with the origin at the top left. Required scope: ‘layer/move’
id: The block to update.value: The value of the y position.
setPositionXMode(id: DesignBlockId, mode: PositionMode): voidSet a block’s mode for its x position. Required scope: ‘layer/move’
id: The block to update.mode: The x position mode: absolute, percent or undefined.
setPositionYMode(id: DesignBlockId, mode: PositionMode): voidSet a block’s mode for its y position. Required scope: ‘layer/move’
id: The block to update.mode: The y position mode: absolute, percent or undefined.
type PositionMode = 'Absolute' | 'Percent' | 'Auto';- Absolute: Position in absolute design units. - Percent: Position in relation to the block’s parent’s size in percent, where 1.0 means 100%. - Auto: Position is automatically determined
Size#
getWidth(id: DesignBlockId): numberQuery a block’s width.
id: The block to query.- Returns The value of the block’s width.
getWidthMode(id: DesignBlockId): SizeModeQuery a block’s mode for its width.
id: The block to query.- Returns The current mode for the width: absolute, percent or auto.
getHeight(id: DesignBlockId): numberQuery a block’s height.
id: The block to query.- Returns The value of the block’s height.
getHeightMode(id: DesignBlockId): SizeModeQuery a block’s mode for its height.
id: The block to query.- Returns The current mode for the height: absolute, percent or auto.
setWidth(id: DesignBlockId, value: number, maintainCrop?: boolean): voidUpdate a block’s width and optionally maintain the crop. If the crop is maintained, the crop values will be automatically adjusted. The content fill mode Cover is only kept if the features/transformEditsRetainCoverMode setting is enabled, otherwise it will change to Crop. Required scope: ‘layer/resize’
id: The block to update.value: The new width of the block.maintainCrop: Whether or not the crop values, if available, should be automatically adjusted.
setWidthMode(id: DesignBlockId, mode: SizeMode): voidSet a block’s mode for its width. Required scope: ‘layer/resize’
id: The block to update.mode: The width mode: Absolute, Percent or Auto.
setHeight(id: DesignBlockId, value: number, maintainCrop?: boolean): voidUpdate a block’s height and optionally maintain the crop. If the crop is maintained, the crop values will be automatically adjusted. The content fill mode Cover is only kept if the features/transformEditsRetainCoverMode setting is enabled, otherwise it will change to Crop. Required scope: ‘layer/resize’
id: The block to update.value: The new height of the block.maintainCrop: Whether or not the crop values, if available, should be automatically adjusted.
setHeightMode(id: DesignBlockId, mode: SizeMode): voidSet a block’s mode for its height. Required scope: ‘layer/resize’
id: The block to update.mode: The height mode: Absolute, Percent or Auto.
type SizeMode = 'Absolute' | 'Percent' | 'Auto';- Absolute: Size in absolute design units. - Percent: Size in relation to the block’s parent’s size in percent, where 1.0 means 100%. - Auto: Size is automatically determined
Layers#
setAlwaysOnTop(id: DesignBlockId, enabled: boolean): voidUpdate the block’s always-on-top property. If true, this blocks’s global sorting order is automatically adjusted to be higher than all other siblings without this property. If more than one block is set to be always-on-top, the child order decides which is on top.
id: the block to update.enabled: whether the block shall be always-on-top.
isAlwaysOnTop(id: DesignBlockId): booleanQuery a block’s always-on-top property.
id: the block to query.- Returns true if the block is set to be always-on-top, false otherwise.
setAlwaysOnBottom(id: DesignBlockId, enabled: boolean): voidUpdate the block’s always-on-bottom property. If true, this blocks’s global sorting order is automatically adjusted to be lower than all other siblings without this property. If more than one block is set to be always-on-bottom, the child order decides which is on bottom.
id: the block to update.enabled: whether the block shall always be below its siblings.
isAlwaysOnBottom(id: DesignBlockId): booleanQuery a block’s always-on-bottom property.
id: the block to query.- Returns true if the block is set to be always-on-bottom, false otherwise.
bringToFront(id: DesignBlockId): voidUpdates the sorting order of this block and all of its manually created siblings so that the given block has the highest sorting order. If the block is parented to a track, it is first moved up in the hierarchy.
id: The id of the block to be given the highest sorting order among its siblings.
sendToBack(id: DesignBlockId): voidUpdates the sorting order of this block and all of its manually created siblings so that the given block has the lowest sorting order. If the block is parented to a track, it is first moved up in the hierarchy.
id: The id of the block to be given the lowest sorting order among its siblings.
bringForward(id: DesignBlockId): voidUpdates the sorting order of this block and all of its superjacent siblings so that the given block has a higher sorting order than the next superjacent sibling. If the block is parented to a track, it is first moved up in the hierarchy. Empty tracks and empty groups are passed by.
id: The id of the block to be given a higher sorting than the next superjacent sibling.
sendBackward(id: DesignBlockId): voidUpdates the sorting order of this block and all of its manually created and subjacent siblings so that the given block will have a lower sorting order than the next subjacent sibling. If the block is parented to a track, it is first moved up in the hierarchy. Empty tracks and empty groups are passed by.
id: The id of the block to be given a lower sorting order than the next subjacent sibling.
Rotation#
getRotation(id: DesignBlockId): numberQuery a block’s rotation in radians.
id: The block to query.- Returns The block’s rotation around its center in radians.
setRotation(id: DesignBlockId, radians: number): voidUpdate a block’s rotation. Required scope: ‘layer/rotate’
id: The block to update.radians: The new rotation in radians. Rotation is applied around the block’s center.
Flipping#
getFlipHorizontal(id: DesignBlockId): booleanQuery a block’s horizontal flip state.
id: The block to query.- Returns A boolean indicating for whether the block is flipped in the queried direction
getFlipVertical(id: DesignBlockId): booleanQuery a block’s vertical flip state.
id: The block to query.- Returns A boolean indicating for whether the block is flipped in the queried direction
setFlipHorizontal(id: DesignBlockId, flip: boolean): voidUpdate a block’s horizontal flip. Required scope: ‘layer/flip’
id: The block to update.flip: If the flip should be enabled.
setFlipVertical(id: DesignBlockId, flip: boolean): voidUpdate a block’s vertical flip. Required scope: ‘layer/flip’
id: The block to update.flip: If the flip should be enabled.
Scaling#
scale(id: DesignBlockId, scale: number, anchorX?: number, anchorY?: number): voidScales the block and all of its children proportionally around the specified relative anchor point. This updates the position, size and style properties (e.g. stroke width) of the block and its children. Required scope: ‘layer/resize’
id: The block that should be scaled.scale: The scale factor to be applied to the current properties of the block.anchorX: The relative position along the width of the block around which the scaling should occur. (0 = left edge, 0.5 = center, 1 = right edge)anchorY: The relative position along the height of the block around which the scaling should occur. (0 = top edge, 0.5 = center, 1 = bottom edge)
Fill a Block’s Parent#
fillParent(id: DesignBlockId): voidResize and position a block to entirely fill its parent block. The crop values of the block, except for the flip and crop rotation, are reset if it can be cropped. If the size of the block’s fill is unknown, the content fill mode is changed from Crop to Cover to prevent invalid crop values. Required scope: ‘layer/move’ - ‘layer/resize’
id: The block that should fill its parent.
Resize Blocks Content-aware#
resizeContentAware(ids: DesignBlockId[], width: number, height: number): voidResize all blocks to the given size. The content of the blocks is automatically adjusted to fit the new dimensions. Required scope: ‘layer/resize’
ids: The blocks to resize.width: The new width of the blocks.height: The new height of the blocks.
Even Distribution#
Multiple blocks can be distributed horizontally or vertically within their bounding box. The blocks are moved to have the remaining space divided evenly between the blocks. Blocks without a position and blocks that are not allowed to be moved will not be distributed.
isDistributable(ids: DesignBlockId[]): booleanConfirms that a given set of blocks can be distributed.
ids: An array of block ids.- Returns Whether the blocks can be distributed.
distributeHorizontally(ids: DesignBlockId[]): voidDistribute multiple blocks horizontally within their bounding box so that the space between them is even. Required scope: ‘layer/move’
ids: A non-empty array of block ids.
distributeVertically(ids: DesignBlockId[]): voidDistribute multiple blocks vertically within their bounding box so that the space between them is even. Required scope: ‘layer/move’
ids: A non-empty array of block ids.
Alignment#
Multiple blocks can be aligned horizontally or vertically within their bounding box. When a group is given, the elements within the group are aligned. If a single block is given, it gets aligned within its parent. Blocks without a position and blocks that are not allowed to be moved will not be aligned.
isAlignable(ids: DesignBlockId[]): booleanConfirms that a given set of blocks can be aligned.
ids: An array of block ids.- Returns Whether the blocks can be aligned.
alignHorizontally(ids: DesignBlockId[], horizontalBlockAlignment: HorizontalBlockAlignment): voidAlign multiple blocks horizontally within their bounding box or a single block to its parent. Required scope: ‘layer/move’
ids: A non-empty array of block ids.alignment: How they should be aligned: left, right, or center
alignVertically(ids: DesignBlockId[], verticalBlockAlignment: VerticalBlockAlignment): voidAlign multiple blocks vertically within their bounding box or a single block to its parent. Required scope: ‘layer/move’
ids: A non-empty array of block ids.alignment: How they should be aligned: top, bottom, or center
Computed Dimensions#
getFrameX(id: DesignBlockId): numberGet a block’s layout position on the x-axis. The position is only available after an internal update loop which only occurs if the features/implicitUpdatesEnabled setting is set.
id: The block to query.- Returns The layout position on the x-axis.
getFrameY(id: DesignBlockId): numberGet a block’s layout position on the y-axis. The position is only available after an internal update loop which only occurs if the features/implicitUpdatesEnabled setting is set.
id: The block to query.- Returns The layout position on the y-axis.
getFrameWidth(id: DesignBlockId): numberGet a block’s layout width. The width is only available after an internal update loop which only occurs if the features/implicitUpdatesEnabled setting is set.
id: The block to query.- Returns The layout width.
getFrameHeight(id: DesignBlockId): numberGet a block’s layout height. The height is only available after an internal update loop which only occurs if the features/implicitUpdatesEnabled setting is set.
id: The block to query.- Returns The layout height.
getGlobalBoundingBoxX(id: DesignBlockId): numberGet the x position of the block’s axis-aligned bounding box in the scene’s global coordinate space. The scene’s global coordinate space has its origin at the top left.
id: The block whose bounding box should be calculated.- Returns float The x coordinate of the position of the axis-aligned bounding box.
getGlobalBoundingBoxY(id: DesignBlockId): numberGet the y position of the block’s axis-aligned bounding box in the scene’s global coordinate space. The scene’s global coordinate space has its origin at the top left.
id: The block whose bounding box should be calculated.- Returns float The y coordinate of the position of the axis-aligned bounding box.
getGlobalBoundingBoxWidth(id: DesignBlockId): numberGet the width of the block’s axis-aligned bounding box in the scene’s global coordinate space. The scene’s global coordinate space has its origin at the top left.
id: The block whose bounding box should be calculated.- Returns float The width of the axis-aligned bounding box.
getGlobalBoundingBoxHeight(id: DesignBlockId): numberGet the height of the block’s axis-aligned bounding box in the scene’s global coordinate space. The scene’s global coordinate space has its origin at the top left.
id: The block whose bounding box should be calculated.- Returns float The height of the axis-aligned bounding box.
getScreenSpaceBoundingBoxXYWH(ids: DesignBlockId[]): XYWHGet the position and size of the axis-aligned bounding box for the given blocks in screen space.
ids: The block to query.- Returns The position and size of the bounding box.
Transform Locking#
You can lock the transform of a block to prevent changes to any of its transformations. That is the block’s position, rotation, scale, and sizing.
isTransformLocked(id: DesignBlockId): booleanQuery a block’s transform locked state. If true, the block’s transform can’t be changed.
id: The block to query.- Returns True if transform locked, false otherwise.
setTransformLocked(id: DesignBlockId, locked: boolean): voidUpdate a block’s transform locked state.
id: The block to update.locked: Whether the block’s transform should be locked.
Full Code#
Here’s the full code:
const x = engine.block.getPositionX(block);const xMode = engine.block.getPositionXMode(block);const y = engine.block.getPositionY(block);const yMode = engine.block.getPositionYMode(block);engine.block.setPositionX(block, 0.25);engine.block.setPositionXMode(block, 'Percent');engine.block.setPositionY(block, 0.25);engine.block.setPositionYMode(block, 'Percent');
const rad = engine.block.getRotation(block);engine.block.setRotation(block, Math.PI / 2);
const flipHorizontal = engine.block.getFlipHorizontal(block);const flipVertical = engine.block.getFlipVertical(block);engine.block.setFlipHorizontal(block, true);engine.block.setFlipVertical(block, false);
const width = engine.block.getWidth(block);const widthMode = engine.block.getWidthMode(block);const height = engine.block.getHeight(block);const heightMode = engine.block.getHeightMode(block);engine.block.setWidth(block, 0.5);engine.block.setWidth(block, 2.5, true);engine.block.setWidthMode(block, 'Percent');engine.block.setHeight(block, 0.5);engine.block.setHeight(block, 2.5, true);engine.block.setHeightMode(block, 'Percent');const frameX = engine.block.getFrameX(block);const frameY = engine.block.getFrameY(block);const frameWidth = engine.block.getFrameWidth(block);const frameHeight = engine.block.getFrameHeight(block);
engine.block.setAlwaysOnTop(block, false)val isAlwaysOnTop = engine.block.isAlwaysOnTop(block)engine.block.setAlwaysOnBottom(block, false)val isAlwaysOnBottom = engine.block.isAlwaysOnBottom(block)engine.block.bringToFront(block)engine.block.sendToBack(block)engine.block.bringForward(block)engine.block.sendBackward(block)
const globalX = engine.block.getGlobalBoundingBoxX(block);const globalY = engine.block.getGlobalBoundingBoxY(block);const globalWidth = engine.block.getGlobalBoundingBoxWidth(block);const globalHeight = engine.block.getGlobalBoundingBoxHeight(block);const screenSpaceRect = engine.block.getScreenSpaceBoundingBoxXYWH([block]);
engine.block.scale(block, 2.0, 0.5, 0.5);
engine.block.fillParent(block);
const pages = engine.scene.getPages();engine.block.resizeContentAware(pages, width: 100.0, 100.0);
// Create blocks and append to pageconst member1 = engine.block.create('graphic');const member2 = engine.block.create('graphic');engine.block.appendChild(page, member1);engine.block.appendChild(page, member2);const distributable = engine.block.isDistributable([member1, member2]);if (distributable) { engine.block.distributeHorizontally([member1, member2], "Left"); engine.block.distributeVertically([member1, member2], "Top");}const alignable = engine.block.isAlignable([member1, member2]);if (alignable) { engine.block.alignHorizontally([member1, member2], "Left"); engine.block.alignVertically([member1, member2], "Top");}
const isTransformLocked = engine.block.isTransformLocked(block);if (!isTransformLocked) { engine.block.setTransformLocked(block, true);}