Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrate with website builders #13

Open
lexoyo opened this issue May 8, 2020 · 6 comments
Open

integrate with website builders #13

lexoyo opened this issue May 8, 2020 · 6 comments

Comments

@lexoyo
Copy link

lexoyo commented May 8, 2020

hi @jeremyckahn
i love this tool so far, great idea !
i'm developing a lot on silex these days (silex.me)
i would love to see how we could make mantra help silex users :)
i ask a friend who uses silex to make website what he thinks about mantra to animate elements of his websites

@lexoyo lexoyo changed the title integrate website builders integrate with website builders May 8, 2020
@jeremyckahn
Copy link
Owner

Hi @lexoyo, I’m glad you’re liking Mantra! Thanks for the kind words. silex.me seems like a really cool tool/service, and I’d love to see Mantra integrated with it! It should be very doable, though a few modifications might have to be made depending on how you plan to integrate it.

Did you have any specific questions on how to do this?

@lexoyo
Copy link
Author

lexoyo commented May 8, 2020

I did not think a lot about it but the UI could be a button in the elements properties

When clicked it would open mantra (iframe? Or new Mantra()?) passing it the element css selector + the data Mantra created... When the anim is modified in Mantra Silex needs the data + css for the anim

I am not sure if it is possible/simple...

@jeremyckahn
Copy link
Owner

jeremyckahn commented May 9, 2020

I would imagine that loading and instantiating Mantra directly would be preferable to an iframe, but every project is a little different! One major advantage of loading directly is that you'll be able to access the CSS that Mantra generates much more easily. Here's how you might listen for timeline updates and get the latest CSS export:

const { mantra } = window

mantra.on('rekapi:timelineModified', () => {
  // Generates a big string of CSS keyframes
  const css = mantra.collectOne(
    'cssAnimationString', 
    mantra.collectOne('cssConfigObject')
  )
})

(EDIT: ⬆️ is a little dangerous, please see my next comment!)

I don't think you'll have to worry too much about window pollution, as I've tried to keep Mantra pretty self-contained: https://github.com/jeremyckahn/mantra/search?q=window&unscoped_q=window

Does this help?

@jeremyckahn
Copy link
Owner

I experimented with the above snippet a bit more, and I realized that you will probably not want to bind an expensive operation to the 'rekapi:timelineModified' event, as that fires quite a bit and can lock up the browser. 😬

You'll probably just want to do this to fetch the generated CSS once your app actually needs it:

const css = mantra.collectOne(
  'cssAnimationString', 
  mantra.collectOne('cssConfigObject')
)

That's a fairly expensive operation, so you'll want to avoid calling it too often!

@lexoyo
Copy link
Author

lexoyo commented May 9, 2020

This is useful info thx

I suppose there is an easy way to set the current animation? What is the data source like? The json maybe?

I'll try to make a first prototype and we will see what is easy and what is not :)

@jeremyckahn
Copy link
Owner

The fundamental APIs to do what you need are there, though admittedly some of them are not documented particularly well. This function will set the current animation within Mantra:

mantra/scripts/mantra.js

Lines 139 to 169 in 28949b0

/**
* @param {Object} timelineData
* @param {boolean} preventStackClear
*/
fn.loadTimeline = function(timelineData, preventStackClear) {
this.model.set('isLoadingTimeline', true);
this.emit('requestClearTimeline');
if (!preventStackClear) {
this.emit('requestClearUndoStack');
}
this.emit('loadBezierCurves', timelineData.curves);
this.emit('requestDeselectAllKeyframes');
this.rekapiComponent.rekapi.importTimeline(timelineData);
this.model.set('isLoadingTimeline', false);
// rekapi:timelineModified events are not triggered during or at the end of
// importTimeline, so trigger the event explicitly here to update
// the RekapiTimeline UI
this.collectOne('rekapiTimeline').trigger(
'rekapi:timelineModified',
this.rekapi
);
// Also force an update of the timeline scrubber guide since the events
// that normally trigger it were silenced previously
this.emit('requestResizeScrubberGuide');
this.rekapiComponent.update();
};

You can access it globally, and it accepts Rekapi timelineData.

mantra.loadTimeline({ ... })

You can also retrieve the current timeline data:

/**
* @override
*/
exportTimeline() {
const { rekapi } = this;
const timeline = rekapi.exportTimeline.apply(rekapi, arguments);
const activeKeyframeProperties = this.collect('activeKeyframeProperties');
let activeProperties = [];
if (activeKeyframeProperties.length) {
activeProperties = _.map(
activeKeyframeProperties,
activeKeyframeProperty =>
activeKeyframeProperty.model.pick('name', 'millisecond')
);
}
_.extend(timeline, { activeProperties });
return timeline;
},

Which can be accessed globally:

mantra.rekapiComponent.exportTimeline()

These methods deal with the same data format, so something like this would reload the current timeline:

mantra.loadTimeline(mantra.rekapiComponent.exportTimeline())

Granted, there's no real reason to reload the current timeline, but this snippet shows how these functions can be used in an interoperable way.

Let me know if this clarifies things for you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants