Not Your Mother's Web3D:
Integrating X3DOM, jQuery and HTML5
by Sandy Ressler
National Institute of Standards and Technology
Web3D 2012, August 4-5, 2012
You can step through the slides with → and ↓
Hit the spacebar for an overview of the slideset (be patient wait for assets to load)Disclaimer
Any mention of commercial products within this presentation or NIST web pages is for information only; it does not imply recommendation or endorsement by NIST.
The views expressed in this presentation are solely those of the author and do not represent any official views of NIST or the US Government.
Agenda
- What is markup, DOM, jQuery, and X3DOM
- Selecting DOM elements, events, moving around the DOM tree
- Dynamically generating Geometry and Making it Interactive
- Dynamically generating UI Controls
- Annoying Integration Issues
- Extending jQuery - Plugins for Dummies
- Future
What is markup?
Markup is information that is embedded in the text of a document that is not intended for printing or display. It may consist of instructions to a printing device, commands for a Web browser, or comments to a coauthor. The form the markup takes is a function of the particular markup language used.
HTML important but not only markup language
XML
XHTML
SGML
I tend to use .xhtml because the browser (parsing) is way more informative about errors
Look Ma there's some 3D in my web pages!
What is the DOM?
- DOM - Document Object Model
- The structure of everything needed to render a page..and more!
- Manipulating the DOM means you are manipulating page elements
- Selecting elements of the DOM means you are selecting those elements of the page you wish to manipulate.
DOM Structure
From http://www.iwein.co.uk/2006/05/30/dom-structure-visualized/DOM Structure (simple document)
From W3C http://www.w3.org/TR/2006/WD-DOM-Level-3-Events-20060413/events.htmlDOM Events
From W3C http://www.w3.org/TR/2006/WD-DOM-Level-3-Events-20060413/events.htmlDOM (HTML) Events
- Web programming is "real time" programming
- Actions are "event driven"
- just like games!!
- An event happens, you perform an action and (sometimes) you have a callback to maintain control, in an asyncronous manner
- type of events: mouse, keyboard,
DOM Event Example here
Inside a <sphere> element define an "onclick" attribute
<sphere radius='0.26' > </sphere>
$('#dialog').html('You hit me');
onclick = "$('#dialog').html('You hit me'); "
jQuery dialogs lab
What is jQuery?
(and why should you care)
robust, highly tested, interoperable, JavaScript framework to simplify your web development life
- very powerful selection mechanism (selecting elements of the DOM)
- jQuery utilizes CSS selection mechanism
- $('sphere') - select all of the elements of type sphere
- deals with many issues of browser interoperability
- simplifies life with asyncronous issues (AJAX)
- highly extensible
Selectorama
jQuery selectors lab
jQuery selectors
Selections
radius='0.0125' onclick="$('#dialog').dialog('open'); $('#dialog').html('<p> You just selected the '+ $(this).parent().parent().attr('description') + ' landmark. </p>'); $('#dialog') .dialog( {title: $(this) .parent() .parent() .attr('description') });
select (pseudo english)
for each element of the type (shape)
do something fn()
Method Chaining
$('#sphere').parent().parent().attr('radius');
What is X3DOM
Simply put: it's X3D in your web page
So what is X3D?
A declarative 3D markup language
...
X3D/X3DOM - Scene Graph
X3D/X3DOM - Event Model
Time (keeps on ticking)
X3D/X3DOM - Interactivity
X3DOM - the id versus DEF issue
- In X3D geometry or other elements are named via the DEF construct
- <Transform translation="1 2 3" DEF="boxTrans" >
- Later on we might refer to it via <Transform USE="boxTrans" >
- but HTML, the DOM and JavasScript don't know anything about the DEF/USE constructs
- If both id and DEF are set both attrubutes will have different values
- if only DEF is set that id is left unset
- if only id is set then DEF and id are set to the same value
X3DOM solution is:
XXX Some real X3DOM code here
The case for declarative 3D markup
Remember thouse jQuery selectors?
Let's select geometry!
$("#sphere")
JSBIN demos/examples
Dynamically generating geometry
defining a sphere template
<sphere radius="0.0125" onclick="$("#dialog").dialog("open");
$(".timer").attr("cycleInterval","0");
$("#clock1").attr("cycleInterval","2.0");
$("#dialog").html("<p> You just selected the "+ $(this).parent().parent().attr("description") + " landmark. </p>");
$("#dialog").dialog( {title: $(this).parent().parent().attr("description") });" ></sphere>
</shape>
code to clone the landmark (sphere)
function cloneLandmarks(idstr, matstr) {
for (var index = 0; index < OrigLandmarks[0].length; index++) {
$(".ball").each(function(index) {
newNum = new Number(index + 1);
newElem = $("#"+idstr+"0").clone().attr("id", "idstr" + newNum);
newElem.attr("description", OrigLandmarks[0][index].description);
newElem.attr("translation", OrigLandmarks[0][index].translation);
//2nd child of shape is sphere
//replace clock1 with correct clock id
tmpObj = newElem.children().children(":nth-child(2)");
tmpClickStr = tmpObj.attr("onclick");
ntmpClickStr = tmpClickStr.replace(/clock1/i,"clock"+newNum);
newElem.children().children(":nth-child(2)").attr("onclick",ntmpClickStr);
//replace mat1 with mat id
newElem.children().children().children().attr("id",matstr+newNum);
$("#"+idstr+"0").after(newElem); // place the new transform
}
};
Usage
cloneLandmarks('lm','mat');
Let's Generate that Geometry
xxx example(s) here
JavaScript DRY (Don't Repeat Yourself)
Making Geometry Interactive
Using the HTML onClick Event
Using X3D's Touch events
BUT Wait!! Which Event Works Better
This is a point of intersection/conflict between X3DOM and the DOM that must be resolved
Integrating UI elements
This is how jQuery UI works
jQuery UI Demos
Dynamically generating user interface controls
First some code to create some jQuery controls
From x3dom site: jQuery Manipulation
code for jQuery sliders manipulating 3D attributes
<X3D xmlns="http://www.web3d.org/specifications/x3d-namespace" id="spheres" showStat="true" x="0px" y="0px" width="400px" height="400px" style="float:left;">
<Scene DEF='scene'>
<Viewpoint position='0 0 10' />
<Background skyColor='1 1 1' />
<Transform id='trans'>
<Shape>
<Appearance>
<Material diffuseColor='0 0 0' specularColor='.2 .2 .2' />
</Appearance>
<Box DEF='box'/>
</Shape>
</Transform>
</Scene>
</X3D>
<div id="ctrlContainer">
<p>Change the color of the cube using the RGB sliders, which updates the "diffuseColor" attribute of the Material node using jQuery.</p>
<div id="sliderContainer">
<ul>
<li><label>Red</label><div id="redSlider" class="slider"/></li>
<li><label>Green</label><div id="greenSlider" class="slider"/></li>
<li><label>Blue</label><div id="blueSlider" class="slider"/></li>
</ul>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
// Create the sliders
$(".slider").slider({min: 0, max: 1, step: 0.01, slide: function(e, ui) {
var newCol = $("#redSlider").slider('option', 'value') + " "
+ $("#greenSlider").slider('option', 'value') + " "
+ $("#blueSlider").slider('option', 'value');
$("Material").attr("diffuseColor", newCol);
}});
});
</script>
Programmatically creating controls
AnthroGloss
controls associated with graphical objects
function to clone a button
function cloneViewpointButtons() {
$('#nameClone').show(); // show the button to clone
var Viewpoints = $("viewpoint"); //select all viewpoint elements and place into array
// original source of clone button code
// http://charlie.griefer.com/blog/index.cfm/2009/9/17/jQuery--Dynamically-Adding-Form-Elements
//iterate through all of the viewpoints
$("viewpoint").each( function(index) {
newNum = new Number(index + 1);
newElem = $('#nameClone').clone().attr('id', 'name' + newNum); //clones only the button
newElem.attr('class', 'viewbutts'); // assign a classname to allow deletion of all but first button
newElem.attr('value', $(this).attr('description'));
//use the animate visual effect and
//create an anonymous function to execute when button is clicked
newElem.button().click(function() {
$(this).animate({opacity: 0.5}, 1500);
$(Viewpoints[index]).attr('set_bind','true'); // this must be an actual viewpoint
var descrip = $(Viewpoints[index]).attr('description');
var htmlStr = "Current Viewpoint: " + descrip + " ";
$('#currViewpoint').html(htmlStr);
});;
$('#nameClone').before(newElem); // place the new button after the old div
});
$('#nameClone').hide(); // hide the button to clone
};
Some More Robust Examples
CAESAR X3DOM
Body Pose Flipper
Let's Assemble this Thing
What pieces do we need?
- Libraries: jQuery, X3DOM, CSS files, fonts
- HTML
- code: JavaScript
- IMPORTANT you must run on a web server! (for included "inline" files)
Annoying Integration Issues
name space, name space, name space
Several types of HTML elements appear in global DOM namespace, and these can interfere with each other
Button elements all treated as global so the must be distinguigshed (can assign class name to solve this)
Dialog popups also get confused as global
Illustrate button integration bug here
So to fix the button integration bug...
set of slides illustrating the button integration bug...vertical slides
Couldn't change the viewpoint element because it's and ELEMENT and we need it.
But we can add a new class "flipvp" to name only those viewpoint elements that we want to play with for this page
Extending jQuery - plugIns for Dummies
jqPlugTest.xhtml
This is all the code for a jQuery plug-in
(function($) {
$.fn.X3DOMgeomButton = function(options) {
// Extend our default options with those provided.
// Note that the first arg to extend is an empty object -
// this is to keep from overriding our "defaults" object.
var opts = $.extend({}, $.fn.X3DOMgeomButton.defaults, options);
// iterate each matched element
return this.each(function() {
var base = $(this);
//var attribute = base.attr(opts);
var scaleOpt = opts.scale;
var onclickOpt = opts.onclick;
var diffuseColorOpt = opts.diffuseColor;
var translationOpt = opts.translation;
if (scaleOpt) base.attr('scale',scaleOpt);
if (onclickOpt) base.attr('onclick',onclickOpt);
if (translationOpt) base.attr('translation',translationOpt);
// base is the transform then -> shape -> appearance -> material
if (diffuseColorOpt) base.children().children().children().attr('diffuseColor',diffuseColorOpt);
});
};
$.fn.X3DOMgeomButton.defaults = {
scale: '10 10 10',
onclick: 'alert("I am hit");',
diffuseColor: '0 1 0'
// do not want a default translation because generally objects exist where they should
};
})(jQuery);
This is how to use the jQuery plug-in
$('#tr0').X3DOMgeomButton(
{ onclick : 'alert("You hit id0 object")',
diffuseColor: '0.5, 1, 1',
translation: '5 0 0'});
$('#tr1').X3DOMgeomButton({ onclick : 'alert("You hit id1 object")',
diffuseColor: '0.8 0 0',
scale: '10 1 10'});
$('#tr2').X3DOMgeomButton({ onclick : 'alert("You hit id2 object")',
diffuseColor: '0.8 0 0.8',
scale: '5 1 5'});
jQuery plug-in Example
The Future
Look at D3 and what it does for SVG
X3DOM and X3 from https://gist.github.com/ZJONSSON
Useful Links
Acknowledgements
- HTML/CSS slideshow software (reveal.js):Hakim El Hattab
- code highlighting - highlight.js by softwaremaniacs.org highlight.js.
- slide/web page embedding - lightview.js, Nick Stakenburg, lightview.js
- Icons from TheNounProject: http://thenounproject.com