浅谈 原生javaScript&&react 实现全局触摸按钮(附带对addeventlistener的了解)
1.采用原生javaACript 实现全局触摸按钮
首先在控制台输出,观察事件有哪些关于触摸的字段可以使用,然后拿这些字段的数据开始来写方法。
因为要做的是全局触摸按钮,我需要拿到的是按钮时时的坐标位置,通过改变样式来改变按钮任意移动位置。所以就那了changedTouches里面的值。touches里面放的是touchstart的开始位置。用react的时候,touch事件会和click起冲突,导致链接点击有bug,所以需要那touchstart的值在touchend的时候做判断是点击事件还是触摸事件,来控制超链接的跳转。但是在普通h5中并没有这个问题,下面再细说。
这是html代码
<div class="active" id="active">
<a class="vote" id="vote" href="https://www.baidu.com"></a> //是全局可以触摸的对象,点击又可以做跳转
</div>
css样式
*{
margin:;
padding:;
} //demo里面我就直接去掉所有默认的样式
.active {
width: 100%;
height: 100%;
background: #9ff5ee;
}
.vote {
position: fixed;
bottom:40px; //全局触摸按钮使用定位的样式,可是随时改变定位的坐标来控制任意移动
right: 15px;
width: 60px;
height: 60px;
border-radius: 50%;
background: yellow;
}
接下来是重点的javascript代码,顺便讲解一下(preventDefault()、stopPropagation()这些方法,ps其实是一边写博客一边学习,复习)
window.onload=function(){ //当一个Web页面加载完成后就会触发执行window.onload 里的代码
var vote=document.getElementById("vote");//通过id取按钮这个节点
function handleTouchEvent(e) {
//只跟踪一次触摸
var width=document.documentElement.clientWidth,height=document.documentElement.clientHeight; //这里取屏幕的可视宽度和可视高度来控制按钮的最大最小访问
switch (e.type) {
case "touchstart": //触摸开始调用的方法
console.log('start');
break;
case "touchend":
console.log('end'); //触摸结束调用的方法,这里不用用到这两个方法,所以不做详情介绍
break;
case "touchmove":
//全局触摸主要用到touchmove这个方法,touchmove过程中坐标会不断变化,取这个变化的坐标来控制当前那全局按钮#vote的坐标。使用style对象来修改目前的样式,其间做了一个控制,不让按钮可以移动上左下右任意方向的屏幕外我用了两层三目运算符来限制坐标的最小和最大值。
document.getElementById("vote").style.left=parseInt(e.changedTouches[0].clientX) - 60 <= 0 || parseInt(e.changedTouches[0].clientX) >= width - 60 ? (parseInt(e.changedTouches[0].clientX) - 60 <= 0 ? 0 : width - 60) : parseInt(e.changedTouches[0].clientX);
//左右方向,最小位置不小于按钮的直径,最大不超过屏幕的可视宽度减按钮直径,上下方向也是
document.getElementById("vote").style.top=parseInt(e.changedTouches[0].clientY) - 60 <= 0 || parseInt(e.changedTouches[0].clientY) >= height - 60 ? (parseInt(e.changedTouches[0].clientY) - 60 <= 0 ? 0 : height-60) : parseInt(e.changedTouches[0].clientY);
break;
} }
function clickA(e){
e.preventDefault();//这里是点击事件,阻止了默认事件的触发,所以超链接不会跳转,没阻止的话超链接就会正常跳转了
}
vote.addEventListener("touchstart", handleTouchEvent, false);
vote.addEventListener("touchmove", handleTouchEvent, false);
vote.addEventListener("touchend", handleTouchEvent, false);
vote.addEventListener("click", clickA, false);
}
事件调用的方法有 attachEvent方法适用于IE addEventListener方法适用于FF
attachEvent只有两个参数,第一个参数为事件名称,第二个参数为接收事件处理的函数,因为是做h5的触摸,不需要做ie的兼容,所以没做全兼容。如果要做全兼容,如下
//兼容所有浏览器的事件监听方法
function(element, type, handler){
if (element.addEventListener) {
element.addEventListener(type, handler, false);
}
else
if (element.attachEvent) {
element.attachEvent("on" + type, handler);
}
else {
element["on" + type] = handler;
}
}
上文demo中事件的调用采用了addEventListener这个方法,这个方法有三个参数,第一个参数表示事件名称(不含 on,如 "click");第二个参数表示要接收事件处理的函数;第三个参数是一个bool值,一般为false。第三个参数的作用设置事件为冒泡还是捕获,如果为false那就是冒泡bubbling,为true就是捕获capture,冒泡和捕获是什么呢,看图
两层div元素,而且都设定有click事件,一般来说,如果我在内层黄色的元素上click不只会触发黄色元素的click事件,还会同时触发红色元素的click事件,由内到外的触发就是冒泡bubbling,由外层div到内层div触发就是捕获。这时候如果想阻止这些冒泡和捕获事件的发生,就需要用到stopPropagation()方法了,IE中则使用e.cancelBubble = true阻止冒泡,该方法阻止目标元素的冒泡事件,但是会不阻止默认行为。浏览器的默认行为就需要用到preventDefault()方法来阻止默认事件,比如上文的阻止超链接的跳转。
阻止冒泡的效果如下
function clickA(e){
alert('aaaa')
e.stopPropagation(); //点击a#vote按钮,如果没有加入该行,点击该事件会同时出发a#vote和div#active上面的事件,加入该行就可以阻止冒泡
e.preventDefault();//这里是点击事情,阻止了默认事件的触发,所以超链接不会跳转,没阻止的话超链接就会正常跳转了
}
function clickDiv(e){
alert('444')
}
document.getElementById("vote").addEventListener("click", clickA, false); //事件的调用
document.getElementById("active").addEventListener("click", clickDiv, false);
以上为原生javascript的实现方法
2.react 实现全局触摸按钮(使用react+ES6语法,使用webpack打包工具)
react大体包含(组件 ,JSX, 虚拟DOM, 单向数据流);
JSX也就是HTML直接嵌套到JS代码里面,所以以下就没有所谓的html和js分开了。
我们首先还是来观察react+ES6的事件输出,根据前面原生的js我们知道移动端的触摸主要用了touches和changedTouches里面的值,用touches来取得初始的坐标位置,用changedTouches可以取得触摸后移动位置的坐标。除了这两个还有一个targetTouches保存着当前坐标。它们都属于TouchList
对象
TouchList
由Touch
对象构成的数组,通过event.touches
取到。一个Touch
对象代表一个触点,当有多个手指触摸屏幕时,TouchList
就会存储多个Touch
对象,前面说到的identifier
就用来区分每个手指对应的Touch
对象。
touches / changedTouches / targetTouches
touches
一个TouchList对象,包含当前所有接触屏幕的触点的Touch对象,不论 touchstart 事件从哪个elment上触发。
targetTouches
也是一个TouchList对象,包含了如下触点的 Touch 对象:touchstart从当前事件的目标element上触发
changedTouches
也是一个 TouchList 对象,对于 touchstart 事件, 这个 TouchList 对象列出在此次事件中新增加的触点。对于 touchmove 事件,列出和上一次事件相比较,发生了变化的触点。对于 touchend ,列出离开触摸平面的触点(这些触点对应已经不接触触摸平面的手指)。
touchend这里要特别注意,touches和targetTouches只存储接触屏幕的触点,要获取触点最后离开的状态要使用changedTouches ,但是在react单向数据流中,可以实时改变状态机state中的值,所以可以不断取得接触屏幕触点的位置来改变触摸对象的坐标,所以react里面可用touches和targetTouches在touchend和touchmove中
e.touches、e.targetTouches、e.changedTouches 的输出都如下图,都是Touch对象
react绑定事件处理函数---->触摸(React 标准化了事件对象,因此在不同的浏览器中都会有相同的属性。)
onTouchCancel
onTouchEnd
onTouchMove
onTouchStart
触摸只会在移动设备上产生。在使用触摸时,尝试着用onclick来处理同个元素上的点击事件,发现点击事件根本没反应。所以我就在onTouchEnd处理元素触摸后的结果。当元素触摸结束后位置没偏移,就可以当成是点击事件,处理点击事件要完成的任务。
接下来上代码。
'use strict'; import React from 'react';
import './index.less'; //这里用的都是es6的引入方式 export default class Back extends React.Component {
static defaultProps = {
prefixCls: 'zm'
};
constructor() { //初始化state的工作要在constructor中完成。
super();
//在react中,无法获取dom节点,把要改变的值放在state状态机中
this.state = {
top: '76%', //触摸按钮初始位置(距离左边顶部的位置)
left: '83%',
startX: '', //触摸按钮初始的坐标
startY: '',
x: 0, //记录触摸按钮触摸后有无变化
y: 0,
height: document.documentElement.clientHeight, //屏幕可视宽高
width: document.documentElement.clientWidth,
}; } handleStart(e){
e.preventDefault(); //前面原生js用的是touches,其实还有一个targetTouches,在这两个的输出结果是一致的。
this.setState({ //当触摸开始时候,记录当时的坐标值,还有设置触摸变化的xy轴的变化为0,因为当新一轮触摸开始时候,必须重新设置,相当于初始化
startX : e.targetTouches[0].clientX,
startY : e.targetTouches[0].clientY,
x:0,
y:0,
});
} handleTouchMove(e) {
const { startX, startY, width, height } = this.state;//取得初始坐标和屏幕可视宽高 this.setState({
//设置当前的坐标位置,思路和上面原生的一样,不过由于react有实时变化的状态机state,所以在此用touches,targetTouches
//都可以来设置实时变化的值,不用用到changedTouches;
left: parseInt(e.touches[0].clientX) - 48 <= 0 || parseInt(e.touches[0].clientX) >= width - 48 ? (parseInt(e.touches[0].clientX) - 48 <= 0 ? 0 : width - 48) : parseInt(e.touches[0].clientX),
top: parseInt(e.touches[0].clientY) - 48 <= 0 || parseInt(e.touches[0].clientY) >= height - 48 ? (parseInt(e.touches[0].clientY) - 48 <= 0 ? 0 : height - 48) : parseInt(e.touches[0].clientY),
x: e.touches[0].clientX - startX, //当前触摸点-初始坐标取得实时变化值
y: e.touches[0].clientY - startY,
});
} handleTouchEnd (e) {
const { x, y } = this.state; if (x == 0 && y == 0) { //触摸结束后,判断实时变化值有没变化,没变化则视为点击事件。
window.location.href = '#';
};
} render() {
const { prefixCls } = this.props;
const { top, left, height, width } = this.state; //取得实时状态机state的值 return (
<div
className="zm"
style={{top:`${top}`,left:`${left}` }} //取得state的值实时改变触摸点的坐标位置
onTouchStart={this.handleStart.bind(this)} //使用bind(this)改变函数作用域,不加上bind则this指向的是全局对象window而报错。
onTouchMove={this.handleTouchMove.bind(this)}
onTouchEnd={this.handleTouchEnd.bind(this)}
/> )
}
}
react中要注意的是使用touch时 click没反应,需要在touchend中做判断做处理
浅谈 原生javaScript&&react 实现全局触摸按钮(附带对addeventlistener的了解)的更多相关文章
- 浅谈 原生javaScript && react 实现全局触摸按钮(附带对addeventlistener的了解)
1.采用原生javaACript 实现全局触摸按钮 首先在控制台输出,观察事件有哪些关于触摸的字段可以使用,然后拿这些字段的数据开始来写方法. 因为要做的是全局触摸按钮,我需要拿到的是按钮时时的坐标位 ...
- 浅谈原生JavaScript实现remove()和recover()
利用原生JavaScript实现: 1.remove(selectors)删除指定的一个或一组元素. 2.recover(selectors)恢复刚才删除的元素. function remove(se ...
- 浅谈原生JavaScript的动画和特效
一.JavaScript中的动画原理 动画效果的实现总的来说可分为两种,一种是利用纯css实现,该方法在css3成熟后广泛应用:另外一种是通过JavaScript(或者一些封装的库如jQuery的an ...
- 浅谈前端JavaScript编程风格
前言 多家公司和组织已经公开了它们的风格规范,详细可參阅jscs.info,以下的内容主要參考了Airbnb的JavaScript风格规范.当然还有google的编程建议等编程风格 本章探讨怎样使用E ...
- 表单美化-原生javascript和jQuery多选按钮(兼容IE6)
前些天我们讲了下单选按钮的美化今天来做表单元素多选按钮的美化.我们的想法是:利用多选按钮是否被选中和是否不给选择的特性来为按钮的父元素添加对应的样式,就是说用什么的样式是由按钮的状态来决定. 用到的图 ...
- 浅谈控件(组件)制作方法一(附带一delphi导出数据到Excel的组件实例)(原创)
来自:http://blog.csdn.net/zhdwjie/article/details/1490741 -------------------------------------------- ...
- 浅谈React
浅谈react react是什么?其官网给出了明确定义:A JavaScript library for building user interfaces,一个用于构建用户界面的JavaScript库 ...
- 浅谈React数据流管理
引言:为什么数据流管理如此重要?react的核心思想就是:UI=render(data),data就是我们说的数据流,render是react提供的纯函数,所以用户界面的展示完全取决于数据层.这篇文章 ...
- 浅谈JavaScript中的闭包
浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...
随机推荐
- 【Lua学习笔记之:Lua环境搭建 Windows 不用 visual studio】
Lua 环境搭建 Windows 不用 visual studio 系统环境:Win7 64bit 联系方式:yexiaopeng1992@126.com 前言: 最近需要学习Unity3d游戏中的热 ...
- C# 自动Ping 测试服务器运行状况
通过小程序自动Ping配置文件中的IP地址,间隔时间.IP地址.手机号码通过配置文件获得. 废话不多说,上代码. using Newtonsoft.Json; using Newtonsoft.Jso ...
- YbSoftwareFactory 代码生成插件【十三】:Web API 的安全性
ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.Android设备.IOS等) ...
- nextAll([expr])
描述: 给第一个div之后的所有元素加个类 HTML 代码: <div></div><div></div><div></div> ...
- angularJS——自定义服务provider之$get
可以认为provider有三个部分: 第一部分是私有变量和私有函数,这些变量和函数会在以后被修改. 第二部分是在app.config函数里可以访问的变量和函数,所以,他们可以在其他地方使用之前被修改. ...
- 自己写的java excel导出工具类
最近项目要用到excel导出功能,之前也写过类似的代码.因为这次项目中多次用到excel导出.这次长了记性整理了一下 分享给大伙 欢迎一起讨论 生成excel的主工具类: public class E ...
- No module named caffe
1.直接打开终端,输入python,enter,输入import caffe,enter,不出错 2.直接打开终端,输入sudo su切换到root下,或者是直接 sudo python,enter, ...
- Java中excute,excuteUpdate,excuteQuery的区别
executeQuery(String sql) 执行select语句,它返回的是查询后得到记录集(resultset). executeUpdate(String sql) 执行 ...
- AJAX(JS&&JQ&&H5)
一 AJAX的简介: AJAX是"Asynchronous Javascript And XML"(异步JavaScript和XML),通过后台与服务器实现少量的数据交换,可以使页 ...
- 关于HandlerThread的分析
Android中的Thread没有对java中的Thread做任何封装,而Android提供了一个遍历方法HandlerThread,他继承于Thread,实现了对遍历系统的一些封装,下面研究一下Ha ...