Skip to content
This repository was archived by the owner on Jul 30, 2018. It is now read-only.
This repository was archived by the owner on Jul 30, 2018. It is now read-only.

Web Animations API #657

Closed
Closed
@tomdye

Description

@tomdye

This issue supersedes: #70

Enhancement

Summary

In order to provide functional web animations for our widgets should provide a way to specify animations on the vNode level without needed to expose the underlying HTMLElements to the user.

Animations should be able to be controlled via changes in widget properties / state and should be removable. Animation effects should have capability to be provided as functions such that they can access widget properties and meta to utilise dimensions in the values provided.

A polyfill will be required for browsers that do not fully support the Web Animations API.

This functionality can be achieved via a mixin which uses meta to access the underlying HTMLElements and the afterRender decorator to find VNodes with animation properties.

Animations Interface

interface AnimationProperties {
	id: string;
	effects: any[];
	controls?: AnimationControls;
	timing?: AnimationTimingProperties;
}

interface AnimationControls {
	play?: boolean;
	onFinish?: () => void;
	reverse?: boolean;
	cancel?: boolean;
	finish?: boolean;
	playbackRate?: number;
	startTime?: number;
	currentTime?: number;
}

interface AnimationTimingProperties {
	duration?: number;
	delay?: number;
	direction?: string;
	easing?: string;
	endDelay?: number;
	fill?: string;
	iterations?: number;
	iterationStart?: number;
}

Example usage

_animateOpen() {
	const { size, scroll } = this.meta(Dimensions).get('content');
	const dim = this.meta(Dimensions).get('content');

	return [
		{ height: `${size.height}px` },
		{ height: `${scroll.height}px` }
	];
}

render() {
	const timing = {
		duration: 300,
		fill: 'forwards',
		easing: 'ease-in-out'
	};

	return v('div', {
		key: 'content',
		classes: this.classes(css.content),
		animate: [ {
			id: 'down',
			effects: this._animateOpen.bind(this),
			timing,
			controls: {
				play: true
			}
		}]
	}, [ 'Content' ]);
}

Issues

VNode typing

One of the problems presented by this approach in that we are currently unable to type the properties of a VNode based on the mixins that have been applied to it's containing widget. The only way to do this currently is by adding to the underlying VirtualDomProperties as we do for the Themeable properties, but this is far from ideal.

Possible approaches to this include using a higher order function to wrap around the call to v, animate(v('div', {}), animationProperties) or exporting a decorated v on the widget instance that includes the animation properties in its typings.

Meta get node timing #662

Currently the requireNode callback in meta fires as soon as the requested node is available. This can happen before parent elements / widgets have had their properties processed and as such any styles applied to them will not yet have impacted the required node. When working with animations and accessing Dimensions via meta this is highly problematic.
We should look into implementing an events system that can allow callers to ensure specific nodes have been processed before dimensions etc are requested.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions