Skip to content

Combine

You can use four different boolean operations on blocks to combine them into unique shapes. These operations are:

  • 'Union': adds all the blocks’ shapes into one
  • 'Difference': removes from the bottom-most block the shapes of the other blocks overlapping with it
  • 'Intersection': keeps only the overlapping parts of all the blocks’ shapes
  • 'XOR': removes the overlapping parts of all the block’s shapes

Combining blocks allows you to create a new block with a customized shape.

Combining blocks with the union, intersection or XOR operation will result in the new block whose fill is that of the top-most block and whose shape is the result of applying the operation pair-wise on blocks from the top-most block to the bottom-most block.

Combining blocks with the difference operation will result in the new block whose fill is that of the bottom-most block and whose shape is the result of applying the operation pair-wise on blocks from the bottom-most block to the top-most block.

The combined blocks will be destroyed.

isCombinable(ids: DesignBlockId[]): boolean

Checks whether blocks could be combined. Only graphics blocks and text blocks can be combined. All blocks must have the “lifecycle/duplicate” scope enabled.

  • ids: An array of block ids.
  • Returns Whether the blocks can be combined.
combine(ids: DesignBlockId[], op: BooleanOperation): DesignBlockId

Perform a boolean operation on the given blocks. All blocks must be combinable. See isCombinable. The parent, fill and sort order of the new block is that of the prioritized block. When performing a Union, Intersection or XOR, the operation is performed pair-wise starting with the element with the highest sort order. When performing a Difference, the operation is performed pair-wise starting with the element with the lowest sort order. Required scopes: ‘lifecycle/duplicate’, ‘lifecycle/destroy’

  • ids: The blocks to combine. They will be destroyed if “lifecycle/destroy” scope is enabled.
  • op: The boolean operation to perform.
  • Returns The newly created block or an error.

Here’s the full code:

// Create blocks and append to scene
const star = engine.block.create('shapes/star');
const rect = engine.block.create('shapes/rect');
engine.block.appendChild(page, star);
engine.block.appendChild(page, rect);
// Check whether the blocks may be combined
const combinable = engine.block.isCombinable([star, rect]);
if (combinable) {
const combined = engine.block.combine([star, rect], 'Union');
}

Combining three circles together

We create three circles and arrange in a recognizable pattern. Combing them with 'Union' result in a single block with a unique shape. The result will inherit the top-most block’s fill, in this case circle3’s fill.

const circle1 = engine.block.create('graphic');
engine.block.setShape(circle1, engine.block.createShape('ellipse'));
engine.block.setFill(circle1, engine.block.createFill('color'));
engine.block.setPositionX(circle1, 30);
engine.block.setPositionY(circle1, 30);
engine.block.setWidth(circle1, 40);
engine.block.setHeight(circle1, 40);
engine.block.appendChild(page, circle1);
const circle2 = engine.block.create('graphic');
engine.block.setShape(circle2, engine.block.createShape('ellipse'));
engine.block.setFill(circle2, engine.block.createFill('color'));
engine.block.setPositionX(circle2, 80);
engine.block.setPositionY(circle2, 30);
engine.block.setWidth(circle2, 40);
engine.block.setHeight(circle2, 40);
engine.block.appendChild(page, circle2);
const circle3 = engine.block.create('graphic');
engine.block.setShape(circle3, engine.block.createShape('ellipse'));
engine.block.setFill(circle3, engine.block.createFill('color'));
engine.block.setPositionX(circle3, 50);
engine.block.setPositionY(circle3, 50);
engine.block.setWidth(circle3, 50);
engine.block.setHeight(circle3, 50);
engine.block.appendChild(page, circle3);
const union = engine.block.combine([circle1, circle2, circle3], 'Union');

To create a special effect of text punched out from an image, we create an image and a text. We ensure that the image is at the bottom as that is the base block from which we want to remove shapes. The result will be a block with the size, shape and fill of the image but with a hole in it in the shape of the removed text.

