MDN may have intermittent access issues April 18 13:00 - April 19 01:00 UTC. See whistlepig.mozilla.org for all notifications.

mozilla

Revision 509739 of Responding to light conditions

  • Revision slug: Web/Apps/Developing/gather_and_modify_data/Responding_to_light_conditions
  • Revision title: Responding to light conditions
  • Revision id: 509739
  • Created:
  • Creator: chrisdavidmills
  • Is current revision? No
  • Comment

Revision Content

Ambient light sensors detect the presence and intensity of visible light. If used in a smart way, ambient light sensing optimizes visibility and battery life of portable devices such as tablets, smartphones, and laptops. This article looks at one way to respond to light conditions in the context of Open Web Apps: The Ambient Light API. Using this we can get information on the ambient light level and take actions to improve readability or create special effects dependant on light conditions. And even better, this article is rounded off with a nice Christmas-themed demo!

Ambient Light Sensors

Ambient light sensors are used in a variety of functions such as adjusting display brightness to a comfortable level.

In the context of smart houses, ambient light sensors can be used to turn on room lights when it gets too dim for human eyes and turn off unneeded lights when room brightness is adequate, or for video surveillance applications that detect motion via ambient light level changes.

In the context of Open Web Apps, consider for example an e-book reader app that automatically adjusts brightness in different light conditiions to improve readability.

Ambient Light API

The Ambient Light API gives web developers a tool to get information from available photo sensors (or similiar detectors) about the ambient light level.

TheW3C Specification defines two events:

  • The DeviceLightEvent, explained in this MDN page.
  • The LightLevelEvent, which at the time of writing (December 2013) is not documented in detail anywhere and no browser supports it. Look to the W3C specification for more information and keep track of the implementation status on the Mozilla Bugzilla.

The demo explained in the next section will use only che DeviceLightEvent.

Demo: XMAS Tales

XMAS Tales is an e-book reader app for kids that uses the Ambient Light API to respond to different light conditions with special effects, to impress children with the magic of Christmas. The demo is published on Github and you can also grab the source code to play with.

Notes:

  • Currently the Ambient Light API is supported only by Firefox and Firefox for Android. You should test it here first.
  • Portable devices such as MacBooks and Android tablets usually have an ambient light sensor.
  • The demo does not support small resolutions very well at present.

Let’s have a look at the code, starting with the HTML & CSS and then exploring the JavaScript, and how the demo used the Ambient Light API.

HTML & CSS

The Ambient Light API is a Javascript API, so showing the HTML and CSS might be considered out of scope here, but I think it is crucial to understand at least the elements composing the page on which JavaScript operates.

The main elements are:

  • The Book
  • The Christmas Tree
  • The Ambience

The Book

This is the book cover:

cover

And this is the HTML structure:

<div class="book">
    <div class="cover">...</div>
    <div class="page1">...</div>
    <div class="page2">
        <div>
            <div class="sky">
                ...
                <div class="tree">...</div>
                <div id="ambient-light-info">
                    <p>Ambient Light<br/><span id="lux">unknown</span> lux</p>
                </div>
                ...
            </div>
        </div>
    </div>
</div>

The book cover and rather nifty page flip motion is all done using CSS, including some complex CSS transform and transition action. You can find the CSS code for the book in the book.css file.

The Christmas Tree

Here is the Christmas Tree inside the book:

pages

This is the HTML:

<div class="tree">
    <div class="leaf"></div>
    <div class="leaf"></div>
    <div class="leaf"></div>
    <div class="leaf"></div>
    <div class="leaf"></div>
    <div class="leaf"></div>
    <ul class="bauble-container">
        <li><div class="pink bauble"></div></li>
        <li><div class="red bauble"></div></li>
        <li><div class="blue bauble"></div></li>
        <li><div class="yellow bauble"></div></li>
        <li><div class="green bauble"></div></li>
    </ul>
</div>

