页面效果简单做(一)

简介:有自己写的,也有网上看到的,即使是别人写的也会对其改动,或添加注释,并保持统一的编码风格,便于阅读。目标是不用第三方库即可完成(浏览器原生),简单做,能够阐述逻辑和原理清楚即可,因此可能考虑不是最周详的,包括跨浏览器的问题,如果你打算使用在项目中使用最好测试清楚,还可能要进一步修改之。

注意:打算提供在线例子的,但短时间内没有静态空间,所以例子的事情要稍等一阵子。已提供在线例子。

1、简易拖放效果

使用了 DOM 1 的方式登记事件,其实无必要 DOM Level 2 的 addEventListener,因为根据鼠标事件,同一时刻通常 document 只有一个 mousemove/mouseup 事件。点击查看例子。

<meta charset="utf-8" />  
<title>拖放 DD</title>  
<script>   
    SimpleDrag = function(el) {  
        this.el = el;  
        this._x = this._y = 0;  
        el.onmousedown = delegate(this, this.start);  
        this.move = delegate(this, this.move);  
          
        function delegate(object, fn){ // 绑定当前 this,并且修正浏览器兼容问题 e ||  window.event
            return function(e) {    
                return fn.call(object, (e || window.event));    
            }  
        }  
    };  
    SimpleDrag.prototype = {  
        start : function(e) {  
            this._x = e.clientX - this.el.offsetLeft;  
            this._y = e.clientY - this.el.offsetTop;  
            document.onmousemove = this.move;  
            document.onmouseup = this.stop;  
        },  
        // 拖动    
        move : function(e) {  
            this.el.style.left = e.clientX - this._x + "px";  
            this.el.style.top  = e.clientY - this._y + "px";  
        },  
        // 停止拖动    
        stop : function() {  
            document.onmousemove = document.onmouseup = null;  
        }  
    };  
</script>  
<style>  
    .dragable{  
        background-color:#C4E3FD;   
        width:50px; height:50px;  
        position:absolute;  
        left: 20px;  
        cursor:move;  
    }  
    .dragEl_1{  
        top : 10px;  
        border:5px solid blue;   
    }  
    .dragEl_2{  
        top : 80px;  
        border:5px solid red;   
    }  
</style>  
<div class="dragable dragEl_1">1</div>    
<div class="dragable dragEl_2">2</div>    
<script>  
    new SimpleDrag(document.querySelector(".dragEl_1"));    
    new SimpleDrag(document.querySelector(".dragEl_2"));    
</script> 

2、上下滚动内容

原理是取出最尾元素放到前头。点击查看例子。

<html>  
<head>  
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
	<title>上下滚动内容</title>  
</head>  
<body>  
	<ul id="scroll">  
		<li>11111111111</li>  
		<li>22222222222</li>  
		<li>33333333333</li>  
		<li>44444444444</li>  
		<li>55555555555</li>  
		<li>66666666666</li>  
		<li>77777777777</li>  
		<li>88888888888</li>  
		<li>99999999999</li>  
		<li>00000000000</li>  
	</ul>  
	  
	  
	<ol id="scrollA">  
		<li>11111111111</li>  
		<li>22222222222</li>  
		<li>33333333333</li>  
		<li>44444444444</li>  
		<li>55555555555</li>  
		<li>66666666666</li>  
		<li>77777777777</li>  
		<li>88888888888</li>  
		<li>99999999999</li>  
		<li>00000000000</li>  
	</ol>  
	
	<script>
		/**
		 * @param {Element} el 列表元素
		 * @param {Number} interval 动画时间间隔
		 * @param {Boolean} canstop 是否可以鼠标移入时候暂停动画
		 */
		function ScrollContent(el, interval, canstop) {
			interval = interval || 3000;
			canstop  = canstop  || false;
			
			function scroll() {
				var lastEl = el.firstChild;
				while (lastEl.nodeType != 1)  // 找到最后一个元素
					lastEl = lastEl.nextSibling;
				
				el.appendChild(el.removeChild(lastEl)); // 把最后一个元素放到前头
			}

			var t = window.setInterval(scroll, interval);

			if (canstop) {
				el.onmouseover = function() {
					if (t) window.clearInterval(t);
				}
				el.onmouseout = function() {
					t = window.setInterval(scroll, interval);
				}
			}
		}
		
		new ScrollContent(document.getElementById('scroll'), 1000);
		new ScrollContent(document.getElementById('scrollA'), 500, true);
	</script>
</body>  
</html> 

3、左右滚动内容

