Skip to content

Commit

Permalink
Extract LottieMorph implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
linusha committed Aug 11, 2021
1 parent 999b60c commit 0e56e3b
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 125 deletions.
2 changes: 2 additions & 0 deletions examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function treeExample () {
export function skyExample () {
const skySequence = new Sequence({ name: 'sky sequence', start: 0, duration: 500 });

/*
const stars = new LottieMorph({ fill: Color.transparent, extent: pt(200, 200), position: pt(0, 0), name: 'lottie stars', animationDataUrl: 'https://assets4.lottiefiles.com/packages/lf20_Aerz0y.json' });
skySequence.addMorph(stars);
Expand All @@ -90,6 +91,7 @@ export function skyExample () {
const starProgressAnimation = new NumberAnimation(stars, 'progress');
starProgressAnimation.addKeyframes([new Keyframe(0, 0.4, { name: 'start of the animation' }), new Keyframe(0.2, 0.75, { name: 'animation done' })]);
skySequence.addAnimation(starProgressAnimation);
*/

const sun = new Ellipse({ name: 'sun', extent: pt(70, 70), fill: Color.rgb(250, 250, 20), position: pt(0, 350) });
skySequence.addMorph(sun);
Expand Down
124 changes: 0 additions & 124 deletions interactive-morphs/lottie-morph.js
Original file line number Diff line number Diff line change
@@ -1,131 +1,7 @@
// This code was adapted from typeshift.components

import { HTMLMorph } from 'lively.morphic';
import { resource, importModuleViaNative } from 'lively.resources';

export class LottieMorph extends HTMLMorph {
static get properties () {
return {
animationDataUrl: {
copyAssetOnFreeze: true,
set (url) {
if (!url.startsWith(document.location.origin) && !url.startsWith('http')) {
let baseUrl;
if (url.startsWith('/')) baseUrl = document.location.origin;
else baseUrl = document.location.href + (document.location.href.endsWith('/') ? '' : '/..');

url = resource(baseUrl).join(url).withRelativePartsResolved().url;
}
if (this.animationDataUrl == url) return;
if (this._licenseTooltipSet) {
delete this._licenseTooltipSet;
this.tooltip = null;
}
this.setProperty('animationDataUrl', url);
this.lottieAnimation = null;
resource(url).readJson().then((animData) => {
this.animationData = this.fixAssets(animData, url);
this.initialize();
});
}
},
progress: {
defaultValue: 0.5,
min: 0,
max: 1,
isFloat: true,
set (progress) {
if (!this.isReady()) return;
this.setProperty('progress', progress);
this.renderFrame(Number.parseInt(this.lottieAnimation.totalFrames * progress));
}
},
animationData: {
serialize: false
},
borderStyle: {
defaultValue: 'none'
}
};
}

get isLottieMorph () {
return true;
}

// This was previously onLoad. Right now it allows us to mitigate a race condition.
// The race condition was introduced due to missing instrumentation of custom packages by the lively freezer.
// The missing instrumentation lead to the initialization order of the morph not being correct.
// There will be a fix in upstream lively for this. After the fix, this can be changed back.
onOwnerChanged (newOwner) {
if (!newOwner) return;

if (!this.animationDataUrl) {
this.animationDataUrl = 'https://assets6.lottiefiles.com/datafiles/AtGF4p7zA8LpP2R/data.json';
if (!this.tooltip) {
this.tooltip = 'CC-BY Credit: LK Jing';
this._licenseTooltipSet = true;
}
// CC-BY (https://creativecommons.org/licenses/by/4.0/)
// LK Jing (https://lottiefiles.com/user/3313)
// https://lottiefiles.com/2523-loading
}
}

menuItems () {
let items = super.menuItems();
items = items.slice(3); // remove edit CSS and edit HTML options
items.unshift(
['change animation data url...', async () => {
const url = await this.world().prompt('Enter Animation Data URL:', {
input: this.animationDataUrl,
lineWrapping: true,
width: 600,
selectInput: true
});
if (url) this.animationDataUrl = url;
}],
{ isDivider: true });
return items;
}

async initialize () {
// if (!this.world()) return; // do not initialize an animation on morphs not rendered
await this.whenRendered();
this.domNode.innerHTML = '';
const Lottie = await importModuleViaNative('https://jspm.dev/lottie-web');
this.lottieAnimation = Lottie.loadAnimation({
animationData: this.animationData,
renderer: 'svg',
autoplay: false,
container: this.domNode
});
}

destroyAnimation () {
if (!this.lottieAnimation) return;
this.lottieAnimation.destroy();
this.lottieAnimation = null;
}

fixAssets (animationData, dataUrl) {
const folderAccessor = 'u';
for (const asset of animationData.assets || []) {
if (asset[folderAccessor]) {
asset[folderAccessor] = resource(dataUrl).parent().join(asset[folderAccessor]).url;
}
}
return animationData;
}

renderFrame (frame) {
if (this.lottieAnimation) {
this.lottieAnimation.renderer.renderFrame(this.lottieAnimation.firstFrame + frame);
}
}

isReady () {
if (!this.lottieAnimation) return false;
return this.lottieAnimation.isLoaded;
}
}
2 changes: 1 addition & 1 deletion tests/editor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ describe('Editor and Interactive connections', () => {
async function performEditorActions () {
const someTimelineSequence = editor.withAllSubmorphsSelect(morph => morph.isTimelineSequence)[0];
await someTimelineSequence.openSequenceView();
editor.ui.inspector.targetMorph = someTimelineSequence.sequence.submorphs[0];
editor.ui.inspector.targetMorph = someTimelineSequence.sequence.submorphs[1];
}

function interactiveConnections () {
Expand Down

0 comments on commit 0e56e3b

Please sign in to comment.