3D галерея

В данном уроке приводится код 3D галереи которая может стать отличным инструментом для представления портфолио работ. Изображения размещаются в папке images и при запуске скрипта их надо указать для загрузки. Кроме того, к изображению можно привязать ссылку, которая работает и как подпись к картинке. Таким образом 3D галерея может стать основой оригинальной навигации по сайту.

Галерея использует средства только JavaScript, без подключения каких-либо библиотек.

HTML
 	<div id="screen">
	    <div id="command">
 	        <h1>3D галерея</h1>
 	        <div id="bar"></div>
 	    </div>
 	    <div id="urlInfo"></div>
 	</div>


Элемент div screen содержит всю галерею. Элемент div command содержит подпись и панель управления галереей div bar. Элемент div urlInfo будет выводить на ссылку, привязанную к изображению.
CSS
	html {
 	 overflow: hidden;
 	}
 	body {
 	 position: absolute;
 	 margin: 0px;
 	 padding: 0px;
 	 background: #eee;
 	 width: 100%;
	 height: 100%;
 	 color: #fff;
 	 font-family: arial;
 	 font-size: 0.8em;
 	}
 	#screen {
 	 position: absolute;
 	 width: 100%;
	 height: 100%;
 	 background: #000;
 	 overflow: hidden;
 	}
 	#screen img, canvas {
 	 position: absolute;
 	 left: -9999px;
 	 cursor: pointer;
 	       image-rendering: optimizeSpeed;
	 
 	}
 	#screen .href {
 	 border: #FFF dotted 1px;
 	}
 	#screen .fog {
 	 position: absolute;
 	 background: #fff;
	 opacity: 0.1;
 	 filter: alpha(opacity=10);
 	}
 	#command {
 	 position:absolute;
 	 left: 1em;
 	 top: 1em;
 	 width: 130px;
 	 z-index: 30000;
 	 background:#000;
 	 border: #000 solid 1em;
 	}
 	#bar {
 	 position:relative;
 	 left: 1em;
 	 top: 1em;
 	 height: 160px;
 	}
 	#bar .button {
 	 position: absolute;
 	 background: #222;
 	 width: 20px;
 	 height: 20px;
 	 cursor: pointer;
 	}
 	#bar .loaded {
 	 background: #666;
 	}
 	#bar .viewed {
 	 background: #fff;
 	}
 	#bar .selected {
 	 background: #f00;
 	}
 	#urlInfo {
 	 position: absolute;
	 background: url(images/r.gif) no-repeat 0 4px;
 	 visibility: hidden;
 	 z-index: 30000;
 	 padding-left: 12px;
 	 cursor: pointer;
 	}

JavaScript