原理跟前者一样,只不过是把元素换为字符串,应该是更简单的了。点击查看在线例子。



<meta charset="utf-8" />
<title>水平字幕滚动</title>

<div class="content1">这是一段滚动的文字11111111</div>
<div class="content2">这是一段滚动的文字22222222</div>
<script>
	/**
	 * @param {Element} el 列表元素
	 * @param {Number} interval 动画时间间隔
	 * @param {Boolean} canstop 是否可以鼠标移入时候暂停动画
	 */
	function ScrollContent_Hoz(el, interval, canstop) {
		interval = interval || 500;
		canstop  = canstop  || false;
		var arr = el.innerHTML.split("");
		function scroll() {
			arr.push(arr.shift());
			el.innerHTML = arr.join("");
		}

		var t = window.setInterval(scroll, interval);

		if (canstop) {
			el.onmouseover = function() {
				if (t) window.clearInterval(t);
			}
			el.onmouseout = function() {
				t = window.setInterval(scroll, interval);
			}
		}
	}
	 
	new ScrollContent_Hoz(document.querySelector('.content1'));
	new ScrollContent_Hoz(document.querySelector('.content2'), null, true);
</script>

4、多级联动下拉菜单

联动本身并无多大难点,只是 onchange 事件的运用即可。值得一提的是这个演示了日历控件所涉及的日历生成算法——当然这是后话了。点击查看在线例子。

<meta charset="UTF-8">
<title>联动 Select 下拉</title>
<select id="year">
	<option value="0">--请选择--</option>
</select>年
<select id="month">
	<option value="0">--请选择--</option>
</select>月
<select id="day">
	<option value="0">--请选择--</option>
</select>日

<script>
	function initSelect(selectEl, i, end) {
		selectEl.length = 1;
		for (; i <= end; i++) {
			try {
				selectEl.add(new Option(i, i), null);
			} catch (e) {
				selectEl.add(new Option(i, i));
			}
		}
	}
	var year = document.getElementById("year");
	var month = document.getElementById("month");
	var day = document.getElementById("day");
	
	initSelect(year, 1970, 2012);
	
	year.onchange = function() {
		if (this.value != 0) {
			initSelect(month, 1, 12);
		} else {
			month.length = 1;
			day.length = 1;
		}
	}
	month.onchange = function() {
		if (this.value != 0) {
			var m30 = {
				2 : 1,
				4 : 1,
				6 : 1,
				9 : 1,
				11 : 1
			};
			if (this.value == 2) { // 二月份特别处理
				if (isLeapYear(year.value)) 
					 initSelect(day, 1, 29);
				else initSelect(day, 1, 28);
			} else if (this.value in m30) // 三十天的月份
			/*
			因为2、4、6、9、11月份都是30天,如果把它们放在一个数组中,那么还要遍历来判断是否相等,则比较麻烦了,于是在这里把这些都当成对象来处理,使用 in 判断即可
			*/
					 initSelect(day, 1, 30);
			else 	 initSelect(day, 1, 31);
		} else day.length = 1;
	}
	// 判断闰年的条件:能被4整除且不能被100整除 或 能被100整除且能被400整除
	function isLeapYear(y) {
		return (y % 4 == 0 && y % 100 != 0)
			|| (y % 100 == 0 && y % 400 == 0);
	}
</script>

5、Tab 多选项卡

主要控制 tab display:block/none 来显示与隐藏,原理比较简单。使用方法:new SimpleTab(document.querySelector('.tab2')).jump(0);。点击查看在线例子。

代码比较长,所以只贴 JS 部分。完整代码参见 HTML。

/--------------------公共方法 -------------START
var emptyStr = '';
// 允许用户输入 .abc/abc 的 CSS Selector,推荐 abc 即可
function removeFirstDot(str){
	if(str && str.charAt(0) === '.'){
		var arr = str.split(emptyStr);
		arr.shift();
		return arr.join(emptyStr);
	}
	
	return str;
}
	
/**
 * 增加元素样式。
 * @param {String} cls
 */
Element.prototype.addCls = function (cls) {
	cls = removeFirstDot(cls);

	var _cls = this.className;
	if (_cls.indexOf(cls) === -1) {
		// not found, so add it
		if (_cls === '')this.className = cls;
		else this.className += ' ' + cls;
	}
}

/**
 * 移除元素样式。
 * @param {String} cls
 */
Element.prototype.removeCls = function (cls) {
	cls = removeFirstDot(cls);
	var _cls = this.className;
	var reg = new RegExp('\\s?\\b' + cls + '\\b', 'ig');
	if (reg.test(_cls)) 
		this.className = _cls.replace(reg, '');// remove it
}
 