const text = engine.block.create('text');
engine.block.replaceText(text, 'Removed text');
engine.block.setPositionX(text, 10);
engine.block.setPositionY(text, 40);
engine.block.setWidth(text, 80);
engine.block.setHeight(text, 10);
engine.block.appendChild(page, text);
const image = engine.block.create('graphic');
engine.block.setShape(image, engine.block.createShape('rect'));
const imageFill = engine.block.createFill('image');
engine.block.setFill(image, imageFill);
engine.block.setPositionX(image, 0);
engine.block.setPositionY(image, 0);
engine.block.setWidth(image, 100);
engine.block.setHeight(image, 100);
engine.block.setString(
imageFill,
'fill/image/imageFileURI',
'https://img.ly/static/ubq_samples/sample_1.jpg'
);
engine.block.appendChild(page, image);
engine.block.sendToBack(image);
const difference = engine.block.combine([image, text], 'Difference');

Full Code

Here’s the full code:

import CreativeEngine from 'https://cdn.img.ly/packages/imgly/cesdk-engine/1.51.0/index.js';
const config = {
license: 'mtLT-_GJwMhE7LDnO8KKEma7qSuzWuDxiKuQcxHKmz3fjaXWY2lT3o3Z2VdL5twm',
userId: 'guides-user',
baseURL: 'https://cdn.img.ly/packages/imgly/cesdk-engine/1.51.0/assets',
};
CreativeEngine.init(config).then(async engine => {
document.getElementById('cesdk_container').append(engine.element);
const scene = engine.scene.create();
const page = engine.block.create('page');
engine.block.setWidth(page, 800);
engine.block.setHeight(page, 600);
engine.block.appendChild(scene, page);
const circle1 = engine.block.create('graphic');
engine.block.setShape(circle1, engine.block.createShape('ellipse'));
engine.block.setFill(circle1, engine.block.createFill('color'));
engine.block.setPositionX(circle1, 30);
engine.block.setPositionY(circle1, 30);
engine.block.setWidth(circle1, 40);
engine.block.setHeight(circle1, 40);
engine.block.appendChild(page, circle1);
const circle2 = engine.block.create('graphic');
engine.block.setShape(circle2, engine.block.createShape('ellipse'));
engine.block.setFill(circle2, engine.block.createFill('color'));
engine.block.setPositionX(circle2, 80);
engine.block.setPositionY(circle2, 30);
engine.block.setWidth(circle2, 40);
engine.block.setHeight(circle2, 40);
engine.block.appendChild(page, circle2);
const circle3 = engine.block.create('graphic');
engine.block.setShape(circle3, engine.block.createShape('ellipse'));
engine.block.setFill(circle3, engine.block.createFill('color'));
engine.block.setPositionX(circle3, 50);
engine.block.setPositionY(circle3, 50);
engine.block.setWidth(circle3, 50);
engine.block.setHeight(circle3, 50);
engine.block.appendChild(page, circle3);
const union = engine.block.combine([circle1, circle2, circle3], 'Union');
const text = engine.block.create('text');
engine.block.replaceText(text, 'Removed text');
engine.block.setPositionX(text, 10);
engine.block.setPositionY(text, 40);
engine.block.setWidth(text, 80);
engine.block.setHeight(text, 10);
engine.block.appendChild(page, text);
const image = engine.block.create('graphic');
engine.block.setShape(image, engine.block.createShape('rect'));
const imageFill = engine.block.createFill('image');
engine.block.setFill(image, imageFill);
engine.block.setPositionX(image, 0);
engine.block.setPositionY(image, 0);
engine.block.setWidth(image, 100);
engine.block.setHeight(image, 100);
engine.block.setString(
imageFill,
'fill/image/imageFileURI',
'https://img.ly/static/ubq_samples/sample_1.jpg',
);
engine.block.appendChild(page, image);
engine.block.sendToBack(image);
const difference = engine.block.combine([image, text], 'Difference');
});