The tree and bauble are all created using CSS, with some crafty use of borders and border radius for the "leaves", and border-radius and gradients for the Christmas baubles. You can find the CSS code for the Christmas Tree in the christmas-tree.css file.

The Ambience

The book is contained inside an ambient div

<div class="snow ambient">
    <div class="book">...</div>
</div>

This way, depending on the mood class associated with it (snow, morning, evening or night), the book and the Christmas Tree have a different ambience projected over the top of them.

snowmorning

eveningnight

The most important thing to understand here is that, when the mood class on the ambient div is set to night, the sky becomes darker and it starts snowing. This is achieved via the following CSS:

.night.ambient .sky {
    color: whitesmoke!important;
    background-color: #080A38!important; 
    background-image: url('../images/snow.png'), url('../images/snow3.png'), url('../images/snow2.png')!important;
    animation: snow 20s linear infinite;
}

At the same time, the baubles are switched on:

.night.ambient .bauble.on:after { … }

And the "Merry Christmas" message becomes visible:

.night.ambient .message {
    visibility: visible;
}

Finally, some of the words of the story on page 1 change color:

.night.ambient .book .page1 span {
    font-weight: bold;
    font-size: 1.2em;
    color: #00a1ee;
}

You can find the CSS code for the Christmas Tree in the ambient.css file.

Javascript and Ambient Light Events

XMAS Tales implements the following JavaScript files:

<script src="scripts/controllers/BookViewController.js"></script>
<script src="scripts/controllers/ChristmasTreeViewController.js"></script>
<script src="scripts/utils/AmbientLightManager.js"></script>
<script src="scripts/start.js"></script>

This demo is built using Object Oriented Programming. For an introduction to Object Oriented Javascript have a look at this MDN page.

Each JavaScript file represents a component that executes specific tasks in the application. The AmbientLightManager is the component that uses Ambient Light Events so the most interesting code for the purposes of this tutorial is inside AmbientLightManager.js. However, in order to understand how the app works, we’ll briefly have a look at all the JavaScript files. Feel free to skip to the Ambient Light Manager section if you are mainly interested in the Ambient Light API.

Start

The start.js file contains the initializations of the Javascript Objects which the XMAS Tales web app needs to work.

window.mBookViewController = new BookViewController();
window.mChristmasTreeViewController = new ChristmasTreeViewController();
window.mAmbientLightManager = new AmbientLightManager();

This is done when the window object is loaded.

Install

When Mozilla launches the first Firefox OS tablet, we can easily add an install button. Watch this video in the meantime.

If you are not familiar with building web apps for Firefox OS, please have a look at our Quickstart app tutorial.

The BookViewController

Surprise! To flip the cover of the book we don’t need JavaScript: it’s all made with CSS transitions defined in book.css. We currently only have a single page, but such a controller can be helpful if you want to add more pages and include a navigation bar.

The ChristmasTreeViewController

The Christmas Tree has 5 baubles:

this.pinkBauble = document.querySelector('.pink.bauble');
this.redBauble = document.querySelector('.red.bauble');
this.blueBauble = document.querySelector('.blue.bauble');
this.yellowBauble = document.querySelector('.yellow.bauble');
this.greenBauble = document.querySelector('.green.bauble');

which blink randomly:

    this.blinkRandomly();

The blinkRandomly method repeatedly adds the on class and removes it after a while. This is done by executing a code snippet repeatedly, with a random time delay between each call to that function:

window.setInterval(function() {
    _self.pinkBauble.classList.add('on');
    window.setTimeout(function() {
        _self.pinkBauble.classList.remove('on');
    }, Math.random() * 8000);
}, Math.random() * 11000);

Have a look at the MDN pages for window.setInterval, window.setTimeout and Math.random if you need some more background information about these functions.

Although the blinkRandomly method is called by the ChristmasTreeViewController constructor, Christmas lights will be visible only when it’s dark, i.e. when the Christmas Tree's ambience container has .night.ambient classes set on it.

