Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

freely positioned elements #154

Closed
wants to merge 2 commits into from

2 participants

@shezi

This pull-request contains two distinct change sets:
1. Pulling the "canvas" apart from the "root" elements to make insertion of additional content into the root element easier. This can be used to put the fallback message or other control elements inside the root-div, making the markup cleaner.
2. Freely positioned elements: These elements are marked with the class "positioned" and will be positioned like steps, but do not show up in the steps list. They can be used to add additional content that is not tied into a single frame, e.g. a graph connecting several steps.

Johannes Spi... added some commits
Johannes Spielmann Turning canvas into canvasScale and canvasRotate. This allows us to p…
…ull non-animated elements (like the fallback message) into the impress-root.
7fa033d
Johannes Spielmann freely-positioned elements (new feature) 9ec51ef
@bartaz
Owner

Hi,

thank you for your additions.

I don't really understand the need for additional canvas element. The #impress root element is meant to contain elements positioned by impress.js. Anything else can (and should) be placed outside of it in HTML. All the custom classes impress.js uses are set on the body element, so they can be used by all elements on the page.

When it comes to the second addition - the freely positioned elements. It was requested couple of times (for example in #8) but I'm still not sure what would be the best way to implement it... I was thinking more about using some data-skip attribute than adding new class (like your positioned).
So this feature will probably appear in impress.js at some point, but I'm not sure in what form. I want to keep impress.js as simple as possible.

So, I'm not going to merge this pull request.

What I've noticed in one of your commits was some grammar fixes in the comments. They sound much more English and I'll be glad to use them.
Would it be possible for you to create some branch that would include these changes, so you can make a pull request with it? It would be easier then coping them manually (and I'd like to keep you as a contributor of them).

@bartaz bartaz closed this
@shezi

Hi bartaz,

thank you for your long reply and your explanations.

I will create a branch that contains documentation changes and do another pull-request for those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 10, 2012
  1. Turning canvas into canvasScale and canvasRotate. This allows us to p…

    Johannes Spielmann authored
    …ull non-animated elements (like the fallback message) into the impress-root.
  2. freely-positioned elements (new feature)

    Johannes Spielmann authored
This page is out of date. Refresh to see the latest.
Showing with 122 additions and 49 deletions.
  1. +21 −0 css/impress-demo.css
  2. +33 −16 index.html
  3. +68 −33 js/impress.js
View
21 css/impress-demo.css
@@ -181,6 +181,17 @@ a:focus {
}
/*
+ Styling for the freely-positioned elements.
+ We'll style them the same as the slide elements for consistency
+*/
+.positioned {
+
+ font-family: 'PT Serif', georgia, serif;
+ font-size: 48px;
+ line-height: 1.5;
+}
+
+/*
... and we enhance the styles for impress.js.
Basically we remove the margin and make inactive steps a little bit transparent.
@@ -527,6 +538,16 @@ a:focus {
cursor: pointer;
}
+/*
+ For the freely-positioned element we will allocate some more space and make the text a bit tighter.
+ Since this text isn't visible on any slide, we can leave it fully opaque all the time.
+*/
+#roamfree {
+ line-height: 1.2em;
+ width: 8em;
+ font-size: 64px;
+}
+
/*
Now, when we have all the steps styled let's give users a hint how to navigate
View
49 index.html
@@ -98,38 +98,31 @@
<!--
- Body element is used by impress.js to set some useful class names, that will allow you to detect
+ The body element is used by impress.js to set some useful class names that will allow you to detect
the support and state of the presentation in CSS or other scripts.
- First very useful class name is `impress-not-supported`. This class means, that browser doesn't
+ The first very useful class name is `impress-not-supported`. This class means that browser doesn't
support features required by impress.js, so you should apply some fallback styles in your CSS.
- It's not necessary to add it manually on this element. If the script detects that browser is not
+ It's not necessary to add it manually on this element. If the script detects that the browser is not
good enough it will add this class, but keeping it in HTML means that users without JavaScript
will also get fallback styles.
- When impress.js script detects that browser supports all required features, this class name will
+ When impress.js detects that the browser supports all required features, this class name will
be removed.
- The class name on body element also depends on currently active presentation step. More details about
- it can be found later, when `hint` element is being described.
+ The class name on body element also depends on the currently active presentation step. More details about
+ it can be found later, when the `hint` element is being described.
-->
<body class="impress-not-supported">
-<!--
- For example this fallback message is only visible when there is `impress-not-supported` class on body.
--->
-<div class="fallback-message">
- <p>Your browser <b>doesn't support the features required</b> by impress.js, so you are presented with a simplified version of this presentation.</p>
- <p>For the best experience please use the latest <b>Chrome</b>, <b>Safari</b> or <b>Firefox</b> browser.</p>
-</div>
<!--
- Now that's the core element used by impress.js.
+ Now here's the core element used by impress.js.
That's the wrapper for your presentation steps. In this element all the impress.js magic happens.
- It doesn't have to be a `<div>`. Only `id` is important here as that's how the script find it.
+ It doesn't have to be a `<div>`. Only its `id` is important here as that's how the script finds it.
You probably won't need it now, but there are some configuration options that can be set on this element.
@@ -145,7 +138,16 @@
right around the corner of this tag ;)
-->
-<div id="impress">
+<div id="impress" data-perspective="1000">
+
+ <!--
+ This fallback message is only visible when there is `impress-not-supported` class set on the body.
+ See the comment with the body for an explanation.
+ -->
+ <div class="fallback-message">
+ <p>Your browser <b>doesn't support the features required</b> by impress.js, so you are presented with a simplified version of this presentation.</p>
+ <p>For the best experience please use the latest <b>Chrome</b>, <b>Safari</b> or <b>Firefox</b> browser.</p>
+ </div>
<!--
@@ -310,6 +312,21 @@
<div id="overview" class="step" data-x="3000" data-y="1500" data-scale="10">
</div>
+ <!--
+
+ Did you notice this element in the presentation?
+ It is not positioned in any of the slides, but only visible in the overview slide.
+
+ By setting the class to include `positioned`, you can let impress.js know that the element should be
+ put onto the canvas in the place determined by the parameters. All of the positioning parameters work exactly
+ as the ones for the steps, i.e. you can do `data-x`, `data-y`, `data-z`, `data-rotate`, `data-rotate-z`,
+ `data-rotate-x`, `data-rotate-y` and `scale`.
+
+ -->
+ <div id="roamfree" class="positioned" data-x="-1400" data-y="4000" data-rotate="" data-scale="5">
+ By the way: did you notice that you can also position elements freely without creating a slide?
+ </div>
+
</div>
<!--
View
101 js/impress.js
@@ -258,7 +258,8 @@
// root presentation elements
var root = byId( rootId );
- var canvas = document.createElement("div");
+ var canvasScale = document.createElement("div");
+ var canvasRotate = document.createElement("div");
var initialized = false;
@@ -293,24 +294,32 @@
}
};
+ // `getPositionDataFromElement` transforms the data-attributes of an element into
+ // a dictionary that is usable for positioning the element
+ var getPositionDataFromElement = function(el) {
+ var data = el.dataset;
+ var posData = {
+ translate: {
+ x: toNumber(data.x),
+ y: toNumber(data.y),
+ z: toNumber(data.z)
+ },
+ rotate: {
+ x: toNumber(data.rotateX),
+ y: toNumber(data.rotateY),
+ z: toNumber(data.rotateZ || data.rotate)
+ },
+ scale: toNumber(data.scale, 1),
+ el: el
+ };
+ return posData;
+ }
+
// `initStep` initializes given step element by reading data from its
// data attributes and setting correct styles.
var initStep = function ( el, idx ) {
- var data = el.dataset,
- step = {
- translate: {
- x: toNumber(data.x),
- y: toNumber(data.y),
- z: toNumber(data.z)
- },
- rotate: {
- x: toNumber(data.rotateX),
- y: toNumber(data.rotateY),
- z: toNumber(data.rotateZ || data.rotate)
- },
- scale: toNumber(data.scale, 1),
- el: el
- };
+
+ var step = getPositionDataFromElement(el);
if ( !el.id ) {
el.id = "step-" + (idx + 1);
@@ -328,6 +337,20 @@
});
};
+ var initPositionedElement = function(el, idx) {
+
+ var positionData = getPositionDataFromElement(el);
+
+ css(el, {
+ position: "absolute",
+ transform: "translate(-50%,-50%)" +
+ translate(positionData.translate) +
+ rotate(positionData.rotate) +
+ scale(positionData.scale),
+ transformStyle: "preserve-3d"
+ });
+ };
+
// `init` API function that initializes (and runs) the presentation.
var init = function () {
if (initialized) { return; }
@@ -353,12 +376,21 @@
};
windowScale = computeWindowScale( config );
-
- // wrap steps with "canvas" element
- arrayify( root.childNodes ).forEach(function ( el ) {
- canvas.appendChild( el );
+
+ // wrap steps with "canvas" elements
+ // we only wrap '.step' elements here so we can have other elements that don't get transformed inside the impress-root as well, like the fallback message
+ $$(".step", root).forEach(function ( el ) {
+ canvasRotate.appendChild( el );
});
- root.appendChild(canvas);
+
+ // wrap positioned items with canvas elements.
+ // we wrap .positioned items, because we will use those to put them into absolute positions later
+ $$(".positioned", root).forEach(function(el) {
+ canvasRotate.appendChild(el);
+ });
+
+ canvasScale.appendChild(canvasRotate);
+ root.appendChild(canvasScale);
// set initial styles
document.documentElement.style.height = "100%";
@@ -368,20 +400,21 @@
overflow: "hidden"
});
- var rootStyles = {
+ var transformationStyles = {
position: "absolute",
transformOrigin: "top left",
transition: "all 0s ease-in-out",
transformStyle: "preserve-3d"
};
- css(root, rootStyles);
- css(root, {
+ css(canvasScale, transformationStyles);
+ css(canvasScale, {
top: "50%",
left: "50%",
transform: perspective( config.perspective/windowScale ) + scale( windowScale )
});
- css(canvas, rootStyles);
+
+ css(canvasRotate, transformationStyles);
body.classList.remove("impress-disabled");
body.classList.add("impress-enabled");
@@ -389,6 +422,9 @@
// get and init steps
steps = $$(".step", root);
steps.forEach( initStep );
+
+ // get and init positioned elements
+ $$(".positioned", root).forEach(initPositionedElement);
// set a default initial state of the canvas
currentState = {
@@ -486,32 +522,31 @@
onStepLeave(activeStep);
}
- // Now we alter transforms of `root` and `canvas` to trigger transitions.
+ // Now we alter transforms of `canvasScale` and `canvasRotate` to trigger transitions.
//
- // And here is why there are two elements: `root` and `canvas` - they are
+ // And here is why there are two elements: `canvasScale` and `canvasRotate` - they are
// being animated separately:
- // `root` is used for scaling and `canvas` for translate and rotations.
+ // `canvasScale` is used for scaling and `canvasRotate` for translate and rotations.
// Transitions on them are triggered with different delays (to make
// visually nice and 'natural' looking transitions), so we need to know
// that both of them are finished.
- css(root, {
+ css(canvasScale, {
// to keep the perspective look similar for different scales
// we need to 'scale' the perspective, too
transform: perspective( config.perspective / targetScale ) + scale( targetScale ),
transitionDuration: duration + "ms",
transitionDelay: (zoomin ? delay : 0) + "ms"
});
-
- css(canvas, {
+ css(canvasRotate, {
transform: rotate(target.rotate, true) + translate(target.translate),
transitionDuration: duration + "ms",
transitionDelay: (zoomin ? 0 : delay) + "ms"
});
-
+
// Here is a tricky part...
//
// If there is no change in scale or no change in rotation and translation, it means there was actually
- // no delay - because there was no transition on `root` or `canvas` elements.
+ // no delay - because there was no transition on `canvasScale` or `canvasRotate` elements.
// We want to trigger `impress:stepenter` event in the correct moment, so here we compare the current
// and target values to check if delay should be taken into account.
//
Something went wrong with that request. Please try again.