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的了解)的更多相关文章

  1. 浅谈 原生javaScript && react 实现全局触摸按钮(附带对addeventlistener的了解)

    1.采用原生javaACript 实现全局触摸按钮 首先在控制台输出,观察事件有哪些关于触摸的字段可以使用,然后拿这些字段的数据开始来写方法. 因为要做的是全局触摸按钮,我需要拿到的是按钮时时的坐标位 ...

  2. 浅谈原生JavaScript实现remove()和recover()

    利用原生JavaScript实现: 1.remove(selectors)删除指定的一个或一组元素. 2.recover(selectors)恢复刚才删除的元素. function remove(se ...

  3. 浅谈原生JavaScript的动画和特效

    一.JavaScript中的动画原理 动画效果的实现总的来说可分为两种,一种是利用纯css实现,该方法在css3成熟后广泛应用:另外一种是通过JavaScript(或者一些封装的库如jQuery的an ...

  4. 浅谈前端JavaScript编程风格

    前言 多家公司和组织已经公开了它们的风格规范,详细可參阅jscs.info,以下的内容主要參考了Airbnb的JavaScript风格规范.当然还有google的编程建议等编程风格 本章探讨怎样使用E ...

  5. 表单美化-原生javascript和jQuery多选按钮(兼容IE6)

    前些天我们讲了下单选按钮的美化今天来做表单元素多选按钮的美化.我们的想法是:利用多选按钮是否被选中和是否不给选择的特性来为按钮的父元素添加对应的样式,就是说用什么的样式是由按钮的状态来决定. 用到的图 ...

  6. 浅谈控件(组件)制作方法一(附带一delphi导出数据到Excel的组件实例)(原创)

    来自:http://blog.csdn.net/zhdwjie/article/details/1490741 -------------------------------------------- ...

  7. 浅谈React

    浅谈react react是什么?其官网给出了明确定义:A JavaScript library for building user interfaces,一个用于构建用户界面的JavaScript库 ...

  8. 浅谈React数据流管理

    引言:为什么数据流管理如此重要?react的核心思想就是:UI=render(data),data就是我们说的数据流,render是react提供的纯函数,所以用户界面的展示完全取决于数据层.这篇文章 ...

  9. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

随机推荐

  1. Flex 布局2

    Flex 布局2     你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我只列出代码,详细的语法解释请查阅<Flex布局教程:语法篇>.我的主要参考资料是Landon Sch ...

  2. ios 缺少合规证明

    现在app上传到appStore的时候,项目中如果出现加密,状态栏是:缺少合规证明. 解决的方法是在Info.plist文件中添加:ITSAppUsesNonExemptEncryption 设置为N ...

  3. ThinkPad E430光驱面板拆卸方法

    前一阵买了固态硬盘,拆出来的机械硬盘一直放在一边落灰.想着不能这么浪费资源,就买了光驱硬盘架,打算把光驱拆出来换上机械硬盘. 光驱很好拆,把后盖板打开之后,拧下固定的螺丝,用螺丝刀轻轻撬一下,光驱就出 ...

  4. 亲手使用Sencha Touch + phonepag开发Web APP随笔 -- 第一个APP

    参考博文: [Phonegap+Sencha Touch] 移动开发1.准备工作 [Phonegap+Sencha Touch] 移动开发2.PhoneGap/Cordova初步使用   经过差不多1 ...

  5. SQLServer 游标 (A)

    游标 游标分为客户端游标和服务器端游标.Sql通过游标可以对一个结果集进行逐行处理.对于使用服务器端游标的过程有:声明.打开.读取.关闭.释放. 1 声明游标 1.1 SQL-92标准的声明 Decl ...

  6. viewport设置

    <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable ...

  7. APICloud开发App总结(一)

    apiCloud app 开发是最近一两年刚刚兴起的一种混合开发方式.常用的模块以原生方式开发好,然后用js进行粘合.组织,完成整个的app的逻辑.这种开发方式极大的提高了软件模块的复用率,加快了ap ...

  8. Bash:-:-定义空变量作为输出结合换行符\n和column输出

    RET="" declare -a HOST=() declare -a ALL_SVR=() declare -a FREESVR=() ;i<${#_ALL_AGENT_ ...

  9. tinyshop框架教程已在腾讯课堂开课

    php就业网简介:www.php91.net,专注于Thinkphp框架教程的php框架学习中心.同时也有小崔老师自学php的教程,与你一起成长哦 同时,php就业网教程部分:http://www.p ...

  10. vueJs+webpack单页面应用--vue-router配置

    vue-route版本要跟vue版本同步,我的vue用的2.0+的,vue-router 也用了最新版2.1+ npm安装vue-router: $ npm install vue-router -- ...