Скрипт:
 	var m3D = function () {
 	    /* ---- Переменные ---- */
 	    var diapo = [],
 	        imb,
 	        scr,
 	        bar,
 	        selected,
	        urlInfo,
 	        imagesPath = "images/",
 	        camera = {x:0, y:0, z:-650, s:0, fov: 500},
 	        nw = 0,
 	        nh = 0;
 	    /* ==== метод сдвоенной камеры ==== */
 	    camera.setTarget = function (c0, t1, p) {
 	        if (Math.abs(t1 - c0) > .1) {
 	            camera.s = 1;
	            camera.p = 0;
 	            camera.d = t1 - c0;
 	            if (p) {
 	                camera.d *= 2;
 	                camera.p = 9;
 	            }
 	        }
 	    }
 	    camera.tween = function (v) {
 	        if (camera.s != 0) {
 	            camera.p += camera.s;
 	            camera[v] += camera.d * camera.p * .01;
 	            if (camera.p == 10) camera.s = -1;
 	            else if (camera.p == 0) camera.s = 0;
 	        }
 	        return camera.s;
 	    }
 	    /* ==== Конструктор diapo ==== */
 	    var Diapo = function (n, img, x, y, z) {
 	        if (img) {
 	            this.url = img.url;
 	            this.title = img.title;
 	            this.color = img.color;
 	            this.isLoaded = false;
 	            if (document.createElement("canvas").getContext) {
 	                /* ---- используем элемент canvas вместо изображения (трюк для производительности) ---- */
 	                this.srcImg = new Image();
 	                this.srcImg.src = imagesPath + img.src;
 	                this.img = document.createElement("canvas");
 	                this.canvas = true;
 	                scr.appendChild(this.img);
 	            } else {
 	                /* ---- обычное изображение ---- */
 	                this.img = document.createElement('img');
 	                this.img.src = imagesPath + img.src;
 	                scr.appendChild(this.img);
 	            }
	            /* ---- обработка событие onclick ---- */
 	            this.img.onclick = function () {
 	                if (camera.s) return;
 	                if (this.diapo.isLoaded) {
	                    if (this.diapo.urlActive) {
 	                        /* ---- гиперссылка для перехода ---- */
 	                        top.location.href = this.diapo.url;
 	                    } else {
 	                        /* ---- позиционирование цели ---- */
	                        camera.tz = this.diapo.z - camera.fov;
 	                        camera.tx = this.diapo.x;
	                        camera.ty = this.diapo.y;
	                        /* ---- disable previously selected img ---- */
 	                        if (selected) {
 	                            selected.but.className = "button viewed";
 	                            selected.img.className = "";
 	                            selected.img.style.cursor = "pointer";
 	                            selected.urlActive = false;
 	                            urlInfo.style.visibility = "hidden";
 	                        }
 	                        /* ---- выбираем текущее изображение ---- */
 	                        this.diapo.but.className = "button selected";
 	                        interpolation(false);
	                        selected = this.diapo;
 	                    }
 	                }
 	            }
 	            /* ---- кнопки панели управления ---- */
 	            this.but = document.createElement('div');
 	            this.but.className = "button";
 	            bar.appendChild(this.but);
 	            this.but.diapo = this;
 	            this.but.style.left = Math.round((this.but.offsetWidth  * 1.2) * (n % 4)) + 'px';
 	            this.but.style.top  = Math.round((this.but.offsetHeight * 1.2) * Math.floor(n / 4)) + 'px';
 	            this.but.onclick = this.img.onclick;
 	            imb = this.img;
 	            this.img.diapo = this;
 	            this.zi = 25000;
 	        } else {
 	            /* ---- прозрачный элемент div ---- */
	            this.img = document.createElement('div');
 	            this.isLoaded = true;
 	            this.img.className = "fog";
 	            scr.appendChild(this.img);
 	            this.w = 300;
 	            this.h = 300;
 	            this.zi = 15000;
 	        }
 	        /* ---- перменные объекта ---- */
 	        this.x = x;
 	        this.y = y;
 	        this.z = z;
 	        this.css = this.img.style;
 	    }
 	    /* ==== основная 3D анимация ==== */
 	    Diapo.prototype.anim = function () {
 	        if (this.isLoaded) {
 	            /* ---- от 3D к 2D проекции ---- */
 	            var x = this.x - camera.x;
 	            var y = this.y - camera.y;
 	            var z = this.z - camera.z;
 	            if (z < 20) z += 5000;
 	            var p = camera.fov / z;
 	            var w = this.w * p;
 	            var h = this.h * p;
 	            /* ---- рисуем HTML  ---- */
 	            this.css.left   = Math.round(nw + x * p - w * .5) + 'px';
 	            this.css.top    = Math.round(nh + y * p - h * .5) + 'px'; 
 	            this.css.width  = Math.round(w) + 'px';
 	            this.css.height = Math.round(h) + 'px';
 	            this.css.zIndex = this.zi - Math.round(z);
 	        } else {
 	            /* ---- изображение загружено? ---- */
 	            this.isLoaded = this.loading();
 	        }
 	    }
 	    /* ==== инициализация при загрузке ==== */
 	    Diapo.prototype.loading = function () {
 	        if ((this.canvas && this.srcImg.complete) || this.img.complete) {
 	            if (this.canvas) {
	                /* ---- версия с элементом canvas ---- */
 	                this.w = this.srcImg.width;
 	                this.h = this.srcImg.height;
 	                this.img.width = this.w;
 	                this.img.height = this.h;
 	                var context = this.img.getContext("2d");
 	                context.drawImage(this.srcImg, 0, 0, this.w, this.h);
 	            } else {
 	                /* ---- версия с обычным изображением ---- */
 	                this.w = this.img.width;
 	                this.h = this.img.height;
 	            }
 	            /* ---- кнопка загружена ---- */
 	            this.but.className += " loaded";
 	            return true;
 	        }
 	        return false;
 	    }
 	    ////////////////////////////////////////////////////////////////////////////
 	    /* ==== размеры экрана ==== */
 	    var resize = function () {
 	        nw = scr.offsetWidth * .5;
 	        nh = scr.offsetHeight * .5;
 	    }
 	    /* ==== отключаем интерполяцию во время анимации ==== */
 	    var interpolation = function (bicubic) {
 	        var i = 0, o;
 	        while( o = diapo[i++] ) {
 	            if (o.but) {
 	                o.css.msInterpolationMode = bicubic ? 'bicubic' : 'nearest-neighbor'; // makes IE8 happy
 	                o.css.imageRendering = bicubic ? 'optimizeQuality' : 'optimizeSpeed'; // does not really work...
 	            }
	        }
 	    }
 	    /* ==== скрипт инициализации ==== */
 	    var init = function (data) {
 	        /* ---- контейнеры ---- */
 	        scr = document.getElementById("screen");
 	        bar = document.getElementById("bar");
 	        urlInfo = document.getElementById("urlInfo");
 	        resize();
 	        /* ---- загрузка изображений ---- */
 	        var i = 0,
 	            o,
 	            n = data.length;
 	        while( o = data[i++] ) {
 	            /* ---- изображения ---- */
 	            var x = 1000 * ((i % 4) - 1.5);
 	            var y = Math.round(Math.random() * 4000) - 2000;
 	            var z = i * (5000 / n);
 	            diapo.push( new Diapo(i - 1, o, x, y, z));
 	            /* ---- прозрачные рамки ---- */
 	            var k = diapo.length - 1;
 	            for (var j = 0; j < 3; j++) {
 	                var x = Math.round(Math.random() * 4000) - 2000;
 	                var y = Math.round(Math.random() * 4000) - 2000;
 	                diapo.push( new Diapo(k, null, x, y, z + 100));
 	            }
 	        }
 	        /* ---- запуск движка ---- */
	        run();
 	    }
	    ////////////////////////////////////////////////////////////////////////////
 	    /* ==== основной цикл ==== */
 	    var run = function () {
 	        /* ---- пермещение по оси x ---- */
 	        if (camera.tx) {
 	 
 	            if (!camera.s) camera.setTarget(camera.x, camera.tx);
 	            var m = camera.tween('x');
 	            if (!m) camera.tx = 0;
 	        /* ---- перемещение по оси y ---- */
 	        } else if (camera.ty) {
 	            if (!camera.s) camera.setTarget(camera.y, camera.ty);
 	            var m = camera.tween('y');
 	            if (!m) camera.ty = 0;
 	        /* ---- перемещение по оси z ---- */
 	        } else if (camera.tz) {
 	            if (!camera.s) camera.setTarget(camera.z, camera.tz);
 	            var m = camera.tween('z');
 	            if (!m) {
 	                /* ---- конец анимации ---- */
 	                camera.tz = 0;
 	                interpolation(true);
 	                /* ---- активируем гиперссылку ---- */
 	                if (selected.url) {
 	                    selected.img.style.cursor = "pointer";
 	                    selected.urlActive = true;
 	                    selected.img.className = "href";
 	                    urlInfo.diapo = selected;
 	                    urlInfo.onclick = selected.img.onclick;
	                    urlInfo.innerHTML = selected.title || selected.url;
 	                    urlInfo.style.visibility = "visible";
 	                    urlInfo.style.color = selected.color || "#fff";
 	                    urlInfo.style.top = Math.round(selected.img.offsetTop + selected.img.offsetHeight - urlInfo.offsetHeight - 5) + "px";
 	                    urlInfo.style.left = Math.round(selected.img.offsetLeft + selected.img.offsetWidth - urlInfo.offsetWidth - 5) + "px";
 	                } else {
 	                    selected.img.style.cursor = "default";
 	                }
 	            }
 	        }
 	        /* ---- анимация изображения ---- */
 	        var i = 0, o;
 	        while( o = diapo[i++] ) o.anim();
 	        /* ---- цикл ---- */
 	        setTimeout(run, 32);
 	    }
 	    return {
 	        ////////////////////////////////////////////////////////////////////////////
	        /* ==== скрипт инициализации ==== */
 	        init : init
 	    }
 	}();

