mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 11:20:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			452 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			452 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
| <!DOCTYPE html>
 | |
| <html>
 | |
| <body>
 | |
| 
 | |
| <!--
 | |
| 
 | |
| Goals:
 | |
| 	- design a simple navigation system and structure
 | |
| 	- make it animate correctly only via CSS
 | |
| 
 | |
| XXX zoom animation is odd...
 | |
| 
 | |
| -->
 | |
| 
 | |
| <script src="jquery.js"></script>
 | |
| <script>
 | |
| 
 | |
| $(document).ready(function(){
 | |
| 	$('.square').click(squareClick)
 | |
| 
 | |
| 	containerSize(300, 200)
 | |
| 
 | |
| 	$('.current.square').click()
 | |
| })
 | |
| 
 | |
| function toggleMarkers(){
 | |
| 	var marker = $('.v-marker, .h-marker')
 | |
| 	if(marker.css('display') == 'none'){
 | |
| 		marker.fadeIn()
 | |
| 	} else {
 | |
| 		marker.fadeOut()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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 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)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| 
 | |
| /*********************************************************************/
 | |
| 
 | |
| // 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>
 | |
| 
 | |
| Guides:
 | |
| <button onclick="toggleMarkers()">Toggle Guides</button>
 | |
| <br>
 | |
| 
 | |
| 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>
 |