ImageGrid/ui/experiment-ribbon-navigation-n-zoom.html
Alex A. Naanou 5d78b6bf81 fixed several bugs...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2012-07-19 17:35:15 +04:00

429 lines
10 KiB
HTML
Executable File

<!DOCTYPE html>
<html>
<body>
<!--
Goals:
- design a simple navigation system and structure
- make it animate correctly only via CSS
-->
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$('.square').click(squareClick)
containerSize(300, 200)
$('.current.square').click()
})
// XXX need to make this work for % values...
function containerSize(W, H){
var oW = $('.meta-container').width()
var oH = $('.meta-container').height()
var zoom = $('.container').css('zoom')
$('.meta-container').css({
'width': W,
'height': H
})
// shift the field...
$('.container').css({
// compensate top/left that get changed while zooming....
'top': H/2 * 1/zoom - H/2,
'left': W/2 * 1/zoom - W/2,
'margin-top': (parseFloat($('.container').css('margin-top')) + (H-oH)/2),
'margin-left': (parseFloat($('.container').css('margin-left')) + (W-oW)/2)
})
}
function squareClick(){
// set classes...
$('.current').removeClass('current')
$(this)
.addClass('current')
.parents('.ribbon')
.addClass('current')
// position the container and ribbons...
centerSquare()
}
/*
* The folowing two functions will get the vertical and horizontal
* distance components between the pints a and A, centers of the small
* and large squares respectively.
* One of the squares is .container and the other is .meta-container,
* which is small or big is not important.
*
* +---------------+-------+
* | | |
* | | |
* | + a . . | . . . | . +
* | . | | +- getCurrentVerticalOffset(...)
* | . + A | . . . | . +
* +---------------+ |
* | . . |
* | . . |
* | . . |
* +-----------------------+
* . .
* +-+-+
* +------------------- getCurrentHorizontalOffset(...)
*
*
* Adding this distance to margins of one of the sqares will effectively
* allign the two points.
*
* NOTE: neither function accunts for container margins.
*
*/
// get the vertical offset of the center of square from center of meta-container
// NOTE: this does not account for container margins
function getCurrentVerticalOffset(square){
if(square == null){
square = $('.square.current')
}
var zoom = $('.container').css('zoom')
var ribbons = $('.ribbon')
var ribbon = square.parents('.ribbon')
var squares = ribbon.children('.square')
// vertical...
var H = $('.meta-container').height()
var h = ribbons.outerHeight(true)
// margin...
var mh = h - ribbons.outerHeight()
// current ribbon position (1-based)
var rn = ribbons.index(ribbon) + 1
// XXX compensating for margin error buildup... really odd!
// ...why is this still different for the first three ribbons?!
// ....sub-pixel error?
// relative position to container...
// XXX is there a better way to get this?
var t = rn * (h - mh/2)
return -t + H/2 + h/2
}
// get the horizontal offset of the center of square from center of meta-container
// NOTE: this does not account for container margins
function getCurrentHorizontalOffset(square){
if(square == null){
square = $('.square.current')
}
var zoom = $('.container').css('zoom')
var ribbon = square.parents('.ribbon')
var squares = ribbon.children('.square')
var W = $('.meta-container').width()
var w = squares.outerWidth(true)
// margin...
// XXX do we need this?
var mw = w - squares.outerWidth()
// current square position (1-based)
var sn = squares.index(square) + 1
var l = sn * (w - mw/2)
return -l + W/2 + w/2
}
function centerSquare(){
$('.container').css({
'margin-top': getCurrentVerticalOffset()
})
// horizontal...
alignRibbon()
}
function alignRibbon(square, position){
// default values...
if(square == null){
square = $('.square.current')
}
if(position == null){
position = 'center'
}
var ribbon = square.parents('.ribbon')
// account for margined container...
// NOTE: this enables us to cheat and shift all the ribbons just
// by changing container margin-left...
var cml = parseFloat($('.container').css('margin-left'))
if(!cml){
cml = 0
}
var h_offset = getCurrentHorizontalOffset(square) - cml
var w = $('.square').outerWidth(true)
switch(position){
case 'before':
ribbon.css({'margin-left': h_offset + w/2})
return true
case 'center':
ribbon.css({'margin-left': h_offset})
return true
case 'after':
ribbon.css({'margin-left': h_offset - w/2})
return true
}
return false
}
// XXX need to fix animation jumping around...
// XXX try transition-origin instead of compensating by moving...
function zoomContainerBy(factor){
var zoom = $('.container').css('zoom')*factor
setContainerZoom(zoom)
}
function setContainerZoom(zoom){
var H = $('.meta-container').height()
var W = $('.meta-container').width()
$('.container').css({
'zoom': zoom,
// this only shifts to account for zoom/scale change...
// ...we need to factor in the position of .current within the container
'top': H/2 * 1/zoom - H/2,
'left': W/2 * 1/zoom - W/2
})
}
function fitImage(){
var H = $('.meta-container').height()
var W = $('.meta-container').width()
var h = $('.square.current').height()
var w = $('.square.current').width()
var f = Math.min(H/h, W/w)
setContainerZoom(f)
}
function fitThreeImages(){
var H = $('.meta-container').height()
var W = $('.meta-container').width()
var h = $('.square.current').height()
// XXX cheating, need to get three widths...
var w = $('.square.current').width()*3
var f = Math.min(H/h, W/w)
setContainerZoom(f)
}
</script>
<style>
.animated {
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.meta-container {
position: relative;
border: solid gray 5px;
width: 300px;
height: 200px;
overflow: hidden;
}
.h-marker {
position: absolute;
border-top: solid blue 1px;
height: 0px;
width: 100%;
top: 50%;
left: 0px;
}
.v-marker {
position: absolute;
border-left: solid blue 1px;
height: 100%;
width: 0px;
top: 0px;
left: 50%;
}
.container {
position: relative;
top: 0px;
left: 0px;
/* set this to adjust the vertical position of the view... */
margin-top: -50px;
/* animate */
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
zoom: 1;
}
.ribbon {
height: 50px;
/* HACK: need to figure out a way to avoid setting the width here... */
width: 1000px;
margin-top: 5px;
margin-bottom: 5px;
/* animate */
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.square {
width: 50px;
height: 50px;
background: silver;
color: white;
float: left;
/* animate */
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.image {
background: no-repeat 50% black;
background-size: contain;
background-image: url(images/350px/DSC_3501.jpg);
}
.current.square {
background-color: gray;
}
</style>
Zoom: <button onclick="zoomContainerBy(2)">+</button>
<button onclick="zoomContainerBy(0.5)">-</button>
<button onclick="setContainerZoom(1)">Original</button>
<button onclick="fitImage()">Image</button>
<button onclick="fitThreeImages()">Three</button>
<br>
Size:
<button onclick="containerSize($('.meta-container').width()*1.5, $('.meta-container').height()*1.5)">+</button>
<button onclick="containerSize($('.meta-container').width()*0.75, $('.meta-container').height()*0.75)">-</button>
<button onclick="containerSize(300, 200)">300x200</button>
<button onclick="containerSize(600, 400)">600x400</button>
<br>
<br>
<div class="meta-container animated">
<div class="container">
<div class="ribbon">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon" style="margin-left: 40px;">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon current">
<div class="square">1</div>
<div class="square">2</div>
<div class="square current">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon" style="margin-left: -100px;">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square image">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
<div class="ribbon">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
</div>
</div>
<div class="h-marker"></div>
<div class="v-marker"></div>
</div>
</body>
</html>