记一次 JS 模拟 CSS active 效果的过程

简介: 所谓的界面触控效果,就是用户点下去的时候,界面立刻产生变化以反馈给用户知道:“ok,你点击的吩咐,我已晓得罗~”,也有人说“点击高亮的效果”。——毋庸置疑,这是人机交互中非常重要沟通手段,使用得也非常常见的。

所谓的界面触控效果,就是用户点下去的时候,界面立刻产生变化以反馈给用户知道:“ok,你点击的吩咐,我已晓得罗~”,也有人说“点击高亮的效果”。——毋庸置疑,这是人机交互中非常重要沟通手段,使用得也非常常见的。当时我要实现这效果的时候,自己还满认为,不就是网页上为链接加个 a:hover 效果嘛~链接不行的加个“图片翻转”不就可以了。——孰料,在移动终端上,花费的时间远超想像。首先,我倾向于采用纯样式的方法,大体思路是:普通状态写一种样式;用户点击后归为另外一种状态,写出其状态对应样式。这样,我立刻想到的时“元素:hover”。经测试 PC 上无问题,但手机上尤其列表控件显得过于灵敏,有时与滚动事件冲突,有时出现奇怪的 bug,于是想想,不应使用 hover,应是采用“元素:active”才对(active 意即“击中”那一下,hover 仅仅“移上”意思)。改用 active 后,上述问题立即迎刃而解。简单说,active 效果与 hover 效果相比,就是 active 点击后会撤销手指松开的样式。

/* 普通效果 */
.x_list li {
    padding: 3px;
    width: 100%;
    list-style: none;
    background-color: #999;/*普通效果的背景色*/
    border-bottom: 1px solid #333;
    border-top: 1px solid white;
    clear: both;
    display: inline-table;
    position: relative;
}
/* 点击效果 */
.x_list li:active{
    background-color:red;
}

看来,hover 与 active 意思虽相近,但细作起来还是明显差别。以往讨论桌面的时候,大多用 hover 即可,而现如今在手机上却把两者的区别给凸显出来了。我想,这是什么缘故呢,——为什么以往桌面的做法行得通,而手机上却把问题暴露出来呢。我觉得,执行“事件的媒介”也是重要的原因,因为桌面上输入事件的乃鼠标器居多,而且手机上则围绕手指触控的居多。两者的分野,导致所处于的经验与法则也不尽相同。可以说,承接下来的那个 bug,都有同样的缘故在作祟。

可是,即使使用 active,又遇到浏览器支持的问题:——Android 2.x 仍不支持元素:active,新版的 Android 4.x 和 iOS 则顺利通过。于是我安排 iOS 与 Android 4 就用 CSS 的写法,而 Android 另一边厢安排 js 方法实现之。

既然用 js 方法实现之,我第一时间想到的用 setTimeout() 定时器实现之。点击后添加一样式,timeout 之后撤销样式。

// 用户按下之后,为元素加入高亮样式,然后立刻消褪,——这就是所谓的 active 样式。
// 请注意,这个方法属于“反面教材”
function onActive(el, fn){
	el.addCls('active');
	setTimeout(function(){
		fn && fn();
		el.removeCls('active');
	}, 300);
}

这个貌似可行的办法实则不正确!因为经过领导演示,人家 Sencha Touch 的选中高亮是可以跟随滚动的,我的在首页上的点击高亮是可以但不会响应点击滚动,有反常理!甚幸,恰恰有正确的案例在前,让我可以参照,可以纠正。后来结果通过 touchstart/touchend 事件实现这个界面触控效果。代码如下:

HTMLElement.prototype.onActive = (function () {
	/**
	 * this 应为 CSS Selector
	 * @param {Event} e
	 */
	function highlight(e){
		var targetEl = e.target;
		if(targetEl && targetEl.tagName == this.toUpperCase()){
			targetEl.toggleCls('active');
		}else if(targetEl){
			arguments.callee.call(this, {
				target : targetEl.parentNode
			});
		}
	}

    // 是否支持触摸事件
    var isSupportTouch = 'ontouchstart' in window || "ontouchend" in window.document;
	// 支持触摸式使用相应的事件替代
	var hightEvent_in  = isSupportTouch ? 'touchstart': 'mouseover',
		hightEvent_out = isSupportTouch ? 'touchend' : 'mouseout';

    /**
      * @param {String} highlightCfg
      */
    return function(el_cssSelector){
    	// ONLY FOR Moblie?
    	if (!window.navigator.isAndroid_2) {
    		return false;
    	}
    	var eventHandler = highlight.bind(el_cssSelector || 'LI'); // 默认 li 修改样式
    	// $$.addListener 为跨浏览器的事件添加器
		$$.addListener(this,  hightEvent_in, eventHandler);
		$$.addListener(this, hightEvent_out, eventHandler);
//		$$.addListener(this, 'touchcancel',eventHandler, isUseCapture); /*@todo考察该事件,比较特殊*/
		 return this; // 方便链式调用
	}
})();
上述代码扩展的浏览器原生对象 HTMLElment 原型,因此在任一元素身上都有 onActive 方法,另外 toggleCls(className) 也是通过扩展元素原型来提供的。相应地,样式不经过伪类来实现,而是定义一个 .active 的样式类:

/* 点击效果 */
.x_list li.active{ /* 注意这里冒号被改为点号*/
    background-color:red;
}