Have a look at the ChristmasTreeViewController.js for more details.

The AmbientLightManager

The AmbientLightManager uses the Ambient Light API to manage the following DOM Objects:

this.ambient = document.querySelector('.ambient');
this.lux = document.querySelector('#lux');

The constructor adds a listener to the devicelight event:

/* Ambient Light Events */
window.addEventListener('devicelight', function(deviceLightEvent) {

    /* Ambient light level (lux) to screen */
    _self.printLux(deviceLightEvent.value);

    /* Check ambient light status */
    if (deviceLightEvent.value > 500) { // snow
        _self.setSnow();
    }
    else if (deviceLightEvent.value > 100) { // morning
        _self.setMorning();
    }
    else if (deviceLightEvent.value > 10) { // evening
        _self.setEvening();
    }
    else { // night
        _self.setNight();
    }
});

The printLux method prints the level of ambient light (measured in lux) to the bottom right of page 2, just below the Christmas Tree.

The setSnow, setMorning, setEvening and setNight methods just put the related classes alongside the ambient class on the ambient div. For example, this is the setNight method:

setNight: function() {
    this.ambient.classList.remove('evening');
    this.ambient.classList.remove('morning');
    this.ambient.classList.remove('snow');
    this.ambient.classList.add('night');
}

And thanks to ambient.css, this is the final result:

Merry Christmas

Merry Christmas! :)

Revision Source

<div class="summary">
 <p>Ambient light sensors detect the presence and intensity of visible light. If used in a smart way, ambient light sensing optimizes visibility and battery life of portable devices such as tablets, smartphones, and laptops. This article looks at one way to respond to light conditions in the context of Open Web Apps: The Ambient Light API. Using this we can get information on the ambient light level and take actions to improve readability or create special effects dependant on light conditions. And even better, this article is rounded off with a nice Christmas-themed demo!</p>
</div>
<h2 id="Ambient_Light_Sensors">Ambient Light Sensors</h2>
<p>Ambient light sensors are used in a variety of functions such as adjusting display brightness to a comfortable level.</p>
<p>In the context of smart houses, ambient light sensors can be used to turn on room lights when it gets too dim for human eyes and turn off unneeded lights when room brightness is adequate, or for video surveillance applications that detect motion via ambient light level changes.</p>
<p>In the context of Open Web Apps, consider for example an e-book reader app that automatically adjusts brightness in different light conditiions to improve readability.</p>
<h2 id="Ambient_Light_API">Ambient Light API</h2>
<p>The Ambient Light API gives web developers a tool to get information from available photo sensors (or similiar detectors) about the ambient light level.</p>
<p>The<a href="http://www.w3.org/TR/ambient-light/">W3C Specification</a>&nbsp;defines two events:</p>
<ul>
 <li>The <code>DeviceLightEvent</code>, explained in <a href="/en-US/docs/Web/API/DeviceLightEvent">this MDN page</a>.</li>
 <li>The <code>LightLevelEvent</code>, which at the time of writing (December 2013) is not documented in detail anywhere and no browser supports it. Look to the <a href="http://www.w3.org/TR/ambient-light/#lightlevelevent-interface">W3C specification</a> for more information and keep track of the implementation status on the <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=842952">Mozilla Bugzilla</a>.</li>
</ul>
<div class="note">
 <p>The demo explained in the next section will use only che <code>DeviceLightEvent</code>.</p>
</div>
<h2 id="Demo.3A_XMAS_Tales">Demo: XMAS Tales</h2>
<p>XMAS Tales is an e-book reader app for kids that uses the Ambient Light API to respond to different light conditions with special effects, to impress children with the magic of Christmas. The <a href="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/">demo is published on Github</a> and you can also grab the <a href="https://github.com/franciov/xmas-tales">source code</a> to play with.</p>
<p>Notes:</p>
<ul>
 <li>Currently the Ambient Light API is supported only by Firefox and Firefox for Android. You should test it here first.</li>
 <li>Portable devices such as MacBooks and Android tablets usually have an ambient light sensor.</li>
 <li>The demo does not support small resolutions very well at present.</li>
