随查

一、

移动端判断触摸的方向

最近做微信端页面,于是趁周末梳理了下移动端的事件这一块。

通过判断手指在屏幕上移动的位置减去手指放在屏幕上时的位置,就可以得出是往什么方向滑动:

 

DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Documenttitle><style type="text/css">

        div{

            position: relative;

            width: 500px;

            height: 500px;

            background-color: #ccc;}style>head><body><div id="d">div><script type="text/javascript">var d = document.getElementById('d'),

            startX,startY,moveX,moveY;

 

        d.addEventListener('touchstart',function(e){

            var target = e.targetTouches[0];

            startX = target.clientX,

            startY = target.clientY;

        });

 

        d.addEventListener('touchmove',function(e){

            var target = e.targetTouches[0];

            moveX = target.clientX;

            moveY = target.clientY;

 

            var x = moveX - startX,

                y = moveY - startY;

 

            // 如果x>0并且x轴上移动的距离大于y轴上移动的距离if(Math.abs(x) > Math.abs(y) && x >0){

                alert('向右');

            }

            elseif(Math.abs(x) > Math.abs(y) && x <0){

                alert('向左');

            }

            elseif(Math.abs(x) < Math.abs(y) && y >0){

                alert('向下');

            }

            elseif(Math.abs(x) < Math.abs(y) && x <0){

                alert('向上');

            }

        });

 

    script>body>html>

 

这里是通过计算得出来的x轴

 

二、

web端使用

 

用户在iconfont.cn可以下载,多种格式的icon,平台也可将图标转换为字体,便于前端工程师自由调整与调用。

 

icon单个使用

 

单个图标用户可以自行选择下载不同的格式使用,包括png,ai,svg。

点击下载按钮,可以选择下载图标。

 

 

 

此种方式适合用在图标引用特别少,以后也不需要特别维护的场景。

 

比如设计师用来做demo原型。

前端临时做个活动页。

当然如果你只是为了下载图标做PPT,也是极好的。

不过如果是成体系的应用使用,建议用户把icon加入项目,然后使用下面三种推荐的方式。

 

unicode引用

 

unicode是字体在网页端最原始的应用方式,特点是:

 

兼容性最好,支持ie6+,及所有现代浏览器。

支持按字体的方式去动态调整图标大小,颜色等等。

但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。

注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式

unicode使用步骤如下:

 

第一步:拷贝项目下面生成的font-face

 

@font-face {font-family: 'iconfont';

    src: url('iconfont.eot');

    src: url('iconfont.eot?#iefix') format('embedded-opentype'),

    url('iconfont.woff') format('woff'),

    url('iconfont.ttf') format('truetype'),

    url('iconfont.svg#iconfont') format('svg');

}

第二步:定义使用iconfont的样式

 

.iconfont{

    font-family:"iconfont" !important;

    font-size:16px;font-style:normal;

    -webkit-font-smoothing: antialiased;

    -webkit-text-stroke-width: 0.2px;

    -moz-osx-font-smoothing: grayscale;}

第三步:挑选相应图标并获取字体编码,应用于页面

 

<i class="iconfont">&#x33;</i>

font-class引用

 

font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。

 

与unicode使用方式相比,具有如下特点:

 

兼容性良好,支持ie8+,及所有现代浏览器。

相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。

因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。

不过因为本质上还是使用的字体,所以多色图标还是不支持的。

使用步骤如下:

 

第一步:拷贝项目下面生成的fontclass代码:

 

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.css

第二步:挑选相应图标并获取类名,应用于页面:

 

<i class="iconfont icon-xxx"></i>

symbol引用

 

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 这种用法其实是做了一个svg的集合,与上面两种相比具有如下特点:

 

支持多色图标了,不再受单色限制。

通过一些技巧,支持像字体那样,通过font-size,color来调整样式。

兼容性较差,支持 ie9+,及现代浏览器。

浏览器渲染svg的性能一般,还不如png。

使用步骤如下:

 

第一步:拷贝项目下面生成的symbol代码:

 

//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js

第二步:加入通用css代码(引入一次就行):

 

<style type="text/css">

    .icon {

       width: 1em; height: 1em;

       vertical-align: -0.15em;

       fill: currentColor;

       overflow: hidden;

    }

</style>

第三步:挑选相应图标并获取类名,应用于页面:

 

<svg class="icon" aria-hidden="true">

    <use xlink:href="#icon-xxx"></use>

</svg>

Android使用

 

android可以直接使用单个icon(svg,png)。也可以直接引入字体应用:

 

第一步:从iconfont平台选择要使用到的图标,并下载至本地;复制字体文件到项目 assets 目录

 

 

 

第二步:打开从iconfont平台下载下来的文件,并在目录中打开demo.html,找到图标相对应的 HTML 实体字符码;

 

 

 

第三步:打开 res/values/strings.xml,添加 string 值;

 

<string name="icons">&#x3605; &#x35ad; &#x35ae; &#x35af;</string>