Инициализация скрипта осуществляется следующим образом:
 	setTimeout(function() {
 	    m3D.init(
 	        [
 	            { src: '46eae50db6.jpg', url: 'http://ruseller.com', title: 'Переход на сайт RUSELLER.COM', color: '#fff' },
 	            { src: '1ef7ea6559.jpg' },
 	            { src: '8fe86226ff.jpg' },
 	            { src: '69833ed09a.jpg' },
 	            { src: 'fe00425d0a.jpg' },
 	            { src: 'b05b0c6962.jpg' },
 	            { src: '6a884d6ef2.jpg' },
 	            { src: 'ed57bce8c4.jpg' },
 	            { src: '94da4fb185.jpg' },
 	            { src: 'd04505fe96.jpg' },
 	            { src: '46eae50db6.jpg', url: 'http://ruseller.com', title: 'Переход на сайт RUSELLER.COM', color: '#fff' },
 	            { src: '1ef7ea6559.jpg' },
 	            { src: '8fe86226ff.jpg' },
 	            { src: '69833ed09a.jpg' },
 	            { src: 'fe00425d0a.jpg' },
 	            { src: 'b05b0c6962.jpg' },
 	            { src: '6a884d6ef2.jpg' },
 	            { src: 'ed57bce8c4.jpg' },
 	            { src: '94da4fb185.jpg' },
 	            { src: 'd04505fe96.jpg' },
 	            { src: '46eae50db6.jpg', url: 'http://ruseller.com', title: 'Переход на сайт RUSELLER.COM', color: '#fff' },
 	            { src: '1ef7ea6559.jpg' },
 	            { src: '8fe86226ff.jpg' },
 	            { src: '69833ed09a.jpg' },
 	        ]
 	    );
 	}, 500);
Добавлено: 16 Августа 2013 09:25:08 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...