index.html
file from Github and make it available using rawgit. Here is the link created for famo.us examples: http://rawgit.com/Famous/famous/master/examples/index.html.
29 déc. 2014
Access all famo.us examples without downloading the starter kit
One neat trick that we have used on famous-views to set some links to famo.us examples is to use rawgit. A nice service that allow exposing a Github page. Simply choose an
28 déc. 2014
Debugging server side REST calls with mitmproxy in Meteor
Introduction
Isomorphic javascript offers a great flexibility for developper letting them choose where the code will get executed. On the clients or on the servers. While the Chrome DevTools have evolved at an impressive pace allowing to easily debug and see what is going on with your client's REST calls, the state of server side debugging may be a little bit deceptive in this field. Hence, when you need to put data fetching within your server, checking the flows of requests / responses could be a bit cumbersome if you solely rely on transaction logs or node-inspector. You could use technics like packet sniffing using Wireshark but setting a proper environment when using TLS with your REST call is a huge configuration process.
This is where mitmproxy comes to the rescue. Its name says it all: Man In The Middle PROXY. This incredible tool relies on the same technics as the infamous security attack, this time, for a greater purpose. For this article, I'm using mitmproxy as a local proxy server allowing me to trace all outgoing and incoming transactions from my server side Meteor app. Note that it is not the only use case that mitmproxy offers. Actually, this tool is incredibly agile allowing you to debug your mobile apps with great ease. Let us put our white hat on.
Installation on OSX
Using homebrew for installing mitmproxy is a one command line call:brew install mitmproxyNote that this steps actually installs 2 tools
mitmproxy
and mitmdump
as well as a set of certificates in ~/.mitmproxy
. We only use the first tool in this article but the second one could be handy when you need a lightweight display of your transaction flow and an easy way to save them in a replayable log. Note also that if you also intend to use mitmproxy for debugging other applications like native client ones, you can accept the certificate ~/.mitmproxy/mitmproxy-ca-cert.pemcertificate
in OSX that mitmproxy has created just for you. Just a caveat here. When you set your proxy settings in OSX, be sure to remove the local filters that Apple gently put for you if you want to see your native apps talking to your local servers.
Here's a little screenshot of a debugging session using mitmproxy:
Not that isomorphic
For REST calls, Meteor comes with its own isomorphic library: HTTP. On the client, it acts as basic AJAX calls, while on the server, it relies on the request module. Like all isomorphic libraries, this allows you to put your code logic in your clients or in your server with a nice and uniform API. But this comes at a price, it only covers the features that makes sense for both the clients and the server.
A server is not a browser. Indeed, while having cookies on the browser make sense for retaining states in your application for each user, cookies on the server starts to be a weird concept. Are these cookies used for the clients that you will serve or should the server could be seen as a client to another server? The same goes for the proxy settings on a server. Why would you need a proxy on a production server? Therefore, what is available on the client side of your app may not be available on the server side.
Unfortunately, you could have use cases where the REST API that you are using within your server may need cookies (which is a bit weird when speaking of REpresentational State Transfer which should rely on state-less operations ☺). Additionally, for debugging our flows, we also need the proxy capabilities that are offered out of the box by our browsers. This is where comes the nice package http-more from dandv. It exposes some already baked in feature of the request module for your server side REST calls.
You install it by replacing Meteor's default package like so:
For orienting your request to the proxy, play nice with your TLS layer and setting a cookie jar:
Once saved, you can reread it and modify it to only spare the relevant parts of your flows:
You install it by replacing Meteor's default package like so:
meteor remove http meteor add dandv:http-more
Proxyfy your REST calls in your server
Now that our toolbox is setup, it is time to orient our server so that it takes advantages of mitmproxy. This is achieved via the freshly exposed options in the HTTP library.For orienting your request to the proxy, play nice with your TLS layer and setting a cookie jar:
HTTP.get url, proxy: 'http://127.0.0.1:8080' strictSSL: false jar: true , (e, r) -> console.log 'GET sent through the proxy :-)'Now, you should see all your flows of your server on mitmproxy.
Some nice mitmproxy shortcuts and moves
mitmproxy's documentation is clear and very helpful. But before let you dive in, I'm sharing some of my most used shortcuts:- C to clear the list of flows.
- ↑ and ↓ for selecting a flow.
- ↵ for seeing the details of an exchange and q to go back to the list.
- ⇥ in detail of a flow to switch between the request and the response.
mitmproxy -w FILENAME
Once saved, you can reread it and modify it to only spare the relevant parts of your flows:
mitmproxy -nr FILENAMEWhere:
n
prevents to launch a proxy server.r
read the previous saved file.
- d for deleting flows.
- e for editing a request or a response.
- w then a for saving your all your modifications of the flows for the session.
- q then y for quitting edition mode.
mitmproxy -c FILENAME
14 déc. 2014
Put your HTML, CSS and JS in a single file using Meteor
It could be a bit cumbersome to switch from your HTML template file to your JS logic to your CSS stylesheets. I consider that the method exposed hereafter isn't tailored for novice users. Still, it can help you understanding how Meteor works.
Actually, the method is quite simple. It all drills down to how the HTML files are generated using Blaze, the reactive UI. During the build process of your app, Meteor builds JS file out of your HTML template file and exposes / sends them to your clients. This method short-circuits the build process. If you write directly your HTML using Blaze, the reactive UI, you remove the HTML file. The second step is to use JS to write your CSS. Here, I use the CSSC package for Meteor.
Here is the results for an equivalent of the default Meteor app.
You could think of it as a small component into a larger app.
And now, here is the code to create this small component. As promised, a single file, in CoffeeScript for brevity:
If you want to test it yourself, here is the set of required commands:
At the beginning, it may look a bit weird. But this could be useful from time to time. Note that you can put some nice additions to this sample. For instance, instead of using the events helpers which will scan you DOM for the button, you could directly affect the click event logic when you are creating the button element. If you are looking for performances on some parts of your app, this could be an interesting technic.
Actually, the method is quite simple. It all drills down to how the HTML files are generated using Blaze, the reactive UI. During the build process of your app, Meteor builds JS file out of your HTML template file and exposes / sends them to your clients. This method short-circuits the build process. If you write directly your HTML using Blaze, the reactive UI, you remove the HTML file. The second step is to use JS to write your CSS. Here, I use the CSSC package for Meteor.
Here is the results for an equivalent of the default Meteor app.
You could think of it as a small component into a larger app.
And now, here is the code to create this small component. As promised, a single file, in CoffeeScript for brevity:
# Render the body when Meteor is ready Meteor.startup Template.body.renderToDocument # HTML # ---- # Instantiate a main template Template['main'] = new Template 'Template.main', -> # Return a table of DOM elements [ # A 'p' tag with a reactive variable HTML.P 'Count ', Blaze.View => Spacebars.mustache @lookup 'count' # A 'button' tag HTML.BUTTON '+1' ] # JS logic # -------- # Declare a reactive variable Session.set 'count', 0 # Expose the reactive variable to the template Template.main.helpers 'count': -> Session.get 'count' # Handle template events Template.main.events 'click button': (e,t) -> e.preventDefault() Session.set 'count', 1 + Session.get 'count' # Add the template to the document's body Template.body.addContent -> Spacebars.include @lookupTemplate 'main' # CSS # --- # Instantiate a stylesheet css = new CSSC # Style the body and the text css.add 'body', margin: CSSC.px 20 backgroundColor: CSSC.navy color: CSSC.aqua # Style the button .add 'button', width: CSSC.px 50 border: "#{CSSC.px 1} #{CSSC.maroon} solid" borderRadius: CSSC.px 3 backgroundColor: CSSC.red color: CSSC.yellow
If you want to test it yourself, here is the set of required commands:
# Start by creating a simple app. meteor create singlefile cd singlefile # Remove the Meteor's default app. rm * # We are going to focus only on the front. # Our single file is being placed in the client directory. mkdir client # Add the necessary packages. meteor add coffeescript pierreeric:cssc pierreeric:cssc-colors pierreeric:cssc-normalize # Create your single file and start editing it. touch client/main.coffee
At the beginning, it may look a bit weird. But this could be useful from time to time. Note that you can put some nice additions to this sample. For instance, instead of using the events helpers which will scan you DOM for the button, you could directly affect the click event logic when you are creating the button element. If you are looking for performances on some parts of your app, this could be an interesting technic.
10 déc. 2014
The fastest loading screen for Meteor
Introduction
Meteor offers a great way to build web apps at an incomparable speed. It leverages the power of Javascript anywhere. In production, its powerful server side build system named Isobuild transpiles all your HTML files into JS files, thanks to Blaze, and packs them with your JS files. This operation leads to a single JS file loaded by a tiny initial HTML loader that bootstraps your app.Depending on your development strategy, this single JS file can end up very fat. This could seriously annoy your first time users who will wait many seconds before seing something on their screen. Of course, proxying your servers with Gzip or SPDY capable fronts greatly helps lowering this initial loading. Truncating this JS file could also help. Using a multiple domains strategy and CDNs also offer great loading time cuts. Still, on mobile, with a bad network access like GPRS, these several seconds rapidly become a problem. To understand the ins and outs of web performance optimization, WPO, I strongly recommend reading the book High Performance Browser Networking by Ilya Grigorik.
What is this about?
Not to be confused with the great masterpiece fast render from Arunoda Susiripala which is used for fastening the initial data required from your collections, the technic that I expose hereafter tackles the initial page load time, PLT. The first paints on the screen, if you prefer. This first paint comes even before the tiny initial HTML loader is fully loaded by your users's terminal.On a regular Meteor app, while your users connect to your site and till the initial load of the JS file, their browser remains blank. Of course, they could see that something is happening. Almost all browser display at least a progress indicator. But users may not notice it and think that your site is either dead or hosted on a distant other planet. That is just very bad for user acquisition, isn't it? If you want to better understand how this affects user's perceptions as well as your search engine optimization strategy, SEO, Paul Irish has covered this in great details in his incredibly informative talk: Fast enough (check the comments for the slides and the Youtube video). What you need to know is that your PLT will be nice if your initial screen painting is under 14k. That seems like an impossible goal to achieve with an out-of-the-box Meteor app with an average weight of ~50k of compressed initial JS file.
But Meteor is far from being a classic website approach and is definitely not a low end build tool. You can use the raw power of its Isobuild to ask your servers for an injection of your initial screen content directly within the tiny initial HTML loader. It is the key to unlock the 14k barrier.
Performing the injection
This could be a bit scary for the majority of Meteor devs. But once again, Arunoda has you well covered. By using another great masterpiece from Arunoda and Gadi Cohen, this injection process is a no brainer: inject initial. Let us jump in the code.In your app, installing inject initial is the one step classical stance:
meteor add meteorhacks:inject-initialFor the sake of brevity, the codes hereafter are in CoffeeScript.
In your server code, you can perform the initial injection. Hereafter, I'm just putting a little CSS spinner. Nothing fancy.
/server/startup.coffee
Inject.rawHead 'loader-style', # Force the initial scale for Android and iOS as our spinner may be # distorted by their default viewport values. '<meta name="viewport" content="width=device-width,maximum-scale=1,' + 'initial-scale=1,user-scalable=no">' + # The loading spinner needs some theming. '<style>' + 'html{background-color: #36342e;}' + 'body{color:#ddd;overflow:hidden;width:100%;}' + '.spinner {' + 'bottom:0;height:80px;left:0;margin:auto;position:absolute;' + 'top:0;right:0;width:80px;' + '-webkit-animation: rotation .6s infinite linear;' + 'animation: rotation .6s infinite linear;' + 'border-left:6px solid rgba(255,194,0,.20);' + 'border-right:6px solid rgba(255,194,0,.20);' + 'border-bottom:6px solid rgba(255,194,0,.20);' + 'border-top:6px solid rgba(255,194,0,.9);' + 'border-radius:100%;' + '}' + '@-webkit-keyframes rotation {' + 'from {-webkit-transform: rotate(0deg);}' + 'to {-webkit-transform: rotate(359deg);}' + '}' + '@-moz-keyframes rotation {' + 'from {-moz-transform: rotate(0deg);}' + 'to {-moz-transform: rotate(359deg);}' + '}' + '@-o-keyframes rotation {' + 'from {-o-transform: rotate(0deg);}' + 'to {-o-transform: rotate(359deg);}' + '}' + '@keyframes rotation {' + 'from {transform: rotate(0deg);}' + 'to {transform: rotate(359deg);}' + '}' + '</style>' # The loading spinner is a CSS animation. # /!\ WARNING: The trick is to create a fake body by injecting data # in the HTML's head as Meteor is requesting JS file in a blocking # fashion and mobile only allow 1 HTTP request at a time on a GPRS network. Inject.rawHead 'loader-body2', '<body><div class="spinner"></div></body>'Here we have somewhat altered, the DOM structure of our app. Indeed, we have just created a body while the head of your your initial HTML loader wasn't even finished to get build. Is that a big problem? No. Your server will carry on filling the rest of your app in the body section that you have created (the styles, the scripts, ...).
At this point, you could tell me: "But wait? There is now a title and meta tags in the body of my app. That's just a disgusting code.". You are right. But the browsers are really not impacted by this. I could reply back: "Who care?". But, indeed, I care. Simply because one of the biggest interest of web technology is that all your codes are readable. It is important to let other developers having the possibility to understand how stuff works. It is part of the learning legacy that we owe to the web. So let us put things in the correct order.
Cleaning our loaded codes is done directly on the client side. We do that once everything is loaded. No hurry as it has no impact except a good readability of our DOM structure.
/client/startup.coffee
Meteor.startup -> # Reshape DOM: put back title and meta elements in the head. # style and script tags can leave in the body tag. $head = $ 'head' for tag in ['meta', 'title'] $tags = $ tag $head.append $tags.clone() $tags.remove()That's it. Nice and clean.
Testing it
There are several ways of testing these results and their behavior. On Mac, I use Network link conditionner, a handy tool provided by Apple. It allows you to modify the behavior of you TCP stack and use GPRS, 3G, ... profiles. Very neat when you are testing hybrid or native apps.If you are testing full web apps, I strongly recommend using Chrome DevTools. The mobile emulator as a special feature allowing to change the network throttling.
Some constraints you need to be aware of
When your initial HTML loader and your initial JS file are being loaded, the JS engine and the SVG rendering engine are paused. I've always been annoyed by this browser behavior but we have to live with it. Thus, you can't put JS loaders or SVG animated loaders. You should favor CSS loader and choose the one that will be the less CPU intensive. Here, you should favor CSS3 animated loader which are animated by the GPU as the CPU will be intensively interpreting what it is finishing pumping from you servers.A side note to finish this little article. This technic is not here to bypass the necessary work of making your app as lightweight as possible. It is still a good practice to ensure that your app will avoid consuming the data subscription of your users ;-)
8 déc. 2014
7 déc. 2014
3D hardware accelerated SVG using famo.us and Meteor
One of the main problem with SVG for Android or Chrome, desktop and mobile, is the lack of hardware acceleration. Multiple issues also prevents some nice effects like skewing for instance. Making smooth animated SVG in a browser or in Cordova tends to be tricky.
As stated in one of my former blog post, famo.us makes a good candidate for removing this pain and Meteor, with its famous-views package, makes a good candidate for tying up everything together.
This weekend, I've started working on a famous-views's plugin named fview-svg. Basically, it reads your SVG as template and create famo.us's
Here is a little video that demonstrates my first demo with fview-svg:
As you can check it in the source code, without the comments, this demo is less than 20 lines of codes. And there is room for improvements.
I've deployed a live demo and you can play with it: fview-svg.
I've tested on desktop in Safari, Chrome, Firefox and Opera. On iOS8, I've tested it, an iPad Mini, an iPad 2, an iPhone 5S. On Android, I've tested it on release 4.4.2 on a Samsung Galaxy Tab and on release 4.0.3 on an HTC Desire C. And this is this last test that just surprised me. You may not even know what this terminal is. It's a low end smarphone. Very cheap. A single core under 1GHz. What Android call a
The source codes of the plugin as well as a tutorial for recreating this demo are available on Github: fview-svg.
Note: The plugin is not already available on Atmosphere, the official Meteor repository. I wand to test it against several additional demos to check which API would be good to export for easing the integration. Still, you can start cloning it and import it in your project if you want to contribute or cannot wait few days.
As stated in one of my former blog post, famo.us makes a good candidate for removing this pain and Meteor, with its famous-views package, makes a good candidate for tying up everything together.
This weekend, I've started working on a famous-views's plugin named fview-svg. Basically, it reads your SVG as template and create famo.us's
Surface
and StateModifier
out of it. One of the sensitive parts of the process was the inverted coordinate system of SVG compare to DOM and SVG's responsive nature. But the beauty of making it a plugin with famous-views is that it will be available for anyone. Nice.Here is a little video that demonstrates my first demo with fview-svg:
As you can check it in the source code, without the comments, this demo is less than 20 lines of codes. And there is room for improvements.
I've deployed a live demo and you can play with it: fview-svg.
I've tested on desktop in Safari, Chrome, Firefox and Opera. On iOS8, I've tested it, an iPad Mini, an iPad 2, an iPhone 5S. On Android, I've tested it on release 4.4.2 on a Samsung Galaxy Tab and on release 4.0.3 on an HTC Desire C. And this is this last test that just surprised me. You may not even know what this terminal is. It's a low end smarphone. Very cheap. A single core under 1GHz. What Android call a
midpi
. These terminals still equip a large portion of Android's market share. Just to give you a glimpse on these terminals, it doesn't even run the first Angry birds properly... And here, the SVG animation was perfect. Fluid. I almost shed a tear.The source codes of the plugin as well as a tutorial for recreating this demo are available on Github: fview-svg.
Note: The plugin is not already available on Atmosphere, the official Meteor repository. I wand to test it against several additional demos to check which API would be good to export for easing the integration. Still, you can start cloning it and import it in your project if you want to contribute or cannot wait few days.
1 déc. 2014
Some Famo.us demo with Meteor
Lately with famous-views, a package for Meteor, we have added some plugins for easing developments. To better demonstrate how to use them and what they bring, I've added some live demo for each one that I've created.
Here is a fast access to these demo:
Here is a fast access to these demo:
- fview-bksurfaceimage: Adaptive images.
- fview-devices: Responsive SVG devices working as container for demoing apps.
- fview-dotloader: Simple and customizable loader.
- fview-slidedeck: Slide deck engine à la Bespoke, Reveal, Impress, Prezzi.
- fview-flexgrid: Flexible grid.
30 nov. 2014
Responsive SVG devices for famo.us and Meteor
Introduction
When creating a landing page or when demonstrating an app, there are often some smartphone, tablet or desktop screenshots. This pattern of demonstration could be a bit enhanced if instead of simple screenshots, the real app could be demonstrated. That would be the power of HTML5 sets in motion.The base component
Famo.us has a nice component that could be leverage for that: the ContainerSurface. It is basically a small context that can be clipped. By living in the same space of your main web site, it allows interesting demonstration patterns where you could demonstrate your app. The problem is to display this context exactly on the device that you want to present.By using an adaptive or a responsive SVG, you can extract coordinates of the device screen where you want to present your app. You can then instantiates a ContainerSurface on this same coordinates and put you app as its content.
In this little plugin fview-devices for famous-views, a Meteor package, this is exactly what is done. Here is a little demonstration of it:
You can also play with it in this live demo: fview-devices.
Conclusion
Beyond this little example, some interesting points emerge such as the capability to mix SVG and Famo.us. It paves the way to further enhancements. For instance, CSS Transform and Animation are possible in SVG. Unfortunately, they are not hardware accelerated. Worst, some browsers have very uneasy bugs to circumvent. By extracting portions of SVG and putting them into Famo.us surfaces, you regain hardware acceleration and circumvent issues from wrong implementations. Basically, you open up wider the capability to use SVG to the mobile platforms.It seems to me that a new story of apps using SVG, Famo.us and Meteor is about to begin. Happy coding.
Famo.us dot loader animation using Meteor's Famous-Views
A simple customizable dot loader ported for famous-views:
Source code: fview-dotloader
Demo site: fview-dotloader
Original work: LeXXik and Talves.
Source code: fview-dotloader
Demo site: fview-dotloader
Original work: LeXXik and Talves.
25 nov. 2014
Famo.us FlexGrid in CoffeeScript with Meteor
Did I just post something similar few hours ago? Indeed very similar. But this time, this goes on a very different scale. The same demonstration is now reactive with datasources coming from a MongoDB, your session or any reactive dictionary that Meteor can provide.
But wait... There's more. Actually, this is not a piece of code that you will paste into your Meteor project. It's a plugin. One command and one line of templating and it is set. One line of templating means: in just one single line of code.
This is all made possible thanks to the efforts of Gadi Cohen's excellent package's Famous-Views and his community (in which I contribute a bit).
Basically, here is how it works. Famo.us components are registered in the Meteor's templating engine. It can be regular components or home made ones. Using your favorite templating language, being Spacebar or Jade, you create the layout of your app. You connect your reactive datasource in your templating if they are already available or via small template helpers à la Meteor. It's like Famo.us/Angular with a full stack JS framework. And if you are using Jade, it is like drawing the Famo.us rendering tree with your code and connect it with reactive data source.
As an example, here is the code required for creating the example displayed in the video:
As an example, here is the code required for creating the example displayed in the video:
// This is pretty basic for every mobile app. head title FlexGrid test meta(charset='utf-8') meta(name='viewport', content='width=device-width, maximum-scale=1, user-scalable=no') meta(name='apple-mobile-web-app-capable', content='yes') meta(name='apple-mobile-web-app-status-bar-style', content='black') meta(name='apple-mobile-web-app-capable', content='yes') meta(name='mobile-web-app-capable', content='yes') body // Every Famo.us apps starts with a context. +famousContext id="mainCtx" // The code is divided into reusable templates // looking very much like web components. +flexGridExample template(name='flexGridExample') // Now we create our 'render tree'. +Scrollview id='scrollview' // Here is the FlexGrid: it's indeed a single line of code! +FlexGrid id='flexgrid' // Here, I connect my datasource: a reactive array. +famousEach items // I use the available values in each item of the array // Note that CSS styles can be passed as reactive value, +Surface class='surf' properties=color // Or as reactive content. p= name
Simple. The community has also brought some others nice plugins that speeds up the creation of your app. The number of plugins available is growing fast.
Famo.us FlexGrid in CoffeeScript
A simple Pen to demonstrate how inheriting from a View by recreating Shu Liu's FlexGrid in CoffeeScript.
PS: Watch it in CodePen to better play with the viewport's size. It's nicely animated.
PS: Watch it in CodePen to better play with the viewport's size. It's nicely animated.
24 nov. 2014
A better inheritance base class for Famo.us widget in Meteor
In former articles, I've proposed a base class for inheriting from Famo.us. There was something odd on the way I was using the
Here is my fixed example:
DEFAULT_OPTIONS
. Actually, it should be a static members. It makes the code even easier to write.Here is my fixed example:
class @MyWidget extends famous.core.View DEFAULT_OPTIONS: size: [undefined, undefined] # ... Put your expected defaults here constructor: (@options) -> super @options # ... Put your remaining initialization code here
23 nov. 2014
A reactive favico for Meteor: rxFavico
I've packaged the nice favico.js project for Meteor: rxFavico. The added bonus is that it's now reactive. You simply modify a reactive dictionary, your favico changes automatically and all your associated display as well. This is handy for coupling it with a mailbox widget or the results of tests while developing.
Here is how to install it:
Here is how to install it:
meteor add pierreeric:rxfavicoHere is an example in CoffeeScript for using it:
rxFavico.set 'count', 10The source are available on Github.
4 nov. 2014
CSS color manipulation and normalize in CoffeeScript
Following my former article Create your CSS styles in CoffeeScript for Meteor, I've updated the CSSC packages to Meteor 1.0.0 and add some new features and plugins.
You can now add multiple rules in one call and calls are chainable:
if Meteor.isClient Meteor.startup -> @maincss = new CSSC @maincss .add 'html', backgroundColor: CSSC.yellow fontFamily: 'Helvetica Neue, Arial, sans-serif' .add 'body', fontSize: CSSC.px 20 .add ['h1', 'h2'], backgroundColor: CSSC.redA new plugin allows to create the same rules as Normalize.css: CSSC-Normalize. Just add it classically:
meteor add pierreeric:cssc-normalizeThe CSSC-Colors has been updated with color manipulation features:
# You can create basic RGB color from an hex String c = new CSSC.Clr '#FF4136' # From an hex string with alpha transparency c = new CSSC.Clr ['#FF4136', .3] # From the provided colors c = new CSSC.Clr CSSC.yellow # From some RGB value c = new CSSC.Clr [255, 60, 0] # From some RGB value with alpha transparency c = new CSSC.Clr [255, 60, 0, .3] # From some HSL value c = new CSSC.Clr ['hsl', .5, 1, .5] # From some HSL value with alpha transparency c = new CSSC.Clr ['hsl', .5, 1, .5, .3] # Once you have chosen your color, whatever the color schemes # that you use, you can modify its value. # Lets add some 20% saturation c.set 's', 1.2 * c.get 's' # Lets lighten it by 30% c.set 'l', 1.3 * c.get 'l' # Lets make less opaque by 10% c.set 'a', .9 * c.get 'a' # Now that we are finished with it use as a simple string where you want. # Through an automatic conversion String c # As a regular hex string c.toString() # As a CSS rgba value c.rgba() # rgba(255, 60, 0, .3) # As a CSS hsl value c.hsl() # hsl(240, 100%, 50%) # As a CSS hsla value c.hsla() # hsl(240, 100%, 50%, .3)
27 oct. 2014
Charts for easy choosing your Famo.us easing functions
Famo.us provides 30 different easing functions for tweening animations. Choosing the most appropriate one will give you the best results possible before creating your own if none matches your expectations.
With these charts, choosing is going to be far more easier:
With these charts, choosing is going to be far more easier:
26 oct. 2014
Atom is getting ready for Meteor 1.0.0
Thanks to Ben Strahan, Atom.io is getting ready for the upcoming Meteor-1.0.0 with the Meteor-Helper package.
There are also few others fixes and enhancements that you can see on the release notes: https://github.com/PEM--/meteor-helper/releases
There are also few others fixes and enhancements that you can see on the release notes: https://github.com/PEM--/meteor-helper/releases
A mind blowing talk from Douglas Crockford at Nordic.js 2014
This is just great. Hard to ingest. It is mind blowing but so true. Though, the video is titled the better parts, the bad parts are really interesting and worth hearing many times.
25 oct. 2014
Setup a Famo.us experiment using Codepen.io
Create your slide deck using Famo.us and Meteor
Introduction
Yesterday, there was the Paris Famo.us Meetup organized by AdFab and Meetic France. I was presenting the first part, which consists of a live coding or demo showcasing. I intended to demonstrate some basic techniques on Famo.us's physic engine. Live coding is tough. There are always some "demo effect" and time runs out very quickly.Fortunately, for this demo preparation, I created some slides. As the meetup was about Famo.us, I decided to code my slide deck using... Famo.us and Meteor.
The slides are deployed on Meteor: MeetupFamousSlides.
The core components
If you think about a presentation tool, it only consists of static pages that you present one after the other. This is definitely the job of iron:router.Creating each slide is easily done when you are using a templating system with emphasis on semantic. Jade and Markdown fit very well in this equation. Therefore, I ended up choosing mquandalle:jade. Each slide is a single Jade file. Thanks to the power of Meteor, you can write additional logic in the template for animating the slide's content.
Speaking of animations, modern slide deck use some of them. Famo.us is really a nice framework for this task. But coupling Meteor and Famo.us is a bit tedious. This is where enters gadiccohen:famous-views. It bridges both worlds with an incredible ease of use. I strongly recommend you to have an eye on it.
Conclusion and code reuse
In less than 2 hours, the presentation engine was ready and I had a basic presentation. Adding slides was a no brainer simply consisting in updating the router and adding a Jade file.You can find the code of the engine and the slide deck on this Github repository.
12 oct. 2014
Create your CSS styles in CoffeeScript for Meteor
I've created my first Meteor package today: CSSC. This package eases the creation of CSS stylesheets in CoffeeScript.
For using it, adds the package into your Meteor's project:
I've also created 2 plugins for this package:
For using it, adds the package into your Meteor's project:
meteor add pierreeric:csscOnce done, just create your stylesheets using DOM and CSSOM notation. For instance, I will create 2 classes
selected
and unselected
:
if Meteor.isClient Meteor.startup -> css = new CSSC css.add '.selected', margin: CSSC.x 3 border: "3px solid #{CSSC.yellow}" borderRadius: CSSC.x 5 css.add '.unselected', color: CSSC.yellowAs you can see it, the syntax is close to what you would use in Stylus or SASS (when using
.sass
notation).I've also created 2 plugins for this package:
- CSSC-Colors which allows inclusion of a nicer set of colors
- CSSC-Famous which avoids you from including CSS files from Famo.us.
With Meteor, this package and its plugins, you don't have to send CSS files to your client. Everything is packed within a single JS file.
15 sept. 2014
Free symbol font for IDE
I've created a free symbol fonts for any IDE that would like to integrate symbols. Here is a sample:
The font is under the MIT licence and available in my repo: FontClassesAndMethods. Feel free to modify it, tweak it, fork it, ...
The font is under the MIT licence and available in my repo: FontClassesAndMethods. Feel free to modify it, tweak it, fork it, ...
13 sept. 2014
Debug Meteor with Atom and customize Meteor's access to MongoDB
I've just updated my Atom.io's plugin Meteor Helper with 2 new features: debug mode and custom Mongo URL.
For debugging your Meteor's server side app, just set the Debug flag, launch a Node-Inspector and open your Chrome navigator on the URL provided by Node-Inspector. Basically, it covers the Step 2 of the Meteorpedia article on debugging.
For launching Meteor so that it uses an alternate MongoDB instance, you simply specify the access to this instance. Default installation of MongoDB are usually accessed via
For debugging your Meteor's server side app, just set the Debug flag, launch a Node-Inspector and open your Chrome navigator on the URL provided by Node-Inspector. Basically, it covers the Step 2 of the Meteorpedia article on debugging.
For launching Meteor so that it uses an alternate MongoDB instance, you simply specify the access to this instance. Default installation of MongoDB are usually accessed via
mongodb://localhost:27017
. Revert back to the classical MongoDB within Meteor, blank the content of the Mongo URL input field.
19 juil. 2014
Do we need HTML and CSS when we got JavaScript or more? A case for AbsurdJS, Meteor, Famo.us and CoffeeScript.
Introduction
AbsurdJS is an amazing project. What is it about? A processor for your HTML and CSS in JavaScript. In JSON to be more precise.The problem
CSS was invented for designers. But do you really know that much designers that are able to provide you with a nice CSS rules that will be awesome on all screens? You are favored by gods if it is your case. Most of the time, they will provide you with some PSD (what an ugly form of design), AI (if you are lucky), Sketch or SVG (here, it is not anymore based on luck, it is like having an angel upon your shoulders).The same goes with HTML. Semantics that appears with HTML5 were added for SEO. But do you know that much SEO guys that will give you the right HTML code? I haven't seen any in my whole 20 years on the web carrier(though SEO is not that long of a job).
Thus, why are we using 3 languages for writing our codes. Is that right? Do we have to? Is it done for helping us and keeping separation of concerns? Funny. Patterns like this exists since the dawn of design patterns from the GoF. And what if we need to synchronize this HTML, CSS and JS back together for animations purposes? We request back in our code the HTML tags that we have just declared? We hooks on the CSS? If we need a color theme, do we have to write it twice or more? Funny, too. Even media queries for responsive web designs, seems like an odd way of reproducing the abstract factory pattern (or the bridge depending on if you know to who you are distributing your files).
The solutions
There are many. Generally, I was keen on using preprocessors: SASS, LESS, Stylus, YAML, Jade, Blade, CoffeeScript, Typescript, Dart, ... But, it finally does not give me a proper answer to the problems previously mentioned. It still need glue code to make all of this work together properly. Things started to shape up when I end up using Meteor, Famo.us and Velocity.js. The Blaze component of Meteor is transforming your HTML, more precisely, your HTML templates using Spacebar, a derivative of Mustache, into JS code. The same goes with Famo.us. It creates HTML and CSS rules that plays well together so that they limit layout trashing issues and combines this technics with advanced physic and animation engine. The same goes with Velocity.js. This jQuery plugins brings back synchronized CSS animations in with JS.Still, plain vanilla JavaScript is a pain to write. While there are plenty of transpilers that could lessen the burden (like Dart and Typescript, to mention the most used ones), none have proven to be as easy as CoffeeScript to me.
Conclusion
Now the solution starts to shape up. Why not use the power of AbsurdJS, Meteor, Famo.us and CoffeeScript? This combination would be a real full stack. It would goes from the persistance layer, the application server to the front end with one and only one language. A transpiled one that even lessen the number of lines that you need to write.14 juil. 2014
Jade within Atom.io: Fasten your HTML and SVG authoring and template debugging
When writing HTML, XML, SVG or templates based on this language, it is cumbersome to open and close tags. Even with a good editor that closes tags for you or a good plugin that write snippet codes, you end up with unreadable and long source files. Jade removes this hassle by providing a simple and elegant code that transpiles to tagged code.
Here's an example of Jade transpiled to HTML:
However, it is sometime handy to seen what your generated code will look like. I've published another Atom.io plugin that preview the generated results with ctrl+alt+j.
The package is available on Atom.io's repository: https://atom.io/packages/jade-compile
And its code source is available on Github: https://github.com/PEM--/jade-compile
Here's an example of Jade transpiled to HTML:
However, it is sometime handy to seen what your generated code will look like. I've published another Atom.io plugin that preview the generated results with ctrl+alt+j.
The package is available on Atom.io's repository: https://atom.io/packages/jade-compile
And its code source is available on Github: https://github.com/PEM--/jade-compile
9 juil. 2014
Meteor.js from within Atom.io: Full stack dev with live reload in one key combo
I've just published a simple Meteor plugin for Atom.io. It launches Meteor with ctrl+alt+m. Whenever any problem is found on the server, a pane shows up from a dedicated status bar to warn you that something is going wrong.
The package is available on Atom.io's repository: https://atom.io/packages/meteor-helper
And its code source is available on Github: https://github.com/PEM--/meteor-helper
Here's a nice and simple video showing what it brings:
The package is available on Atom.io's repository: https://atom.io/packages/meteor-helper
And its code source is available on Github: https://github.com/PEM--/meteor-helper
Here's a nice and simple video showing what it brings:
4 juil. 2014
14 juin 2014
Some bubbles with Famo.us's physic engine in CoffeeScript and Meteor.js
Introduction
A week ago, Raix, the author of Famono package used for integrating Require.js and Famo.us with Meteor.js, has published a new release that simplifies greatly the integration.
I was willing to demonstrate just that when a nice demo of Famo.us's physic engine has shown up on my radar: http://hbsand.com/HappyBoxes/. So why not demonstrating both?
You can access the live demo here: http://famousbubble.meteor.com/.
You can also clone the code repository from Github: https://github.com/PEM--/famousbubble
Note for Chrome users on OSX : The current release of Chrome, the 36, has a bug that stops the demo running after ~1-2s. This bug is fixed in Chrome Canary version 37. I didn't see it on the current Chrome for Android or iOS. Firefox and Safari work well on OSX.
I was willing to demonstrate just that when a nice demo of Famo.us's physic engine has shown up on my radar: http://hbsand.com/HappyBoxes/. So why not demonstrating both?
You can access the live demo here: http://famousbubble.meteor.com/.
You can also clone the code repository from Github: https://github.com/PEM--/famousbubble
Note for Chrome users on OSX : The current release of Chrome, the 36, has a bug that stops the demo running after ~1-2s. This bug is fixed in Chrome Canary version 37. I didn't see it on the current Chrome for Android or iOS. Firefox and Safari work well on OSX.
Preparing your development environment
So, lets get down to business. The first step is to create the app:
mrt create FamousBubble cd FamousBubble rm -rf FamousBubble.* mkdir -p client/stylesheets client/startup client/views mrt add coffeescript mrt add stylus mrt add jade mrt add famono
For the imported Require.js package, I keep it at the bare minimum. Famono places the imported packages from a file called
client/lib/smart.require
:{ "famous": { "git": "https://github.com/Famous/famous.git" }, "famousPolyfills": { "git": "https://github.com/Famous/polyfills.git" } }This has not changed from the early version.
Linking Famo.us with Meteor.js
In Famono, what has changed is the way you require your dependencies. Theclient/startup/famous.coffee
is greatly reduced:# This is equivalent to: require 'famousPolyfills' famousPolyfills # Identically, this is equivalent to: require 'famous.core.famous' famous.core.famous # Declaring the main context window.mainCtx = famous.core.Engine.createContext()
Everything is now imported into the main context of Meteor.js. There is no more boilerplate code.
Our main Jade file,
client/index.jade
stays unchanged:head title Famo.us - Physic demo meta(name='viewport', content='width=device-width, maximum-scale=1, user-scalable=no') meta(name='mobile-web-app-capable', content='yes') meta(name='apple-mobile-web-app-capable', content='yes') meta(name='apple-mobile-web-app-status-bar-style', content='black') body +index template(name='index')
The Styus file,
client/stylesheets/app.styl
, is also unchanged:@import nib html font-family: Helvetica, Arial, sans-serif * -webkit-user-drag: none body -webkit-user-callout: none user-select: none background-color: #FF851B
Like the former file, the associated CoffeeScript file
client/index.coffee
to the index
template is almost unchanged either:Template.index.rendered = -> $(document).ready -> window.appView = new AppView() mainCtx.add appView appView.addDragger() appView.addBubbles()
Easier subclassing
As the Famo.us's University told us, you create your views by inheriting from Famo.us's ones. With Famono, it is now simplified. Here the code for theAppView
, client/views/AppView.coffee
that we just call in the previous file, the index
template:class @AppView extends famous.core.View DEFAULT_OPTIONS: numBodies: 10 gravity: [0, 0.0015, 0] constructor: (@options)-> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options surf = new famous.core.Surface size: [400, 400] properties: backgroundColor: '#FFDC00' borderRadius: '8px' mod = new famous.core.Modifier origin: [.5, .5] @add(mod).add surf @gravity = new famous.physics.forces.Force @options.gravity @ceiling = new famous.physics.constraints.Wall normal: [0, 1, 0] distance: 200 restitution: 0 @floor = new famous.physics.constraints.Wall normal: [0, -1, 0] distance: 200 restitution: 0 @left = new famous.physics.constraints.Wall normal: [1, 0, 0] distance: 200 restitution: 0 @right = new famous.physics.constraints.Wall normal: [-1, 0, 0] distance: 200 restitution: 0 @pe = new famous.physics.PhysicsEngine() @collision = new famous.physics.constraints.Collision restitution: 0 @bubbleBodies = [] famous.inputs.GenericSync.register 'mouse': famous.inputs.MouseSync 'touch': famous.inputs.TouchSync addDragger: -> @dragger = new Dragger() @pe.addBody @dragger.body (@_add @dragger.state).add @dragger.shape sync = new famous.inputs.GenericSync ['mouse', 'touch'] @dragger.shape.pipe sync sync.on 'update', (data) => @dragger.position[0] += data.delta[0] @dragger.position[1] += data.delta[1] @dragger.body.setPosition @dragger.position addBubble: (i) => bubble = new Bubble() @pe.addBody bubble.body bubble.state.transformFrom => @gravity.applyForce bubble.body bubble.body.getTransform() (@add bubble.state).add bubble.shape @pe.attach [@right, @left, @floor, @ceiling], bubble.body (@pe.attach @collision, @bubbleBodies, bubble.body) if i > 0 @pe.attach @collision, [bubble.body], @dragger.body @bubbleBodies.push bubble.body addBubbles: -> [0...@options.numBodies].map (i) => famous.utilities.Timer.setTimeout (@addBubble.bind @, i), 1000As you can see it, the inheritance from a Famo.us's
View
does not require you to wait for Famo.us to be loaded in your document. Additionally, the require step has been greatly simplified. Calling any class provided by Famo.us is done with a simple namespaced call.I've create 2 more classes. The first one,
client/views/Dragger.coffee
concerns the little dragging bubble used to play with the blue bubbles:class @Dragger RADIUS: 30 constructor: -> @shape = new famous.core.Surface size: [2 * @RADIUS, 2 * @RADIUS] properties: border: '2px solid #FF4136' borderRadius: "#{2 * @RADIUS}px" backgroundColor: 'rgba(255, 255, 255, 0.5)' @body = new famous.physics.bodies.Circle radius: @RADIUS mass: 5 @position = [0, 0] @state = new famous.core.Modifier origin: [.5, .5] transform: => famous.core.Transform.translate @position[0], @position[1], 0
The second one,
client/view/Bubble.coffee
concerns the bubble themselves: class @Bubble constructor: -> radius = famous.math.Random.integer 20, 60 @shape = new famous.core.Surface size: [radius * 2, radius * 2] properties: backgroundColor: '#7FDBFF' border: '3px solid #0074D9' borderRadius: "#{radius}px" @body = new famous.physics.bodies.Circle radius: radius, mass: 2 @state = new famous.core.Modifier origin: [.5, .5]
Conclusion
With the new Famono release, integrating Famo.us and Meteor.js is simpler than ever. My little sample is missing few things. A better separation of the controller from the views would be great. But, there is some upcoming Famo.us lessons that should arrive in the Famo.us's University. Therefore, they will surely cover their best practices. No rush.9 juin 2014
Timbre demo from Famo.us University using Meteor.js and CoffeeScript
Introduction
As already demonstrated in my previous article Famo.us polaroid tutorial in CoffeeScript and within Meteor, Meteor, CoffeeScript and Famo.us are incredibly useful tools for front end or full stack developers. This article just show the same principles with the Famo.us University Timbre tutorial. A live demo is deployed on Meteor's testing ground: http://famoustimbre.meteor.com/.Show me the code, please
If you find yourself stuck at translating some JS concept to CoffeeScript while playing the nice tutorial from Famo.us University, I provide my code hereafter:client/stylesheets/app.styl
@import nib html font-family: Helvetica * -webkit-user-drag: none body -webkit-touch-callout: none user-select: none
client/index.jade
head title Famo.us Timbre meta(name='viewport', content='width=device-width, maximum-scale=1, user-scalable=no') meta(name='mobile-web-app-capable', content='yes') meta(name='apple-mobile-web-app-capable', content='yes') meta(name='apple-mobile-web-app-status-bar-style', content='black') body +index template(name='index')
client/lib/famous.coffee
window.Famous ?= {}
client/lib/timbre.coffee
window.Timbre ?= {}
client/startup/famous.coffee
# Import Famous require 'famous/core/famous' # Adds the famo.us dependencies require 'famous-polyfills' # Wait for document ready $(document).ready -> # Load Famo.us libraries Famous.Engine = require 'famous/core/Engine' Famous.Surface = require 'famous/core/Surface' Famous.Transform = require 'famous/core/Transform' Famous.View = require 'famous/core/View' Famous.Modifier = require 'famous/core/Modifier' Famous.StateModifier = require 'famous/modifiers/StateModifier' Famous.HeaderFooter = require 'famous/views/HeaderFooterLayout' Famous.ImageSurface = require 'famous/surfaces/ImageSurface' Famous.FastClick = require 'famous/inputs/FastClick' Famous.GenericSync = require 'famous/inputs/GenericSync' Famous.MouseSync = require 'famous/inputs/MouseSync' Famous.TouchSync = require 'famous/inputs/TouchSync' Famous.GenericSync.register 'mouse': Famous.MouseSync 'touch': Famous.TouchSync Famous.Easing = require 'famous/transitions/Easing' Famous.Transitionable = require 'famous/transitions/Transitionable' Famous.Timer = require 'famous/utilities/Timer' # Create main context Timbre.mainCtx = Famous.Engine.createContext()
client/models/StripData.coffee
Timbre.StripData = [ {title: 'search', iconUrl: 'img/strip-icons/famous.png'} {title: 'starred', iconUrl: 'img/strip-icons/starred.png'} {title: 'friends', iconUrl: 'img/strip-icons/friends.png'} {title: 'settings', iconUrl: 'img/strip-icons/settings.png'} ]
client/index.coffee
ASPECT_RATIO = 320 / 548 Template.index.rendered = -> $document = $ document $document.ready -> docwidth = $document.width() docheight = $document.height() if docwidth / ASPECT_RATIO > docheight screenwidth = docheight * ASPECT_RATIO screenheight = docheight else screenwidth = docwidth screenheight = docwidth / ASPECT_RATIO appView = new Timbre.AppView() mainMod = new Famous.Modifier size: [screenwidth, screenheight] Timbre.mainCtx .add mainMod .add appView
client/models/AppView.coffee
$(document).ready -> class Timbre.AppView extends Famous.View DEFAULT_OPTIONS: openPosition: 276 transition: duration: 300 curve: Famous.Easing.inOutBack posThreshold: 138 velTreshold: 0.75 constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @menuToggle = false @pageViewPos = new Famous.Transitionable 0 @createPageView() @createMenuView() @setListeners() @handleSwipe() createPageView: -> @pageView = new Timbre.PageView() @pageModifier = new Famous.Modifier transform: => Famous.Transform.translate @pageViewPos.get(), 0, 0 @add(@pageModifier).add @pageView createMenuView: -> @menuView = new Timbre.MenuView stripData: Timbre.StripData menuModifier = new Famous.StateModifier transform: Famous.Transform.behind @add(menuModifier).add @menuView setListeners: -> @pageView.on 'menuToggle', @toggleMenu toggleMenu: => if @menuToggle @slideLeft() else @slideRight() @menuView.animateStrips() @menuToggle = !@menuToggle slideLeft: -> @pageViewPos.set 0, @options.transition, => @menuToggle = false slideRight: -> @pageViewPos.set @options.openPosition, @options.transition, => @menuToggle = true handleSwipe: -> sync = new Famous.GenericSync( ['mouse', 'touch'] , {direction: Famous.GenericSync.DIRECTION_X} ) @pageView.pipe sync sync.on 'update', (data) => currentPosition = @pageViewPos.get() @pageViewPos.set Math.max 0, currentPosition + data.delta if currentPosition is 0 and data.velocity > 0 @menuView.animateStrips() sync.on 'end', (data) => velocity = data.velocity position = @pageViewPos.get() if position > @options.posThreshold if velocity < -@options.velTreshold @slideLeft() else @slideRight() else if velocity > @options.velTreshold @slideRight() else @slideLeft()
client/models/PageView.coffee
$(document).ready -> class Timbre.PageView extends Famous.View DEFAULT_OPTIONS: headerSize: 44 constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @createLayout() @createHeader() @createBody() @setListeners() createLayout: -> @layout = new Famous.HeaderFooter headerSize: @options.headerSize layoutModifier = new Famous.StateModifier transform: Famous.Transform.translate 0, 0, .1 @add(layoutModifier).add @layout createHeader: -> backgroundSurface = new Famous.Surface properties: backgroundColor: 'black' backgroundModifier = new Famous.StateModifier transform: Famous.Transform.behind @layout.header .add backgroundModifier .add backgroundSurface @hamburgerSurface = new Famous.ImageSurface size: [44, 44] content: 'img/hamburger.png' searchSurface = new Famous.ImageSurface size: [232, 44] content: 'img/search.png' iconSurface = new Famous.ImageSurface size: [44, 44] content: 'img/icon.png' hamburgerModifier = new Famous.StateModifier origin: [0, .5] align: [0, .5] searchModifier = new Famous.StateModifier origin: [.5, .5] align: [.5, .5] iconModifier = new Famous.StateModifier origin: [1, .5] align: [1, .5] @layout.header .add hamburgerModifier .add @hamburgerSurface @layout.header .add searchModifier .add searchSurface @layout.header .add iconModifier .add iconSurface createBody: -> @bodySurface = new Famous.ImageSurface size: [undefined, true] content: 'img/body.png' @layout.content.add @bodySurface setListeners: -> @hamburgerSurface.on 'click', => @_eventOutput.emit 'menuToggle' @bodySurface.pipe @_eventOutput createBacking: -> backing = new Famous.Surface properties: backgroundColor: 'black' boxShadow: '0 0 20px rgba(0,0,0,0.5)' @add backing
client/models/MenuView.coffee
$(document).ready -> class Timbre.PageView extends Famous.View DEFAULT_OPTIONS: headerSize: 44 constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @createLayout() @createHeader() @createBody() @setListeners() createLayout: -> @layout = new Famous.HeaderFooter headerSize: @options.headerSize layoutModifier = new Famous.StateModifier transform: Famous.Transform.translate 0, 0, .1 @add(layoutModifier).add @layout createHeader: -> backgroundSurface = new Famous.Surface properties: backgroundColor: 'black' backgroundModifier = new Famous.StateModifier transform: Famous.Transform.behind @layout.header .add backgroundModifier .add backgroundSurface @hamburgerSurface = new Famous.ImageSurface size: [44, 44] content: 'img/hamburger.png' searchSurface = new Famous.ImageSurface size: [232, 44] content: 'img/search.png' iconSurface = new Famous.ImageSurface size: [44, 44] content: 'img/icon.png' hamburgerModifier = new Famous.StateModifier origin: [0, .5] align: [0, .5] searchModifier = new Famous.StateModifier origin: [.5, .5] align: [.5, .5] iconModifier = new Famous.StateModifier origin: [1, .5] align: [1, .5] @layout.header .add hamburgerModifier .add @hamburgerSurface @layout.header .add searchModifier .add searchSurface @layout.header .add iconModifier .add iconSurface createBody: -> @bodySurface = new Famous.ImageSurface size: [undefined, true] content: 'img/body.png' @layout.content.add @bodySurface setListeners: -> @hamburgerSurface.on 'click', => @_eventOutput.emit 'menuToggle' @bodySurface.pipe @_eventOutput createBacking: -> backing = new Famous.Surface properties: backgroundColor: 'black' boxShadow: '0 0 20px rgba(0,0,0,0.5)' @add backing
client/models/StripView.coffee
$(document).ready -> class Timbre.StripView extends Famous.View DEFAULT_OPTIONS: width: 320 height: 55 angle: -0.2 iconSize: 32 iconUrl: 'img/strip-icons/famous.png' title: 'Famo.us' fontSize: 26 constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @createBackground() @createIcon() @createTitle() createBackground: -> backgroundSurface = new Famous.Surface size: [@options.width, @options.height] properties: backgroundColor: 'black' boxShadow: '0 0 1px rgba(0, 0, 0, 1)' rotateModifier = new Famous.StateModifier transform: Famous.Transform.rotateZ @options.angle skewModifier = new Famous.StateModifier transform: Famous.Transform.skew 0, 0, @options.angle @add(rotateModifier) .add skewModifier .add backgroundSurface createIcon: -> iconSurface = new Famous.ImageSurface size: [@options.iconSize, @options.iconSize] content: @options.iconUrl properties: pointerEvents: 'none' iconModifier = new Famous.StateModifier transform: Famous.Transform.translate 24, 2, 0 @add(iconModifier).add iconSurface createTitle: -> titleSurface = new Famous.Surface size: [true, true] content: @options.title properties: color: 'white' fontSize: "#{@options.fontSize}px" textTransform: 'uppercase' pointerEvents: 'none' titleModifier = new Famous.StateModifier transform: Famous.Transform.thenMove( Famous.Transform.rotateZ @options.angle , [75, -5, 0] ) @add(titleModifier).add titleSurface
8 juin 2014
AdFab makes Badoit sparkling thanks to Famo.us
Famo.us has a physic engine. When used for animating screens, it's simply stunning.
4 juin 2014
Meteor docset is available in Dash
1 juin 2014
Velocity.js and Meteor
Introduction
Velocity.js is a new animation library in JS. It acts as a replacement of jQuery's animation library. Internally, it uses the CSS3 transformation and animation properties leveraging their hardware acceleration capabilities where possible and falling back on basic jQuery's animation when they are not available. Neat. Here is a small video of a simple animation developed by its creator:Step-by-step recreation
Create a basic Meteor application:mrt create Velocity3dDemo cd Velocity3dDemo rm -rf Velocity3dDemo*Import packages:
mrt add coffeescript mrt add jade mrt add stylus mrt add velocityjsCreate a basic web app structure:
mkdir -p client/stylesheetsCreate the Stylus file
client/stylesheets/app.styl
:@import 'nib' * padding: 0 margin: 0 body background-color: #060b14 overflow: hidden color: #ffffff font-family: Helvetica Neue, Open Sans, sans-serif font-weight: 100 a color: #4bc2f1 text-decoration: none &:hover text-decoration: underline #container perspective: 50px transform-origin: 50% 100% pointer-events: none opacity: 0.55 #welcome position: fixed width: 22rem left: 50% top: 45% margin-top: -1rem margin-left: -11rem font-weight: 200 opacity: 0.65 text-align: center font-size: 0.775rem line-height: 1.05rem letter-spacing: 0.135em word-spacing: -0.075rem @media screen and (max-width: 400px) #welcome font-size: 0.45rem !important #logo position: fixed right: 0.75rem bottom: 0.65rem cursor: pointer text-decoration: none color: #d6d6d6 font-size: 2rem letter-spacing: 0.025em #logoDot color: #d74580 .dot position: fixed width: 30px height: 30px border-radius: 30px background-color: #4bc2f1Create the Jade file
client/index.jade
:head
title Velocity 3D demo
body
+index
template(name='index')
#welcome No WebGL. No Canvas. Just pure DOM.
a#logo(href='http://julian.com/research/velocity/') Velocity.js
#container
Create the CoffeeScript file client/index.coffee
:Template.index.rendered = -> # Device detection isWebkit = /Webkit/i.test navigator.userAgent isChrome = /Chrome/i.test navigator.userAgent isMobile = window.ontouchstart isnt undefined isAndroid = /Android/i.test navigator.userAgent isIE = document.documentMode # Redirection if isMobile and isAndroid and not isChrome alert 'Use Chrome on Android' # Helpers # Randomly generate an integer between 2 numbers. r = (min, max) -> Math.floor(Math.random() * (1 + max - min)) + min # Dot creation # Differentiate dot counts on based on device and browser capabilities dotsCount = if isMobile then (if isAndroid then 40 else 60) else ( if isChrome then 175 else 125) dotsHtml = '' for i in [0..dotsCount] dotsHtml += '<div class="dot"></div>' $dots = $ dotsHtml # Setup $container = $ '#container' $welcome = $ '#welcome' screenWidth = window.screen.availWidth screenHeight = window.screen.availHeight chromeHeight = screenHeight - (document.documentElement.clientHeight or screenHeight) translateZMin = - 725 translateZMax = 600 containerAnimationMap = perspective: [215, 50] opacity: [0.90, 0.55] # IE10+ produce odd glitching issues when you rotateZ on a parent element subjected to 3D transforms. containerAnimationMap.rotateZ = [5, 0] if not(isIE) # Animation # Fade out the welcome message. $welcome.velocity opacity: [0, 0.65] , display: 'none' delay: 3500 duration: 1100 # Animate the dot's container. $container .css 'perspective-origin', "#{screenWidth/2}px #{(screenHeight*0.45)-chromeHeight}px" .velocity containerAnimationMap, {duration: 800, loop: 1, delay: 3250} # Special visual enhancement for WebKit browsers which are faster at box-shadow manipulation ($dots.css 'boxShadow', '0px 0px 4px 0px #4bc2f1') if isWebkit $dots .velocity translateX: [ -> '+=' + r -screenWidth/2.5, screenWidth/2.5 -> r 0, screenWidth ] translateY: [ -> '+=' + r -screenHeight/2.75, screenHeight/2.75 -> r 0, screenHeight ] translateZ: [ -> '+=' + r translateZMin, translateZMax -> r translateZMin, translateZMax ] opacity: [ -> Math.random() -> Math.random() + 0.1 ] , duration: 6000 easing: 'easeInOutsine' .velocity 'reverse', {easing: 'easeOutQuad'} .velocity opacity: 0 , duration: 2000 complete: -> $welcome .html "<a href='https://www.youtube.com/watch?v=MDLiVB6g2NY&hd=1'>Watch the making of this demo.</a><br /><br />Go create something amazing.<br />Sincerely, <a href='http://twitter.com/shapiro'>@Shapiro</a>" .velocity opacity: 0.75 , duration: 3500 display: 'block' .appendTo $containerLaunch it:
mrtPublish it:
mrt deploy velocity3ddemo.meteor.comSide note: I've just redeploy this little web app with a link to Meteor. My browser was on the page. Automatically, my browser has been informed that a new release of the code was available. It has only reloaded the modified assets. This is the incredible power of the live reload even when your apps are deployed. Amazing.
The original tutorial
Julian Shapiro, the author of Velocity.js, has provided a very nice Youtube channel which describes how he achieves his demo. A must watch.31 mai 2014
htop, a better CLI process viewer
Inside my CLI, I sometime like to see which process eats up my CPU or my RAM.
Install it on OSX using:
top
is generally a nice utility for that kind of tasks. But, there is a better and cleaner alternative: htop
. A comparison picture is worth a thousand words.Install it on OSX using:
brew install htop
25 mai 2014
Famo.us polaroid tutorial in CoffeeScript and within Meteor
Introduction
Since Famo.us v0.2.0, some new tutorials have been added to the Famo.us University. The 1st available project is a Polaroid tutorial which teaches you how to create your own app and widget with Famo.us. Just play this little video to check how incredible the animations are with plain simple HTML5 technologies. Note that, this example is completely responsive and I've tested it on smartphones, tablets and desktops.
This example project is not just beautiful. It works very well in iOS, Chrome on Android, Chrome, Safari and Opera. There are little flickers on Firefox but it seems more due to the browser than to the framework. Though, it is completely useable. As ever, the stock Android browser is definitely a knightmare. Meaning that, if you plan on encapsulating your WebApp in a native browser, Apache Cordova is the way to go for iOS but you will need to encapsulate Chromium if you plan on shipping your WebApp for Android. This can be achieve with projects such as Crosswalk, for instance.
Though, the tutorial is incredibly nice and goes smoothly over every difficulties that you may encounter (one of the best tutorial, that I've seen so far), I didn't choose the same way as described. Actually, JavaScript's inheritance model is such a pain to write, that I prefer avoiding it as much as I can. Thus, I've recreated it using another set of tools and it runs as smoothly as the original:
- CoffeeScript as a replacement of JavaScript.
- Jade as a replacement of HTML.
- Stylus as a replacement of CSS.
- Meteor as a replacement of LiveReload, Express and Grunt.
The result is a very small set of code that produces the same WebApp in a fraction of the necessary code and installation steps.
Configuring your Meteor project
Create your Meteor project with the dead simple following command:meteor create Polaroid cd PolaroidNow create a common fullstack JS directory structure only targeted for a client WebApp without server side integration:
mkdir -p client/lib client/models client/startup client/stylesheets client/views lib packages public/imgRemove the automatically created files:
rm -rf Polaroid.*Add the following package with Meteor:
meteor add coffeescript meteor add stylusAnd this one with Meteorite:
mrt add jade mrt add famonoEasy as pie.
Get the unique required asset from Famo.us
This example WebApp needs a simplepublic/img/camera.png
that you'll find in the Zip file that Famo.us provides in their download section.
Create your style file
The style fileclient/stylesheets/app.styl
is kept as its minimum as most of the CSS rules are handled by Famo.us.
@import 'nib' html background: #404040 body -webkit-touch-callout: none user-select: none font-family: 'AvenirNext-Medium'
Create your HTML file with Jade
As before for the style file, the main HTML fileclient/index.jade
is kept as its minimum as most of the tags are handled by Famo.ushead title Famo.us Polaroid body +index template(name='index')That's it, a simple
template
loaded by Meteor.
Create some namespaces
I like to isolate my code from the code that I import. Thus, I create 2 namespaces in 2 separate files.-
One is dedicated to the WebApp in
client/lib/polaroid.coffee
:# Declare Polaroid namespace window.Polaroid ?= {}
-
The other one is dedicated to Famo.us in
client/lib/famous.coffee
:# Declare Famo.us namespace window.Famous ?= {}
lib
directory is used as it is loaded first by Meteor.
The model, a Picasa album
With this example, we do not leverage the power of the full JS stack that Meteor provides. We only use its features of live reloading the code and its easy to use build capability. The model is the same as the one provided in the Famo.us Zip file that you've downloaded except that it is created as a CoffeeScript file namedclient/models/slidedata.coffee
:Polaroid.SlideData = userId: "109813050055185479846" albumId: "6013105701911614529" picasaUrl: "https://picasaweb.google.com/data/feed/api/user/" queryParams: "?alt=json&hl=en_US&access=visible&fields=entry(id,media:group(media:content,media:description,media:keywords,media:title))" defaultImage: "https://lh4.googleusercontent.com/-HbYp2q1BZfQ/U3LXxmWoy7I/AAAAAAAAAJk/VqI5bGooDaA/s1178-no/1.jpg" getUrl: -> @picasaUrl + @userId + "/albumid/" + @albumId + @queryParams parse: (data) -> urls = [] data = JSON.parse(data) entries = data.feed.entry i = 0 while i < entries.length media = entries[i].media$group urls.push media.media$content[0].url i++ urlsA simple dictionary with 2 methods.
Requiring the Famo.us libraries
I simply load all the Famo.us libraries in a single location. This drastically reduces the amount of code. I use the same fileclient/startup/famous.coffee
to load the polyfills and to create the Famo.us's singleton so that if I enhance this WebApp with multiple page loaded with a router, there will be no additional loadings or instantiations.
# Import famous.css require 'famous/core/famous' # Adds the famo.us dependencies require 'famous-polyfills' # Wait for document ready $(document).ready -> # Load Famo.us libraries Famous.Engine = require 'famous/core/Engine' Famous.View = require 'famous/core/View' Famous.Transform = require 'famous/core/Transform' Famous.Surface = require 'famous/core/Surface' Famous.StateModifier = require 'famous/modifiers/StateModifier' Famous.Timer = require 'famous/utilities/Timer' Famous.ImageSurface = require 'famous/surfaces/ImageSurface' Famous.ContainerSurface = require 'famous/surfaces/ContainerSurface' Famous.Lightbox = require 'famous/views/Lightbox' Famous.Utility = require 'famous/utilities/Utility' Famous.Easing = require 'famous/transitions/Easing' Famous.ContainerSurface = require 'famous/surfaces/ContainerSurface' Famous.Transitionable = require 'famous/transitions/Transitionable' Famous.SpringTransition = require 'famous/transitions/SpringTransition' # Register transitions Famous.Transitionable.registerMethod 'spring', Famous.SpringTransition # Create main context Polaroid.mainCtx = Famous.Engine.createContext()
Instantiate the main template
The content of the main template is set under theclient/index.coffee
that goes along with our Jade file:Template.index.rendered = -> # Get request to Picasa API Famous.Utility.loadURL Polaroid.SlideData.getUrl(), (data) -> data = Polaroid.SlideData.parse data # Instantiate the AppView with our URL's data Polaroid.appView = new Polaroid.AppView data: data Polaroid.mainCtx.add Polaroid.appView
Creating the views
The rest of this tutorial is pretty close to the one from the Famo.us University except that it uses the object model provided by CoffeeScript instead of the one from JavaScript. You should fill this 3 files while following the tutorial from the Famo.us University so that you get the nice explanations that they provided us.The views are composed of 3 files:
client/views/appview.coffee
$(document).ready -> class Polaroid.AppView extends Famous.View DEFAULT_OPTIONS: data: undefined cameraWidth: 0.6 * window.innerHeight constructor: (@options) -> @DEFAULT_OPTIONS.slideWidth = 0.8 * @DEFAULT_OPTIONS.cameraWidth @DEFAULT_OPTIONS.slideHeight = @DEFAULT_OPTIONS.slideWidth + 40 @DEFAULT_OPTIONS.slidePosition = 0.77 * @DEFAULT_OPTIONS.cameraWidth @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @createCamera() @createSlideshow() createCamera: -> camera = new Famous.ImageSurface size: [@options.cameraWidth, true] content: 'img/camera.png' properties: width: '100%' cameraModifier = new Famous.StateModifier origin: [0.5, 0] align: [0.5, 0] transform: Famous.Transform.behind @add(cameraModifier).add camera createSlideshow: -> slideshowView = new Polaroid.SlideshowView size: [@options.slideWidth, @options.slideHeight] data: @options.data slideshowModifier = new Famous.StateModifier origin: [0.5, 0] align: [0.5, 0] transform: Famous.Transform.translate 0, @options.slidePosition, 0 slideshowContainer = new Famous.ContainerSurface properties: overflow: 'hidden' @add(slideshowModifier).add slideshowContainer slideshowContainer.add slideshowView slideshowContainer.context.setPerspective 1000
client/views/slideshowview.coffee
$(document).ready -> class Polaroid.SlideshowView extends Famous.View DEFAULT_OPTIONS: size: [450, 500] data: undefined lightboxOpts: inOpacity: 1 outOpacity: 0 inOrigin: [0, 0] outOrigin: [0, 0] showOrigin: [0, 0] inTransform: Famous.Transform.thenMove Famous.Transform.rotateX(0.9), [0, -300, -300] outTransform: Famous.Transform.thenMove Famous.Transform.rotateZ(0.7), [0, window.innerHeight, -1000] inTransition: duration: 500, curve: Famous.Easing.outBack outTransition: duration: 350, curve: Famous.Easing.inQuad constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @rootModifier = new Famous.StateModifier size: @options.size origin: [0.5, 0] align: [0.5, 0] @mainNode = @add @rootModifier @createLightbox() @createSlides() createLightbox: -> @lightbox = new Famous.Lightbox @options.lightboxOpts @mainNode.add @lightbox createSlides: => @slides = [] @currentIndex = 0 console.log @options.data for url in @options.data slide = new Polaroid.SlideView size: @options.size photoUrl: url @slides.push slide slide.on 'click', @showNexSlide @showCurrentSlide() showCurrentSlide: -> @ready = false slide = @slides[@currentIndex] @lightbox.show slide, => @ready = true slide.fadeIn() showNexSlide: => return if @ready isnt true @currentIndex++ if @currentIndex is @slides.length @currentIndex = 0 @showCurrentSlide()
client/views/slideview.coffee
$(document).ready -> class Polaroid.SlideView extends Famous.View DEFAULT_OPTIONS: size: [400, 450] filmBorder: 15 photoBorder: 3 photoUrl: Polaroid.SlideData.defaultImage angle: -0.5 constructor: (@options) -> @constructor.DEFAULT_OPTIONS = @DEFAULT_OPTIONS super @options @rootModifier = new Famous.StateModifier size: @options.size @mainNode = @add @rootModifier @createBackground() @createFilm() @createPhoto() createBackground: -> background = new Famous.Surface properties: backgroundColor: '#fffff5' boxShadow: '0 10px 20px -5px rgba(0, 0, 0, 0.5)' cursor: 'pointer' @mainNode.add background background.on 'click', => @_eventOutput.emit 'click' createFilm: -> @options.filmSize = @options.size[0] - 2 * @options.filmBorder film = new Famous.Surface size: [@options.filmSize, @options.filmSize] properties: backgroundColor: '#222' zIndex: 1 # Make surface invisible to pointer events pointerEvents: 'none' filmModifier = new Famous.StateModifier origin: [0.5, 0] align: [0.5, 0] transform: Famous.Transform.translate 0, @options.filmBorder, 1 @mainNode .add filmModifier .add film createPhoto: -> photoSize = @options.filmSize - 2 * @options.photoBorder photo = new Famous.ImageSurface size: [photoSize, photoSize] content: @options.photoUrl properties: zIndex: 2 # Make surface invisible to pointer events pointerEvents: 'none' @photoModifier = new Famous.StateModifier origin: [0.5, 0] align: [0.5, 0] transform: Famous.Transform.translate 0, @options.filmBorder + @options.photoBorder, 2 opacity: 0.01 @mainNode .add @photoModifier .add photo fadeIn: => @photoModifier.setOpacity 1, {duration: 1500, curve: 'easeIn'} @shake() shake: -> @rootModifier.halt() @rootModifier.setTransform Famous.Transform.rotateX(@options.angle), {duration: 200, curve: 'easeOut'} @rootModifier.setTransform Famous.Transform.identity, {method: 'spring', period: 600, dampingRatio: 0.15}
Further words
My integration is not as proper as I would like it to be. Each class declaration relies on a ready event that I did not succeed in removing. Identically, my class constructors call their parent's one explicitly. Feel free to post some comments if you have a better integration.
Inscription à :
Articles (Atom)