Skip to content

Latest commit

 

History

History
157 lines (112 loc) · 4.99 KB

die-cut.md

File metadata and controls

157 lines (112 loc) · 4.99 KB

Die Cut

Copyright 2016 Moddable Tech, Inc.
Revised: November 22, 2016

Introduction

To get animations on a screen connected to a microcontroller by a serial interface (SPI), the game is to minimize the number of pixels that change from frame to frame.

FYI, here is what is happening at every frame when changes in the appearance or the layout invalidate and update the screen:

  • The dirty region accumulates the invalidations.
  • The containment hierarchy is traversed once to build the command list that will update the screen.
  • The dirty region and the command list are decomposed into rectangles and display lists.
  • Rectangles and display lists are processed to send blocks of pixels to the screen.

The die object is a layout object that allows animations and transitions to “die cut” contents with a region. Thanks to regions operations, the die object minimizes the areas to invalidate and to update. It can give the illusion of full screen animations while few pixels are in fact changing.

Examples

Let us begin with a static example:

let TestContainer = Container.template($ => ({
	left:0, right:0, top:0, bottom:0, skin:blueSkin,
	contents: [
		Die($, {
			left:0, right:0, top:0, bottom:0,
			Behavior: class extends Behavior {
				onDisplaying(die) {
					let w = die.width, h = die.height;
					die.empty()
						.or(10, 10, 40, 40)
						.or(w - 50, 10, 40, 40)
						.or(w - 50, h - 50, 40, 40)
						.or(10, h - 50, 40, 40)
						.xor(30, 30, w - 60, h - 60)
						.sub(70, 70, w - 140, h - 140)
						.cut();
				}
			},
			contents: [
				Content($, { left:0, right:0, top:0, bottom:0, skin:whiteSkin,
			]
		}),
	]
}));

The empty, or, xor and sub methods are chainable operations to build the region. The cut method changes the region.

If you add the TestContainer to an application, here is what it will look like:

But of course the die object is mostly interesting to build animations and transitions. You will find examples in the Piu libraries: WipeTransition and CombTransition.

Let us build a "venitian blind" transition:

class VenitianBlindTransition extends Transition {
	constructor(duration) {
		super(duration);
	}
	onBegin(container, former, current) {
		container.add(current);
		this.container = container;
		this.die = new Die(null, {});
		this.die.attach(current);
	}
	onEnd(container, former, current) {
		this.die.detach();
		container.remove(former);
	}
	onStep(fraction) {
		let die = this.die;
		die.empty();
		let width = die.width;
		let height = die.height;
		let y = 0;
		let step = height >> 3;
		let delta = Math.round(fraction * step);
		for (let i = 0; i < 8; i++) {
			die.or(0, y, width, delta);
			y += step;
		}
		die.cut();
	}
}

The attach and detach methods allow to temporarily insert a die object in the containment hierarchy. At every step of the transition the region changes to progressively close the "venitian blind".

Reference

The die object is a layout object that allows to “die cut” its contents with a region. The die object maintains two regions:

  • the work region that the available operations build,
  • the clip region that clips the contents of the die object

Both regions are initially empty.

Prototype Description

Prototype inherits from Layout.prototype.

Die.prototype.and(x, y, width, height)

x, y, width, height a local rectangle, in pixels

Intersect the rectangle with the work region. Return this.

Die.prototype.attach(content)

content the content object to attach

Bind the die object to the content hierarchy by replacing the specified content object in the content's container with this die object and adding the content object to this die object.

Die.prototype.cut()

Copy the work region into the current region. Invalidate only the difference between the work and the clip regions.

Die.prototype.empty()

Empty the work region. Return this

Die.prototype.detach()

Unbind this die object from the content hierarchy by removing the first content object from this die object and replacing this die object in its container with the removed content object.

Die.prototype.fill()

Set the work region to the bounds of this die object. Return this

Die.prototype.or(x, y, width, height)

x, y, width, height a local rectangle, in pixels

Inclusively union the rectangle with the work region. Return this.

Die.prototype.set(x, y, width, height)

x, y, width, height a local rectangle, in pixels

Set the work region to the rectangle. Return this.

Die.prototype.sub(x, y, width, height)

x, y, width, height a local rectangle, in pixels

Subtract the rectangle from the work region. Return this.

Die.prototype.xor(x, y, width, height)

x, y, width, height a local rectangle, in pixels

Exclusively union the work region with the rectangle. Return this.