/--------------------公共方法 -------------END

SimpleTab = function(container) {
	this.el = container;
	var ul = container.querySelector('ul');
	this.buttons = ul.children, // tab候选栏strip
	this.tabs = container.querySelector('.content').children;
	ul.onclick = onTabChooserPressHandler.bind(this);
}

/**
 * 跳到指定的 tab,仿佛好象点击那样
 * @param {int} index
 */
SimpleTab.prototype.jump = function(index){
	var btn = this.buttons[index];
	onTabChooserPressHandler.call(this, {
		target : btn,
		currentTarget : this.el.querySelector('ul')
	});
}

var onPressed_ClassName = 'selected';
// 登记的单击事件是整个 tan panel
function onTabChooserPressHandler(e) {
	// 搜索 el 下的 li 元素,到容器为止
	var el = e.target;
	if (el.tagName != 'LI') return;

	var buttons = e.currentTarget.children, // tab候选栏strip
		tabs = e.currentTarget.parentNode.querySelector('.content').children;
	!buttons.length && console.log('该控件未发现任何 strip。');
	
	for (var nextIndex = 0, j = buttons.length; nextIndex < j; nextIndex++)
		if (buttons[nextIndex] == el)
			break; // 获取 nextIndex
			
	// 查找与 index 相等的 item 设置其高亮,否则移除样式。
	var btn, showTab;
	for (var i = 0, j = buttons.length; i < j; i++) {
		btn = buttons[i], showTab = tabs[i];
		// debugger;
		if (nextIndex == i && btn.className.indexOf(onPressed_ClassName) == -1) { // 找到目标项
			btn.addCls(onPressed_ClassName);
			showTab.addCls(onPressed_ClassName);
			this.currentIndex = i; // 保存当前游标

		
		} else if (btn == el && btn.className.indexOf(onPressed_ClassName) != -1) {
			// 已在当前项
		} else if (btn.className.indexOf(onPressed_ClassName) != -1) {
			btn.removeCls(onPressed_ClassName);
			showTab.removeCls(onPressed_ClassName);
		}
	}
}

new SimpleTab(document.querySelector('.tab2')).jump(0);

6、全屏幕遮罩及 ESC 键盘事件响应

一般这是全局性的组件,设置为“单例”即可。全屏幕基本是 CSS 还有一个 JS 的小尾巴,因为似乎用 CSS 不容易设置高度,用 JS 做还是比较可行的。点击查看在线例子。

<meta charset="UTF-8">
<title>全屏幕遮罩及 ESC 键盘事件响应</title>

<div class="mask"></div>

<style>
	.mask {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		z-index: 9999999;
		background-color: rgba(0, 0, 0, 0.5);
	}
</style>

<script>
     // 获取页面内容高度赋予 mask
    document.querySelector('.mask').style.height = document.body.scrollHeight + 'px';
	
    // 键盘事件
    function onEnterAndEsc(e){
        e = e || event;
        var keycode = e.which || e.keyCode;
        switch(keycode){  
            case 13: //enter   
            	// 如果 form 里有 action,按下回车自动提交
     			// ...
            break;
            case 339: //exit   
            case 340: //back    
            case 27:
            	var mask = document.querySelector('.mask');
            	mask.parentNode.removeChild(mask);
        } 
    }
		
    document.onkeydown = onEnterAndEsc;
</script>

7、消息对话框

和这里其他的组件一样,对话框也是一个非常雏形的组件,仅仅完成了 fixed 定位、居中、关闭这几样功能,——可能样式方面的代码还着墨的比较多。至于背景遮罩,前面一个例子就有,有兴趣的童鞋可以看看怎么把两者组装起来。另外对话框拖放也是一个功能点,咱们在第一个例子的时候已经有介绍了。动手能力强的童鞋也可以试着自己把它们封装在一起,形成完整的对话框组件——这里就不再赘述了。点击查看在线例子。


<meta charset="UTF-8">
<title>MsgBox</title>

<div class="msgbox">
	<h1>确认</h1>
	<div class="topCloseBtn closeAction">×</div>
	<div class="inner">
		益力多,你今日饮左未?
	</div>
	<div class="btn">
 		<div class="closeAction">确认</div>
	</div>
</div>