</ul>
<p>Let’s have a look at the code, starting with the <a href="#HTML_.26_CSS">HTML &amp; CSS</a> and then exploring the <a href="#Javascript_and_Ambient_Light_Events">JavaScript, and how the demo used the Ambient Light API</a>.</p>
<h3 id="HTML_.26_CSS">HTML &amp; CSS</h3>
<p>The Ambient Light API is a Javascript API, so showing the HTML and CSS might be considered out of scope here, but I think it is crucial to understand at least the elements composing the page on which JavaScript operates.</p>
<p>The main elements are:</p>
<ul>
 <li>The Book</li>
 <li>The Christmas Tree</li>
 <li>The Ambience</li>
</ul>
<h4 id="The_Book">The Book</h4>
<p>This is the book cover:</p>
<p><img alt="cover" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/cover.png" style="width: 390px; height: 519px;" /></p>
<p>And this is the HTML structure:</p>
<pre class="brush: html">
&lt;div class="book"&gt;
    &lt;div class="cover"&gt;...&lt;/div&gt;
    &lt;div class="page1"&gt;...&lt;/div&gt;
    &lt;div class="page2"&gt;
        &lt;div&gt;
            &lt;div class="sky"&gt;
                ...
                &lt;div class="tree"&gt;...&lt;/div&gt;
                &lt;div id="ambient-light-info"&gt;
                    &lt;p&gt;Ambient Light&lt;br/&gt;&lt;span id="lux"&gt;unknown&lt;/span&gt; lux&lt;/p&gt;
                &lt;/div&gt;
                ...
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>The book cover and rather nifty page flip motion is all done using CSS, including some complex CSS transform and transition action. You can find the CSS code for the book in the <a href="https://github.com/franciov/xmas-tales/blob/master/style/book.css">book.css</a> file.</p>
<h4 id="The_Christmas_Tree">The Christmas Tree</h4>
<p>Here is the Christmas Tree inside the book:</p>
<p><img alt="pages" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/pages.png" style="width: 736px; height: 516px;" /></p>
<p>This is the HTML:</p>
<pre class="brush: html">
&lt;div class="tree"&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;div class="leaf"&gt;&lt;/div&gt;
    &lt;ul class="bauble-container"&gt;
        &lt;li&gt;&lt;div class="pink bauble"&gt;&lt;/div&gt;&lt;/li&gt;
        &lt;li&gt;&lt;div class="red bauble"&gt;&lt;/div&gt;&lt;/li&gt;
        &lt;li&gt;&lt;div class="blue bauble"&gt;&lt;/div&gt;&lt;/li&gt;
        &lt;li&gt;&lt;div class="yellow bauble"&gt;&lt;/div&gt;&lt;/li&gt;
        &lt;li&gt;&lt;div class="green bauble"&gt;&lt;/div&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;</pre>
<p>The tree and bauble are all created using CSS, with some crafty use of borders and border radius for the "leaves", and border-radius and gradients for the Christmas baubles. You can find the CSS code for the Christmas Tree in the <a href="https://github.com/franciov/xmas-tales/blob/master/style/christmas-tree.css">christmas-tree.css</a> file.</p>
<h4 id="The_Ambience">The Ambience</h4>
<p>The book is contained inside an ambient div</p>
<pre class="brush: html">
&lt;div class="snow ambient"&gt;
    &lt;div class="book"&gt;...&lt;/div&gt;
