您的位置:奥门新浦京网址 > Wed前段 > Twitter的”fave”动画

Twitter的”fave”动画

发布时间:2019-10-14 18:31编辑:Wed前段浏览(133)

    Twitter的”fave”动画

    2015/05/12 · HTML5 · Twitter, 动画

    本文由 伯乐在线 - 刘健超-J.c 翻译,胡屹 校稿。未经许可,禁止转载!
    英文出处:cssanimation.rocks。欢迎加入翻译组。

    WebSocket 教程

    2017/05/15 · 基础技术 · websocket

    原文出处: 阮一峰   

    WebSocket 是一种网络通信协议,很多高级功能都需要它。

    本文介绍 WebSocket 协议的使用方法。

    图片 1

    HTML5的Websocket(理论篇 I)

    2017/10/28 · HTML5 · websocket

    原文出处: 转转前端   

    先请来TA的邻居:

    http:无状态、基于tcp请求/响应模式的应用层协议 (A:哎呀,上次你请我吃饭了么? B:我想想, 上次请你吃了么)
    tcp:面向连接、保证高可靠性(数据无丢失、数据无失序、数据无错误、数据无重复到达) 传输层协议。(看啊,大阅兵,如此规整有秩序)

    为什么要引入Websocket:

    RFC开篇介绍:本协议的目的是为了解决基于浏览器的程序需要拉取资源时必须发起多个HTTP请求和长时间的轮询的问题。

    long poll(长轮询): 客户端发送一个request后,服务器拿到这个连接,如果有消息,才返回response给客户端。没有消息,就一直不返回response。之后客户端再次发送request, 重复上次的动作。

    图片 2

    从上可以看出,http协议的特点是服务器不能主动联系客户端,只能由客户端发起。它的被动性预示了在完成双向通信时需要不停的连接或连接一直打开,这就需要服务器快速的处理速度或高并发的能力,是非常消耗资源的。

    这个时候,Websocket出现了。

    Twitter的“fave” 动画

    最近 Twitter 通过引入一段新的动画重新设计了“fave”按钮(也叫“fav”)。这段动画并不依赖 CSS transition,而是由一系列图片组成的。下面展示如何用 CSS 的 animation-timing-function 属性中的 steps 时序函数(timing function)重新制作这段动画。

    一、为什么需要 WebSocket?

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

    答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。

    举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

    图片 3

    这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用“轮询”:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。

    轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。

    Websocket是什么:

    RFC中写到:WebSocket协议使在控制环境下运行不受信任代码的客户端和能够选择与那些代码通信的远程主机之间能够双向通信。

    对,划重点:双向通信

    Websocket在连接之后,客户端可以主动发送消息给服务器,服务器也可以主动向客户端推送消息。比如:预订车票信息,除了我们发请求询问车票如何,当然更希望如果有新消息,可以直接通知我们。

    其特点:

    (1)握手阶段采用 HTTP 协议,默认端口是80和443

    (2)建立在TCP协议基础之上,和http协议同属于应用层

    (4)可以发送文本,也可以发送二进制数据

    (5)没有同源限制,客户端可以与任意服务器通信

    (6)协议标识符是ws(如果加密,为wss),如ws://localhost:8023

    简单来说,Websocket协议分为两部分:握手和数据传输。

    图片 4

    运动产生的错觉

    这段动画的效果类似于观看古老的西洋镜,该装置呈现的是一系列连续的围绕着圆筒的插画。在下面的示例中,我们不使用圆筒,而是在某个元素内部呈现一系列图片。

    二、简介

    WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

    它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

    图片 5

    其他特点包括:

    (1)建立在 TCP 协议之上,服务器端的实现比较容易。

    (2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此不容易屏蔽,能通过各种 HTTP 代理服务器。

    (3)数据格式比较轻量,性能开销小,通信高效。

    (4)可以发送文本,也可以发送二进制数据。

    (5)没有同源限制,客户端可以与任意服务器通信。

    (6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    ws://example.com:80/some/path

    1
    2
    ws://example.com:80/some/path
     

    图片 6

    Websocket API:

    这里是指客户端 API。

    示例

    把鼠标悬停在星星上就可以看到动画效果(请到原文查看动画效果——译者注)。

    在本示例中,我们将从制作一系列能组成动画的图片开始。在这里,我们使用来自 Twitter 的“fave”图标动画的部分图片集:

    图片 7

    为了能让这些帧动起来,我们需要把它们放置在一排上。在这个文件中,这些帧已经排列在一排上了,这意味着我们可以通过设置背景位置(background-position)属性使背景从第一帧过渡到最后一帧。

    图片 8

    三、客户端的简单示例

    WebSocket 的用法相当简单。

    下面是一个网页脚本的例子(点击这里看运行结果),基本上一眼就能明白。

    var ws = new WebSocket("wss://echo.websocket.org"); ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; ws.onmessage = function(evt) { console.log( "Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var ws = new WebSocket("wss://echo.websocket.org");
     
    ws.onopen = function(evt) {
      console.log("Connection open ...");
      ws.send("Hello WebSockets!");
    };
     
    ws.onmessage = function(evt) {
      console.log( "Received Message: " + evt.data);
      ws.close();
    };
     
    ws.onclose = function(evt) {
      console.log("Connection closed.");
    };      
     

    WebSocket 构造函数

    通过调用WebSocket构造函数来创建一个WebSocket实例对象,建立客户端与服务器的连接。

    JavaScript

    const ws = new WebSocket('ws://localhost:8023');

    1
    const ws = new WebSocket('ws://localhost:8023');

    Steps() 时序函数

    大多数的时序函数,例如 ease(缓冲)和 cubic-bezier(三次贝塞尔),都能让元素从初始状态平滑地过渡到最终状态。steps 时序函数与此不同,它并不是平滑地过渡,而是将过渡过程分割为一定数量的步骤,并且在这些步骤之间快速地移动。

    图片 9

    我们先建立如下的 HTML 代码:

    XHTML

    <section class="fave"></section>

    1
    <section class="fave"></section>

    四、客户端的 API

    WebSocket 客户端的 API 如下。

    Websocket事件

    WebSocket 是纯事件驱动,通过监听事件可以处理到来的数据和改变的连接状态。服务端发送数据后,消息和事件会异步到达。

    • open:
      服务端响应WebSocket连接请求,就会触发open事件。onopen是响应的回调函数。
    JavaScript
    
    // 连接请求open事件处理: ws.onopen = e =&gt; {
    console.log('Connection success'); ws.send(`Hello ${e}`); };
    
    <table>
    <colgroup>
    <col style="width: 50%" />
    <col style="width: 50%" />
    </colgroup>
    <tbody>
    <tr class="odd">
    <td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
    <div class="crayon-num" data-line="crayon-5b8f447934b5b531196143-1">
    1
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b5b531196143-2">
    2
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b5b531196143-3">
    3
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b5b531196143-4">
    4
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b5b531196143-5">
    5
    </div>
    </div></td>
    <td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
    <div id="crayon-5b8f447934b5b531196143-1" class="crayon-line">
     // 连接请求open事件处理:
    </div>
    <div id="crayon-5b8f447934b5b531196143-2" class="crayon-line crayon-striped-line">
         ws.onopen = e =&gt; {
    </div>
    <div id="crayon-5b8f447934b5b531196143-3" class="crayon-line">
             console.log('Connection success');
    </div>
    <div id="crayon-5b8f447934b5b531196143-4" class="crayon-line crayon-striped-line">
             ws.send(`Hello ${e}`);
    </div>
    <div id="crayon-5b8f447934b5b531196143-5" class="crayon-line">
         };
    </div>
    </div></td>
    </tr>
    </tbody>
    </table>
    

    如果要指定多个回调函数,可以使用addEventListener方法。

    JavaScript

    ws.addEventListener('open', e => { ws.send(`Hello ${e}`); });

    1
    2
    3
    ws.addEventListener('open', e => {
      ws.send(`Hello ${e}`);
    });

    当open事件触发时,意味着握手阶段已结束。服务端已经处理了连接的请求,可以准备收发数据。

    • Message:收到服务器数据,会触发消息事件,onmessage是响应的回调函数。如下:
    JavaScript
    
    // 接受文本消息的事件处理: ws.onmessage = e =&gt; { const data =
    e.data; if (typeof data === "string") { console.log("Received string
    message ",data); } else if (data instanceof Blob) {
    console.log("Received blob message ", data); } };
    
    <table>
    <colgroup>
    <col style="width: 50%" />
    <col style="width: 50%" />
    </colgroup>
    <tbody>
    <tr class="odd">
    <td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
    <div class="crayon-num" data-line="crayon-5b8f447934b62129912854-1">
    1
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b62129912854-2">
    2
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b62129912854-3">
    3
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b62129912854-4">
    4
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b62129912854-5">
    5
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b62129912854-6">
    6
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b62129912854-7">
    7
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b62129912854-8">
    8
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b62129912854-9">
    9
    </div>
    </div></td>
    <td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
    <div id="crayon-5b8f447934b62129912854-1" class="crayon-line">
    // 接受文本消息的事件处理:
    </div>
    <div id="crayon-5b8f447934b62129912854-2" class="crayon-line crayon-striped-line">
    ws.onmessage = e =&gt; {
    </div>
    <div id="crayon-5b8f447934b62129912854-3" class="crayon-line">
        const data = e.data;
    </div>
    <div id="crayon-5b8f447934b62129912854-4" class="crayon-line crayon-striped-line">
        if (typeof data === &quot;string&quot;) {
    </div>
    <div id="crayon-5b8f447934b62129912854-5" class="crayon-line">
            console.log(&quot;Received string message &quot;,data);
    </div>
    <div id="crayon-5b8f447934b62129912854-6" class="crayon-line crayon-striped-line">
        } else if (data instanceof Blob) {
    </div>
    <div id="crayon-5b8f447934b62129912854-7" class="crayon-line">
            console.log(&quot;Received blob message &quot;, data);
    </div>
    <div id="crayon-5b8f447934b62129912854-8" class="crayon-line crayon-striped-line">
        }
    </div>
    <div id="crayon-5b8f447934b62129912854-9" class="crayon-line">
    };
    </div>
    </div></td>
    </tr>
    </tbody>
    </table>
    

    服务器数据可能是文本,也可能是二进制数据,有Blob和ArrayBuffer两种类型,在读取到数据之前需要决定好数据的类型。

    • Error发生错误会触发error事件, onerror是响应的回调函数, 会导致连接关闭。
    JavaScript
    
    //异常处理 ws.onerror = e =&gt; { console.log("WebSocket Error: " ,
    e); handleErrors(e); };
    
    <table>
    <colgroup>
    <col style="width: 50%" />
    <col style="width: 50%" />
    </colgroup>
    <tbody>
    <tr class="odd">
    <td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
    <div class="crayon-num" data-line="crayon-5b8f447934b66862080563-1">
    1
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b66862080563-2">
    2
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b66862080563-3">
    3
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b66862080563-4">
    4
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b66862080563-5">
    5
    </div>
    </div></td>
    <td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
    <div id="crayon-5b8f447934b66862080563-1" class="crayon-line">
    //异常处理
    </div>
    <div id="crayon-5b8f447934b66862080563-2" class="crayon-line crayon-striped-line">
    ws.onerror = e =&gt; {
    </div>
    <div id="crayon-5b8f447934b66862080563-3" class="crayon-line">
        console.log(&quot;WebSocket Error: &quot; , e);
    </div>
    <div id="crayon-5b8f447934b66862080563-4" class="crayon-line crayon-striped-line">
        handleErrors(e);
    </div>
    <div id="crayon-5b8f447934b66862080563-5" class="crayon-line">
    };
    </div>
    </div></td>
    </tr>
    </tbody>
    </table>
    
    • Close当连接关闭时触发close事件,对应onclose方法,连接关闭之后,服务端和客户端就不能再通信。

    WebSocket 规范中定义了ping 帧 和pong 帧,可以用来做心跳重连,网络状态查询等,但是目前 浏览器只会自动发送pong帧,而不会发ping 帧。(有兴趣可详查ping和pong帧)

    JavaScript

    //关闭连接处理 ws.onclose = e => { const code = e.code; const reason = e.reason; console.log("Connection close", code, reason); };

    1
    2
    3
    4
    5
    6
    //关闭连接处理
    ws.onclose = e => {
        const code = e.code;
        const reason = e.reason;
        console.log("Connection close", code, reason);
    };

    背景图片

    接下来, 我们可以添加一些样式并设置背景图片位置:

    图片 10

    CSS

    .fave { width: 70px; height: 50px; background: url(images/twitter_fave.png) no-repeat; background-position: 0 0; }

    1
    2
    3
    4
    5
    6
    .fave {
      width: 70px;
      height: 50px;
      background: url(images/twitter_fave.png) no-repeat;
      background-position: 0 0;
    }

    加了悬停状态后,一旦鼠标悬停在该元素上,背景就会从我们指定的位置移动到这一系列图片中最后一张的位置上(为了兼容浏览器,注意要添加相应的浏览器内核前缀——译者注)。

    CSS

    .fave:hover{ animation: fave 1s steps(55); } @keyframes fave{ 0%{ background-position:0 0; } 100%{ background-position:-3519px 0; } }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .fave:hover{
      animation: fave 1s steps(55);
    }
    @keyframes fave{
      0%{
        background-position:0 0;
      }
      100%{
        background-position:-3519px 0;
      }
    }

    请注意第1个规则 animation。在本例中,我们利用 steps 时序函数,让background-position 属性经历了一个持续时间为1秒的过渡。在 steps 部分的“55”这个值,代表了这段动画是由55帧组成的。

    当我们将鼠标悬停在这个元素上时,所看到的效果是其背景图片通过55个相同的步骤经历了一次过渡。

    另外这个案例,也可以用 transition 实现:

    CSS

    .fave:hover { background-position: -3519px 0; transition: background 1s steps(55); }

    1
    2
    3
    4
    .fave:hover {
      background-position: -3519px 0;
      transition: background 1s steps(55);
    }

    4.1 WebSocket 构造函数

    WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。

    var ws = new WebSocket('ws://localhost:8080');

    1
    2
    var ws = new WebSocket('ws://localhost:8080');
     

    执行上面语句之后,客户端就会与服务器进行连接。

    实例对象的所有属性和方法清单,参见这里。

    WebSocket 方法:

    WebSocket 对象有两个方法:send 和 close

    • send:客户端和服务器建立连接后,可以调用send方法去发送消息。
    JavaScript
    
    //发送一个文本消息 ws.send("this is websocket");
    
    <table>
    <colgroup>
    <col style="width: 50%" />
    <col style="width: 50%" />
    </colgroup>
    <tbody>
    <tr class="odd">
    <td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
    <div class="crayon-num" data-line="crayon-5b8f447934b6d916593124-1">
    1
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b6d916593124-2">
    2
    </div>
    </div></td>
    <td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
    <div id="crayon-5b8f447934b6d916593124-1" class="crayon-line">
    //发送一个文本消息
    </div>
    <div id="crayon-5b8f447934b6d916593124-2" class="crayon-line crayon-striped-line">
    ws.send(&quot;this is websocket&quot;);
    </div>
    </div></td>
    </tr>
    </tbody>
    </table>
    

    在open事件的回调中调用send()方法传送数据:

    JavaScript

    const ws = new WebSocket('ws://localhost:8023'); ws.onopen = e => { console.log('Connection success'); ws.send(`Hello ${e}`); };

    1
    2
    3
    4
    5
    const ws = new WebSocket('ws://localhost:8023');
    ws.onopen = e => {
        console.log('Connection success');
        ws.send(`Hello ${e}`);
    };

    如果想通过响应其他事件发送消息,可通过判断当前的Websocket的readyState属性。接下来会说到readyState.

    • closeclose方法用来关闭连接。调用close方法后,将不能发送数据。close方法可以传入两个可选的参数,code 和reason, 以告诉服务端为什么终止连接。
    JavaScript
    
    ws.close(); //1000是状态码,代表正常结束。 ws.close(1000, "Closing
    normally");
    
    <table>
    <colgroup>
    <col style="width: 50%" />
    <col style="width: 50%" />
    </colgroup>
    <tbody>
    <tr class="odd">
    <td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
    <div class="crayon-num" data-line="crayon-5b8f447934b73487491254-1">
    1
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b73487491254-2">
    2
    </div>
    <div class="crayon-num" data-line="crayon-5b8f447934b73487491254-3">
    3
    </div>
    <div class="crayon-num crayon-striped-num" data-line="crayon-5b8f447934b73487491254-4">
    4
    </div>
    </div></td>
    <td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
    <div id="crayon-5b8f447934b73487491254-1" class="crayon-line">
    ws.close();
    </div>
    <div id="crayon-5b8f447934b73487491254-2" class="crayon-line crayon-striped-line">
     
    </div>
    <div id="crayon-5b8f447934b73487491254-3" class="crayon-line">
    //1000是状态码,代表正常结束。
    </div>
    <div id="crayon-5b8f447934b73487491254-4" class="crayon-line crayon-striped-line">
    ws.close(1000, &quot;Closing normally&quot;);
    </div>
    </div></td>
    </tr>
    </tbody>
    </table>
    

    本文由奥门新浦京网址发布于Wed前段,转载请注明出处:Twitter的&#8221;fave&#8221;动画

    关键词:

上一篇:登录工程,Web性能优化

下一篇:没有了