函数 highlight 中,因为登记事件时不能触发 userCapture,所以没有使用“事件冒泡”的方式而是递归上报的方式。

2013-4-7 重新整理一下这个函数,请注意这是没有版本检测,你应该自己加一个,因为只针对 android 2.x。

/**
 * 模拟 el:active
 * @param {Element} ul 参数为元素
 */
function onActive(ul){
	// ONLY FOR Android 2.x? Yes!
	// 检测是否 android 2.x 的属性,你可以依赖你自己的方案,我的就不贴了,比较简单的。
	// if (!window.navigator.isAndroid_2) {
		// return ul; //尽管该函数不工作,也要返回 this,以方便链式调用
	// }
	
	// add Highlight
	ul.addEventListener('touchstart', function (e){
		var targetEl = e.target;
		while(targetEl && targetEl.tagName != 'LI'){// 默认为 li 修改样式
			targetEl = targetEl.parentNode; 		// 找到要操作的目标元素为止
		}
		// do sth……
		console.log(targetEl.tagName);
		targetEl.addCls('active');
	});

	// remove Highlight
	ul.addEventListener('touchend',   function (e){
		var targetEl = e.target;
		while(targetEl && targetEl.tagName != "LI"){
			targetEl = targetEl.parentNode; // 找到要操作的目标元素为止
		}
		// do sth……
		console.log(targetEl.tagName);
		targetEl.removeCls('active');
	}); 
	
	return ul; // 方便链式调用
}

CSS 样式如下:

/* 点击效果 */
ul.x_list li:active, ul.x_list li.active {
    background-image: -webkit-gradient(linear, center top, center bottom, from(lightGrey), to(white));
}

2013-04-18 把问题重新整理了一下,给出如下“药方”:

<style type="text/css">
p:active, p.active{
	background-color:red;
}
</style>
<body>
	<p>Welcome to Jdrop
Jdrop provides a place to store JSON data in the cloud. The initial application is for storing performance data gathered from mobile devices. It's hard to analyze large amounts of information (HTTP waterfall charts, HTTP headers, document source, etc.) on a mobile device. Jdrop lets you gather this data on the mobile device but analyze it remotely on a larger screen. </p>
</body>
<script type="text/javascript">
	document.addEventListener('touchstart', function (e) {
		e.target.className = 'active';
	}, false);
	document.addEventListener('touchend', function (e) {
		e.target.className = '';
	}, false);
</script>
使用了事件委托比较合理。

目录
相关文章
|
5月前
|
移动开发 前端开发 JavaScript
征信报告修改器,征信报告生成器,制作软件无痕修改软件【js+html+css】
本项目为信用评分模拟器教学工具,采用HTML5实现,仅供学习参考。核心功能通过JavaScript构建,包含虚拟数据生成、权重分配及信用因素分析(如还款记录、信用使用率等)。
|
5月前
|
前端开发 JavaScript
个人征信电子版无痕修改, 个人信用报告pdf修改,js+html+css即可实现【仅供学习用途】
本代码展示了一个信用知识学习系统的前端实现,包含评分计算、因素分析和建议生成功能。所有数据均为模拟生成
|
5月前
|
存储 前端开发 JavaScript
仿真银行app下载安装, 银行卡虚拟余额制作app,用html+css+js实现逼真娱乐工具
这是一个简单的银行账户模拟器项目,用于学习前端开发基础。用户可进行存款、取款操作,所有数据存储于浏览器内存中
|
5月前
|
前端开发
个人征信PDF无痕修改软件,个人征信模板可编辑,个人征信报告p图神器【js+html+css仅供学习用途】
这是一款信用知识学习系统,旨在帮助用户了解征信基本概念、信用评分计算原理及信用行为影响。系统通过模拟数据生成信用报告,涵盖还款记录
|
5月前
|
前端开发 JavaScript 容器
制作b超单生成器, 假怀孕b超单图片制作, p图医院证明【css+html+js装逼恶搞神器】
本资源提供一个适合用于熟人之间恶搞的工具,效果逼真,仅供学习参考与娱乐。包含前端技术学习要点:语义化布局、响应式设计、Flexbox、图片自适应
|
5月前
|
前端开发
医院检查单子p图软件,在线制作仿真病历,js+css+html装逼神器
本示例展示如何用HTML/CSS创建医疗信息页面,内容仅供学习参考。页面模拟“阳光医院体检中心”场景,提供预约功能验证(如姓名、手机号、日期)。所有数据仅用于演示
|
前端开发 JavaScript UED
前端开发的魔法:CSS动画与JavaScript的完美结合
本文将探讨如何利用CSS动画和JavaScript的结合,为前端页面增添生动的效果。我们将通过实例展示如何使用这两种技术为网页元素创建吸引人的动画效果,并讨论它们的优缺点和适用场景。
|
Web App开发 编解码 前端开发
浏览器原理 23 # 分层和合成机制:为什么CSS动画比JavaScript高效?
浏览器原理 23 # 分层和合成机制:为什么CSS动画比JavaScript高效?
440 0
浏览器原理 23 # 分层和合成机制:为什么CSS动画比JavaScript高效?
|
Web App开发 移动开发 前端开发
梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画
CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能。
梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画

热门文章

最新文章

  • 1
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    128
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    141
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    114
  • 4
    (CSS)使用Flex布局,帮助你快速了解各种基本的Flex布局属性以及帮你让元素快速达到布局中的指定位置!
    87
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    210
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    236
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    129
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    65
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    123
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    164