&lt;/div&gt;</pre>
<p>This way, depending on the mood class associated with it (<code>snow</code>, <code>morning</code>, <code>evening</code> or <code>night</code>), the book and the Christmas Tree have a different ambience projected over the top of them.</p>
<p><img alt="snow" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/snow-ambient.png" style="width: 336px; height: 458px;" /><img alt="morning" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/morning-ambient.png" style="width: 333px; height: 457px;" /></p>
<p><img alt="evening" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/evening-ambient.png" style="width: 334px; height: 451px;" /><img alt="night" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/night-ambient.png" style="width: 336px; height: 455px;" /></p>
<p>The most important thing to understand here is that, when the mood class on the <code>ambient</code> div is set to <code>night</code>, the <code>sky</code> becomes darker and it starts snowing. This is achieved via the following CSS:</p>
<pre class="brush: css">
.night.ambient .sky {
    color: whitesmoke!important;
    background-color: #080A38!important; 
    background-image: url('../images/snow.png'), url('../images/snow3.png'), url('../images/snow2.png')!important;
    animation: snow 20s linear infinite;
}</pre>
<p>At the same time, the baubles are switched on:</p>
<pre class="brush: css">
.night.ambient .bauble.on:after { … }</pre>
<p>And the "Merry Christmas" message becomes visible:</p>
<pre class="brush: css">
.night.ambient .message {
    visibility: visible;
}</pre>
<p>Finally, some of the words of the story on page 1 change color:</p>
<pre class="brush: css">
.night.ambient .book .page1 span {
    font-weight: bold;
    font-size: 1.2em;
    color: #00a1ee;
}</pre>
<p>You can find the CSS code for the Christmas Tree in the <a href="https://github.com/franciov/xmas-tales/blob/master/style/ambient.css">ambient.css</a> file.</p>
<h3 id="Javascript_and_Ambient_Light_Events">Javascript and Ambient Light Events</h3>
<p>XMAS Tales implements the following JavaScript files:</p>
<pre class="brush: html">
&lt;script src="scripts/controllers/BookViewController.js"&gt;&lt;/script&gt;
&lt;script src="scripts/controllers/ChristmasTreeViewController.js"&gt;&lt;/script&gt;
&lt;script src="scripts/utils/AmbientLightManager.js"&gt;&lt;/script&gt;
&lt;script src="scripts/start.js"&gt;&lt;/script&gt;</pre>
<div class="warning">
 <p>This demo is built using Object Oriented Programming. For an introduction to Object Oriented Javascript have a look at <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript">this MDN page</a>.</p>
</div>
<p>Each JavaScript file represents a component that executes specific tasks in the application. The <code>AmbientLightManager</code> is the component that uses Ambient Light Events so the most interesting code for the purposes of this tutorial is inside <em>AmbientLightManager.js</em>. However, in order to understand how the app works, we’ll briefly have a look at all the JavaScript files. Feel free to skip to the <a href="#The_AmbientLight_Manager">Ambient Light Manager</a> section if you are mainly interested in the Ambient Light API.</p>
<h4 id="Start">Start</h4>
<p>The <a href="https://github.com/franciov/xmas-tales/blob/master/scripts/start.js">start.js</a> file contains the initializations of the Javascript Objects which the XMAS Tales web app needs to work.</p>
<pre class="brush: js">
window.mBookViewController = new BookViewController();
window.mChristmasTreeViewController = new ChristmasTreeViewController();
window.mAmbientLightManager = new AmbientLightManager();</pre>
<p>This is done when the <code>window</code> object is loaded.</p>
<h4 id="Install">Install</h4>
<p>When Mozilla launches the first Firefox OS tablet, we can easily add an install button. Watch <a href="http://www.youtube.com/watch?v=hANbvc7ydJ4">this video</a> in the meantime.</p>
<div class="note">
 <p>If you are not familiar with building web apps for Firefox OS, please have a look at our <a href="/en-US/Apps/Quickstart/Build/Your_first_app">Quickstart app tutorial</a>.</p>