<style>
	.msgbox {
		position: fixed;
		background-color: #ebebeb;
		border: 1px solid #d3d3d3;
		width: 50%;
		min-width: 300px;
		max-width: 400px;
		z-index: 99999999;
		margin: auto;
		min-height: 100px;
	}
	
	.msgbox h1 {
		font-size: .9rem;
		text-align: center;
		padding: 5px 0;
		letter-spacing: 3px;
	}
	
	.msgbox .topCloseBtn {
		position: absolute;
		text-align: center;
		top: 0;
		right: 10px;
		width: 16px;
		line-height: 16px;
		height: 16px;
		background-color: gray;
		color: white;
		cursor: pointer;
	}
	.msgbox .inner {
		margin: 5px;
		margin-top: 0;
		padding: 10px;
		overflow: hidden;
		background-color: #f7f7f7;
		text-align: center;
		border: 1px solid #dadada;
		min-height:50px;
		line-height:50px;
	}
	.msgbox .btn {
		margin: 5px auto;
		width: 70%;
		overflow: hidden;
		text-align: center;
	}
 
	.msgbox .btn > div {
		display: inline-block;
		max-width: 80px;
		cursor: pointer;
		text-align: center;
		border: 1px solid #d3d3d3;
		padding: 3px 10px;
		letter-spacing: 3px;
		box-sizing: border-box;
		background-color: #f7f7f7;
		font-size: .9rem; 
	}
</style>

<script>
function MsgBox(msgbox) {
	// 计算居中
	msgbox.style.left = (window.innerWidth / 2 - msgbox.clientWidth / 2) + 'px';
	msgbox.style.top = (window.innerHeight / 2 - msgbox.clientHeight / 2) + 'px';
	
	// 平均分按钮宽度
	var btn = msgbox.querySelector('.btn'), btns = msgbox.querySelectorAll('.btn>div');
	var j = btns.length, width = btn.clientWidth / j - 12; // 要减去间隙
 
	// 登记关闭事件
	[].forEach.call(msgbox.querySelectorAll('.closeAction'), function(closeBtn){
		closeBtn.onclick = function(){
			msgbox.parentNode.removeChild(msgbox);
		}
	});
}
	
new MsgBox(document.querySelector('.msgbox'));
</script>

8、跑马灯 Carousel 轮播

跑马灯是个经典的效果,几乎每个网站、APP 都会用到,我们应该要好好掌握跑马灯实现的算法。一种最普遍的思路:把图片们用 ul 之类(div 亦可)的包起来,并设置 float,然后设置这个 ul 本身为 absolute 定位,其父标签用 relative 定位。通过设置 ul 的 left 或 top 值,从而实现图片队列的滚动效果。 点击查看在线例子。

<meta charset="UTF-8">
<title>carousel</title>

<div class="carousel">
	<div>
		<div>
			<a href="topic/?id=283">
				<img src="http://imgu.3gtv.net:9090/_file/section/20150919114717260.jpg">
			</a>
		</div>
		<div>
			<a href="live/?id=3">
				<img src="http://imgu.3gtv.net:9090/_file/section/20150918214948448.png">
			</a>
		</div>
		<div>
			<a href="topic/?id=346">
				<img src="http://imgu.3gtv.net:9090/_file/section/20150910171423733.png">
			</a>
		</div>
		<div>
			<a href="topic/?id=345">
				<img src="http://imgu.3gtv.net:9090/_file/section/20150909172539065.jpg">
			</a>
		</div>
		 
	</div>
</div>

<style>
	.carousel{
		height:250px;
		width:600px;
		overflow:hidden;
		position: relative;
	}
	
	.carousel > div{
		left:0;
		position:absolute;
		white-space: nowrap;
		transition: 200ms left linear;
		-moz-transition: 200ms left linear;
		-o-transition: 200ms left linear;
		-ie-transition: 200ms left linear;
		-webkit-transition: 200ms left linear;
	}
	
	.carousel > div > div{
		float: left;
	}
	.carousel > div > div img {
		width: 100%;
	}
</style>

<script>
function Carousel(el) {
	var containerWidth = el.clientWidth, 
		mover = el.querySelector('div'),
		items = mover.children, len = items.length;
	
    // 设置 mover 和 item 宽度。初始化时候运行。
    for (var i = 0; i < len; i++) {
        items[i].style.width = containerWidth + 'px'; // 设置item 宽度
    }
    mover.style.width = containerWidth * len  + 'px'; // 总宽度,也是容器中最宽的宽度。赋予给 mover。
    var count = 0;
    setInterval(function(){
    	if(++count == len)count = 0;
    	mover.style.left = -count * containerWidth + 'px';
    }, 2000);
}
	
new Carousel(document.querySelector('.carousel'));
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sp42a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值