アマゾンの左側ナビゲーションを模倣(丹念に設計されたヒューマンマシンインタラクション)


Demo:http://liuyanzhi08.github.io/jquery/jQuery-menu/index.html
Source:https://github.com/liuyanzhi08/liuyanzhi08.github.io/tree/master/jquery/jQuery-menu
仿亚马逊左侧导航(精心设计的人机交互)_第1张图片
図:左側のナビゲーションバーでは、次の2つの操作が可能です.
  • ナビゲーションタグ
  • を切り替える.
  • マウスをラベルから右側コンテンツ
  • に移動する.
    ユーザがどのような操作を行っているかを判断する根拠はユーザのマウス軌跡であり,マウスが緑の領域を通過すると2の操作を行う可能性が高く,そうでなければ1の操作を行うに違いない.
    そこで、ユーザーのマウスが緑の領域を通過したとき、マウスが通過したナビゲーションラベル(すなわち緑の領域内のナビゲーションラベル)は、すぐにジャンプするのではなく、300 msなどの時間を遅らせてジャンプします.
    300 ms後、マウスが緑の領域を離れた場合、ユーザーが右側のコンテンツに入りたいことを証明します.この場合、ラベルジャンプは行いません.
    具体的な実現に興味のある子供靴はソースコードを見てもいいし、批判も歓迎します.
    <html>
    	<head>
    		<style type="text/css">
    			.menu-nav, .menu-panel{float: left;}
    			.menu-nav-item{width: 150px;height: 30px;line-height: 30px;text-align: center;background: #eee;margin-bottom: 2px;cursor: default;}
    			.menu-nav-item-hover{background: #bbb;}
    			.menu-nav-item-on{background: #999;}
    			.menu-panel{position: relative;width: 500px;padding-left: 20px;height: 500px;overflow: hidden;}
    			.menu-panel-item{position: absolute;background: white;display: none;}
    			.menu-panel-item img{height: 317px;}
    			.menu-panel-item-on{display: block;}
    		</style>
    	</head>
    	<body>
    		<div class="menu">
    			<div class="menu-nav">
    				<div class="menu-nav-item">menu-1</div>
    				<div class="menu-nav-item">menu-2</div>
    				<div class="menu-nav-item">menu-3</div>
    				<div class="menu-nav-item">menu-4</div>
    				<div class="menu-nav-item">menu-5</div>
    				<div class="menu-nav-item">menu-6</div>
    				<div class="menu-nav-item">menu-7</div>
    				<div class="menu-nav-item">menu-8</div>
    				<div class="menu-nav-item">menu-9</div>
    				<div class="menu-nav-item">menu-10</div>
    			</div>
    			<div class="menu-panel">
    				<div class="menu-panel-item menu-panel-item-on"><img src="img/1.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/2.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/3.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/4.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/5.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/6.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/7.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/8.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/9.jpg" /></div>
    				<div class="menu-panel-item"><img src="img/10.jpg" /></div>
    			</div>
    		</div>
    		<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    		<script type="text/javascript" src="jquery.menu.js"></script>
    		<script type="text/javascript" src="jquery.menu.amazing.js"></script>
    		<script type="text/javascript">
    			var menu = $.Menu({
    				menu: 'menu',
    				panels: 'menu-panel-item',
    				navOn: 'menu-nav-item-on',
    				panelOn: 'menu-panel-item-on',
    				plugins: [
    					$.MenuAmazing()
    				]
    			})
    
    		</script>
    	</body>
    </html>
    /**
     * jQuery Menu plugin
     * 
     * @author lyz
     * @email 702368372#qq.com
     * @version 1.0
     * 
     * Licensed under the MIT License.
     */
    (function ($, window, undefined) {
    	var menu, panels, target, className, index, navOn, panelOn, me, i, reg;
    
    	function Menu (config) {
    		me = this;
    		if (me == $) {
    			return new Menu(config);
    		}
    
    		var DEFAULT = {
    			menu: 'menu',
    			nav: 'menu-nav',
    			navs: 'menu-nav-item',
    			panels: 'menu-panel-item',
    			navHover: 'menu-nav-item-hover',
    			navOn: 'menu-nav-item-on',
    			panelOn: 'menu-panel-item-on',
    			delay: 300,
    			plugins: []
    		}
    		me.config = $.extend(DEFAULT, config, {});
    
    		me.menu = $('.' + me.config.menu);
    		me.nav = $('.' + me.config.nav);
    		me.navs = $('.' + me.config.navs);
    		me.panels = $('.' + me.config.panels);
    
    		me.menu.mouseover (function (e) {
    			target = e.target;
    			className = target.className;
    			target = $(target);
    			index = target.index();
    			reg = new RegExp(me.config.navs);
    
    			if (reg.test(className)) {
    				me.navSwitchTo(index);
    				me.panelSwitchTo(index);
    			}
    		})
    
    		for (i = 0; i < me.config.plugins.length; i++) {
    			me.config.plugins[i].init(me);
    		}
    	}
    
    	Menu.prototype.navAttemptSwitchTo = function (index) {
    		me = this;
    		me.navs.removeClass(me.config.navHover)
    		       .eq(index).addClass(me.config.navHover);
    	}
    
    	Menu.prototype.navSwitchTo = function (index) {
    		me = this;
    		me.navs.removeClass(me.config.navOn + ' ' + me.config.navHover)
    		       .eq(index).addClass(me.config.navOn);
    	}
    
    	Menu.prototype.panelSwitchTo = function (index) {
    		me = this;
    		clearTimeout(me.panelTimer);
    
    		me.panels.removeClass(me.config.panelOn)
    		         .eq(index).addClass(me.config.panelOn);
    		me.navSwitchTo(index);
    	};
    
    	Menu.prototype.panelAttemptSwitchTo = function (index) {
    		me = this;
    		clearTimeout(me.panelTimer);
    
    		me.panelTimer = setTimeout( function () {
    			me.panelSwitchTo(index);
    		}, me.config.delay)
    		me.navAttemptSwitchTo(index);
    	};
    	
    	$.Menu = Menu;
    
    } (jQuery, this, undefined))
    /**
     * Plugin for jQuery-menu which acts similar to amazon's leftside nav
     * 
     * @author lyz
     * @email 702368372#qq.com
     * @version 1.0
     * 
     * Licensed under the MIT License.
     */
    (function ($, window, undefined) {
    	var start, end, slope, liveSlope, target, className, index, reg, ret, paths = [];
    
    	function MenuAmazing () {
    		me = this;
    		if (me == $) {
    			return new MenuAmazing();
    		}
    	}
    
    	/**
    	 * Init plugin
    	 * @param  {object} host 
    	 */
    	MenuAmazing.prototype.init = function (host) {
    		slope = host.nav.outerHeight() / host.nav.outerWidth();
    		host.menu.unbind('mouseover'); 
    
    		host.menu.mouseover( function (e) {
    			target = e.target;
    			className = target.className;
    			target = $(target);
    			index = target.index();
    			reg = new RegExp(host.config.navs);
    			if (reg.test(className)) {
    				if (isSwitch()) {
    					host.panelSwitchTo(index);
    				} else {
    					host.panelAttemptSwitchTo(index);
    				}
    			}
    		});
    
    		host.nav.mouseleave( function () {
    			clearTimeout(host.panelTimer);
    			host.navs.removeClass(host.config.navHover);
    		})
    	}
    
    	/**
    	 * Is swiching immediately or lazily
    	 * @return {Boolean} yes or not
    	 */
    	function isSwitch () {
    		start = paths[0] || {x: 0, y: 0};
    		end = paths[paths.length-1] || {x: 0, y: 0};
    		liveSlope = Math.abs(end.y - start.y) / Math.abs(end.x - start.x);
    		inTriangle = end.x > start.x; // In the first quadrant or the forth quadrant
    
    		if (!inTriangle && liveSlope > slope) {
    			ret = true;
    		} else {
    			ret = false;
    		}
    		return ret;
    	}
    
    	/**
    	 * Mark mouse path
    	 */
    	$(document).mousemove (function (e) {
    		if (paths.length == 3) {
    			paths.shift();
    		}
    		paths.push({x: e.pageX, y: e.pageY});
    	})
    
    	$.MenuAmazing = MenuAmazing;
    
    } (jQuery, this, undefined))