</div>
<h4 id="The_Book_ViewController">The BookViewController</h4>
<p>Surprise! To flip the cover of the book we don’t need JavaScript: it’s all made with CSS transitions defined in <a href="https://github.com/franciov/xmas-tales/blob/master/style/book.css">book.css</a>. We currently only have a single page, but such a controller can be helpful if you want to add more pages and include a navigation bar.</p>
<h4 id="The_ChristmasTree_ViewController">The ChristmasTreeViewController</h4>
<p>The Christmas Tree has 5 baubles:</p>
<pre class="brush: js">
this.pinkBauble = document.querySelector('.pink.bauble');
this.redBauble = document.querySelector('.red.bauble');
this.blueBauble = document.querySelector('.blue.bauble');
this.yellowBauble = document.querySelector('.yellow.bauble');
this.greenBauble = document.querySelector('.green.bauble');</pre>
<p>which blink randomly:</p>
<pre class="brush: js">
    this.blinkRandomly();</pre>
<p>The <code>blinkRandomly</code> method repeatedly adds the on class and removes it after a while. This is done by executing a code snippet repeatedly, with a random time delay between each call to that function:</p>
<pre class="brush: js">
window.setInterval(function() {
    _self.pinkBauble.classList.add('on');
    window.setTimeout(function() {
        _self.pinkBauble.classList.remove('on');
    }, Math.random() * 8000);
}, Math.random() * 11000);</pre>
<div class="note">
 <p>Have a look at the MDN pages for <a href="/en-US/docs/Web/API/Window.setInterval">window.setInterval</a>, <a href="/en-US/docs/Web/API/window.setTimeout">window.setTimeout</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random</a> if you need some more background information about these functions.</p>
</div>
<p>Although the <code>blinkRandomly</code> method is called by the <code>ChristmasTreeViewController</code> constructor, Christmas lights will be visible only when it’s dark, i.e. when the Christmas Tree's ambience container has <code>.night.ambient</code> classes set on it.</p>
<p>Have a look at the <a href="https://github.com/franciov/xmas-tales/blob/master/scripts/controllers/ChristmasTreeViewController.js">ChristmasTreeViewController.js</a> for more details.</p>
<h4 id="The_AmbientLight_Manager">The AmbientLightManager</h4>
<p>The <code>AmbientLightManager</code> uses the Ambient Light API to manage the following DOM Objects:</p>
<pre class="brush: js">
this.ambient = document.querySelector('.ambient');
this.lux = document.querySelector('#lux');</pre>
<p>The constructor adds a listener to the <code>devicelight</code> event:</p>
<pre class="brush: js">
/* Ambient Light Events */
window.addEventListener('devicelight', function(deviceLightEvent) {

    /* Ambient light level (lux) to screen */
    _self.printLux(deviceLightEvent.value);

    /* Check ambient light status */
    if (deviceLightEvent.value &gt; 500) { // snow
        _self.setSnow();
    }
    else if (deviceLightEvent.value &gt; 100) { // morning
        _self.setMorning();
    }
    else if (deviceLightEvent.value &gt; 10) { // evening
        _self.setEvening();
    }
    else { // night
        _self.setNight();
    }
});</pre>
<p>The <code>printLux</code> method prints the level of ambient light (measured in <em>lux</em>) to the bottom right of page 2, just below the Christmas Tree.</p>
<p>The <code>setSnow</code>, <code>setMorning</code>, <code>setEvening</code> and <code>setNight</code> methods just put the related classes alongside the <code>ambient</code> class on the ambient div. For example, this is the <code>setNight</code> method:</p>
<pre class="brush: js">
setNight: function() {
    this.ambient.classList.remove('evening');
    this.ambient.classList.remove('morning');
    this.ambient.classList.remove('snow');
    this.ambient.classList.add('night');
}</pre>
<p>And thanks to <a href="#The_Ambient">ambient.css</a>, this is the final result:</p>
<p><img alt="Merry Christmas" src="http://www.francesco.iovine.name/mdn/xmas-tales/public_html/images/screenshots/merry-christmas.png" style="height: 500px; width: 721px;" /></p>
<p>Merry Christmas! :)</p>
Revert to this revision