第四步:打开 activity_main.xml,添加 string 值到 TextView:

 

<TextView

 

    android:id="../../+id/like"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="../../string/icons" />

第五步:为 TextView 指定文字:

 

import android.graphics.Typeface;

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    Typeface iconfont = Typeface.createFromAsset(getAssets(), "iconfont/iconfont.ttf");

    TextView textview = (TextView)findViewById(R.id.like);

    textview.setTypeface(iconfont);

}

 

 

IOS使用

 

IOS可以直接使用单个icon(svg,png)。也可以直接引入字体应用:

 

第一步:将您从IconFont平台下载的字体文件(.ttf)添加到工程中;

 

打开Info.plist文件,增加一个新的Array类型的键,键名设置为UIAppFonts(Fonts provided by application),增加字体的文件名:“iconfont.ttf“

 

 

 

第二步:使用IconFont字体:

 

UILabel * label = [[UILabel alloc] initWithFrame:self.view.bounds];

UIFont *iconfont = [UIFont fontWithName:@"uxIconFont" size: 34];

label.font = iconfont;

label.text = @"\U00003439 \U000035ad \U000035ae \U000035af \U000035eb \U000035ec";

[self.view addSubview: label];

这里有两个地方注意下:

 

创建 UIFont 使用的是字体名,而不是文件名;

文本值为 8 位的 Unicode 字符,我们可以打开 demo.html 查找每个图标所对应的 HTML 实体 Unicode 码,比如: "店" 对应的 HTML 实体 Unicode 码为:0x3439 转换后为:\U00003439 就是将 0x 替换为 \U 中间用 0 填补满长度为 8 个字符

 

三、跨域的几种方式

js中几种实用的跨域方法原理详解

 

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

 

下表给出了相对http://store.company.com/dir/page.html同源检测的结果:

 

 

 

要解决跨域的问题,我们可以使用以下几种方法:

 

一、通过jsonp跨域

 

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

 

比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php ,那么a.html中的代码就可以这样:

 

 

 

我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

 

因为是当做一个js文件来引入的,所以http://example.com/data.php 返回的必须是一个能执行的js文件,所以这个页面的php代码可能是这样的:

 

 

 

最终那个页面输出的结果是:

 

 

 

所以通过http://example.com/data.php?callback=dosomething 得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

 

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

 

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

 

 

 

原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

 

 

 

2、通过修改document.domain来跨子域

 

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html , 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

 

  

 

这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html 这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

 

在页面 http://www.example.com/a.html 中设置document.domain:

 

 

 

在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

 

 

 

这样我们就可以通过js访问到iframe中的各种属性和对象了。

 

不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。

 

 

 

3、使用window.name来进行跨域

 

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

 

比如:有一个页面a.html,它里面有这样的代码:

 

 

 

再看看b.html页面的代码:

 

 

 

a.html页面载入后3秒,跳转到了b.html页面,结果为:

 

 

 

我们看到在b.html页面上成功获取到了它的上一个页面a.html给window.name设置的值。如果在之后所有载入的页面都没对window.name进行修改的话,那么所有这些页面获取到的window.name的值都是a.html页面设置的那个值。当然,如果有需要,其中的任何一个页面都可以对window.name的值进行修改。注意,window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器,但一般是够用了。

 

上面的例子中,我们用到的页面a.html和b.html是处于同一个域的,但是即使a.html与b.html处于不同的域中,上述结论同样是适用的,这也正是利用window.name进行跨域的原理。

 

下面就来看一看具体是怎么样通过window.name来跨域获取数据的。还是举例说明。

 

比如有一个www.example.com/a.html 页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.cnblogs.com/data.html 里的数据。

 

data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

 

 

 

那么在a.html页面中,我们怎么把data.html页面载入进来呢?显然我们不能直接在a.html页面中通过改变window.location来载入data.html页面,因为我们想要即使a.html页面不跳转也能得到data.html里的数据。答案就是在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。

 

充当中间人的iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为www.cnblogs.com/data.html 就行了。然后a.html想要得到iframe所获取到的数据,也就是想要得到iframe的window.name的值,还必须把这个iframe的src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是整个跨域过程。

 

看下a.html页面的代码:

 

 

 

上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe。网上也有很多类似的现成代码,有兴趣的可以去找一下。

 

通过window.name来进行跨域,就是这样子的。

 

 

 

4、使用HTML5中新引进的window.postMessage方法来跨域传送数据

 

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

 

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

 

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

 

上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的,而且也可以使用window.postMessage这个方法。下面看一个简单的示例,有两个页面

 

 

 

 

 

 

 

我们运行a页面后得到的结果:

 

 

 

我们看到b页面成功的收到了消息。

 

使用postMessage来跨域传送数据还是比较直观和方便的,但是缺点是IE6、IE7不支持,所以用不用还得根据实际需要来决定。

 

posted @ 2017-08-09 08:22  张学亮  阅读(420)  评论(0编辑  收藏  举报