客户端(浏览器端)数据存储技术概览

2017/03/09 · 基础技术 ·
2 评论 ·
存储

原文出处: dwqs   

在客户端(浏览器端)存储数据有诸多益处,最主要的一点是能快速访问(网页)数据。(以往)在客户端有五种数据存储方法,而目前就只有四种常用方法了(其中一种被废弃了):

  • Cookies
  • Local Storage
  • Session Storage
  • IndexedDB
  • WebSQL (被废弃)

CSS或JS实现gif动态图片的停止与播放

2015/12/06 · CSS,
JavaScript ·
gif

原文出处:
张鑫旭   

一、屋外:寒风吹,雪花飘;屋内:空调吹,代码飘

上午出去买菜,正好下雨了,还夹杂着冰珠子。鄙人大意,穿的是一件帅气但单薄的黄色大衣,立马冻成了中华田园犬。原本计划去钓鱼的,科科,作罢,上午在家看CCTV5
骑士队vs鹈鹕队,下午补动漫码代码做文章,好生惬意。

图片 1

对于习惯性刷微博的我,总时不时会看到类似下面的游戏:

测测你和小白(白百何)有哪些共同点,戳开动图,最先看清的词是什么?ie浏览器的同学可以按esc键(或截屏),据说在哪个词暂停,哪个词就是你哦!图片 2

图片 3

OK,
这里出现一个浏览器特性,就是通过ESC快捷键,暂停gif的播放。据说FireFox浏览器以前也有,后来被干掉了,根据@紫云妃的说法是:

是这样的,Firefox原来的表现是:在页面load事件完成,同时x按钮变成刷新按钮之后,esc仍然有几个作用,中断当前正在发送的ajax,websocket,停止gif,apng动画的播放.但这些功能太小众了,影响了普通用户的使用,可能不小心按了esc,结果ajax断了,网页出错了.所以Firefox20修改成:网页加载完成后,esc键完全失效.

然而,这种隐晦的但似乎会影响正常功能的小技巧显然是无法实现真正意义上的gif动态图片的停止与播放的。一是兼容性,二是功能性,三是移动端没有ESC键。

所以,如果我们遇到需要可以随时随地停止gif动态图片播放的需求的时候,就需要寻找其他的出路。好,寒冬里的暖身结束,开始进入正题~~

Hybrid App技术解析 — 原理篇

2018/07/25 · JavaScript
· Hybrid

原文出处: 郭东东   

 

Cookies

Cookies 是一种在文档内存储字符串数据最典型的方式。一般而言,cookies
会由服务端发送给客户端,客户端存储下来,然后在随后让请求中再发回给服务端。这可以用于诸如管理用户会话,追踪用户信息等事情。

此外,客户端也用使用 cookies 存储数据。因而,cookies
常被用于存储一些通用的数据,如用户的首选项设置。

二、gif图片自己可控前提下的方法一:多img资源控制处理

假如说,我们希望暂停的gif是自己(开发人员)传上去的,不是用户可以随机上传不可控的gif.
我们可以这么处理,就是准备2套图片,一个是gif动态图片,还有一个是只有一帧的静止的图片。然后使用JS来回切换`的src`值为这两张图片地址就好了。

此方法甚简单,我就不放实例了。

img.src=”animate.gif”; // 或者呈现的是 img.src=”static.png”;

1
2
3
img.src="animate.gif";
// 或者呈现的是
img.src="static.png";

这个方法最大的优点就是兼容性强,所有浏览器都可以实现停止效果。然而,这种方法有个局限,就是,暂停时候呈现的图片永远是同一张。基本上可以说是停止,而不是暂停。

那有没有什么方法可以真正意义上的暂停呢?还真有!

引言

随着 Web 技术和移动设备的快速发展,Hybrid
技术已经成为一种最主流最常见的方案。一套好的 Hybrid架构方案 能让 App
既能拥有极致的体验和性能,同时也能拥有 Web技术
灵活的开发模式、跨平台能力以及热更新机制,想想是不是都鸡冻不已。。😄。本系列文章是公司在这方面实践的一个总结,包含了原理解析、方案选型与实现、实践优化等方面。

大家可以到github上和我进行讨论哈!

Cookies 的 基本CRUD 操作

通过下面的语法,我们可以创建,读取,更新和删除 cookies:

JavaScript

// Create document.cookie = “user_name=Ire Aderinokun”; document.cookie
= “user_age=25;max-age=31536000;secure”; // Read (All) console.log(
document.cookie ); // Update document.cookie =
“user_age=24;max-age=31536000;secure”; // Delete document.cookie =
“user_name=Ire Aderinokun;expires=Thu, 01 Jan 1970 00:00:01 GMT”;

1
2
3
4
5
6
7
8
9
10
11
12
// Create
document.cookie = "user_name=Ire Aderinokun";  
document.cookie = "user_age=25;max-age=31536000;secure";
 
// Read (All)
console.log( document.cookie );
 
// Update
document.cookie = "user_age=24;max-age=31536000;secure";
 
// Delete
document.cookie = "user_name=Ire Aderinokun;expires=Thu, 01 Jan 1970 00:00:01 GMT";

三、gif图片自己可控前提下的方法二:CSS3 animation控制

也就是我们看到的gif效果并不是一个真正的gif图片,而是使用CSS3的animation属性控制形成的逐帧动态图片效果。我搜了下,@DO1路人乙有篇文章“css3-animation制作逐帧动画”专门介绍了这种技术。说穿了就是animation控制Sprites图片的background-position值模拟gif效果。

例如,新版twitter的Like的效果,貌似就有使用该技术:
图片 4

使用CSS3
animation实现类gif效果的好处在于,图片可以无损,且我们可以很轻松地控制图片动画的暂停和播放,使用的是:animation-play-state: paused;这个声明。

您可以狠狠地点击这里:使用CSS3
animation实现gif动图的暂停和播放demo

点击demo页面的暂停按钮,您会发现,直接就停住了,如下截图示意,截自IE10浏览器:
图片 5

再次点击,就会在暂停画面之后继续播放了。从而实现了我们对动画图片的精确控制效果。

此方法看上去完美,但是,1. IE10+等支持CSS3 animation的浏览器才行;2.
最大的问题是图片需要是自己控制,如果想控制用户上传的真正意义的gif图片,只能……望洋兴叹……………………吗?

现有混合方案

Hybrid App,俗称混合应用,即混合了 Native技术 与 Web技术
进行开发的移动应用。现在比较流行的混合方案主要有三种,主要是在UI渲染机制上的不同:

  1. 基于 WebView UI 的基础方案,市面上大部分主流 App
    都有采用,例如微信JS-SDK,通过 JSBridge 完成 H5 与 Native
    的双向通讯,从而赋予H5一定程度的原生能力。
  2. 基于 Native UI 的方案,例如 React-Native、Weex。在赋予 H5
    原生API能力的基础上,进一步通过 JSBridge
    将js解析成的虚拟节点树(Virtual DOM)传递到 Native 并使用原生渲染。
  3. 另外还有近期比较流行的小程序方案,也是通过更加定制化的
    JSBridge,并使用双 WebView
    双线程的模式隔离了JS逻辑与UI渲染,形成了特殊的开发模式,加强了 H5 与
    Native 混合程度,提高了页面性能及开发体验。

以上的三种方案,其实同样都是基于 JSBridge
完成的通讯层,第二三种方案,其实可以看做是在方案一的基础上,继续通过不同的新技术进一步提高了应用的混合程度。因此,JSBridge
也是整个混合应用最关键的部分,例如我们在设置微信分享时用到的
JS-SDK,wx对象 便是我们最常见的 JSBridge:

图片 6

Cookies 的优点

  • 能用于和服务端通信
  • 当 cookie 快要自动过期时,我们可以重新设置而不是删除

四、自己无法控制的gif图片的停止与播放

比方说,页面上用户上传了些gif图片,哎呀,闪瞎了我的中华田园眼,我要全部暂停,肿么办?如果后台同学没有对gif进行静态处理,此时,只能靠前端小伙伴,有什么办法吗?

有一个。HTML5
canvas可以读取图片信息,绘制当前图片。于是可以实现图片马赛克,模糊,色值过滤等很多图片特效。我们这里不用那么复杂,只要读取我们的图片,重绘下就可以。

您可以狠狠地点击这里:使用JS和canvas实现gif动图的停止和播放demo

点击按钮,然后:
图片 7

图片 8

如何使用?
我对HTMLImageElement原型进行了扩展,增加了stop()play()两个方法,如下:

if (‘getContext’ in document.createElement(‘canvas’)) {
HTMLImageElement.prototype.play = function() { if (this.storeCanvas) {
// 移除存储的canvas
this.storeCanvas.parentElement.removeChild(this.storeCanvas);
this.storeCanvas = null; // 透明度还原 image.style.opacity = ”; } if
(this.storeUrl) { this.src = this.storeUrl; } };
HTMLImageElement.prototype.stop = function() { var canvas =
document.createElement(‘canvas’); // 尺寸 var width = this.width, height
= this.height; if (width & height) { // 存储之前的地址 if
(!this.storeUrl) { this.storeUrl = this.src; } // canvas大小
canvas.width = width; canvas.height = height; // 绘制图片帧(第一帧)
canvas.getContext(‘2d’).drawImage(this, 0, 0, width, height); //
重置当前图片 try { this.src = canvas.toDataURL(“image/gif”); } catch(e)
{ // 跨域 this.removeAttribute(‘src’); // 载入canvas元素
canvas.style.position = ‘absolute’; // 前面插入图片
this.parentElement.insertBefore(canvas, this); // 隐藏原图
this.style.opacity = ‘0’; // 存储canvas this.storeCanvas = canvas; } }
}; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
if (‘getContext’ in document.createElement(‘canvas’)) {
    HTMLImageElement.prototype.play = function() {
        if (this.storeCanvas) {
            // 移除存储的canvas
            this.storeCanvas.parentElement.removeChild(this.storeCanvas);
            this.storeCanvas = null;
            // 透明度还原
            image.style.opacity = ”;
        }
        if (this.storeUrl) {
            this.src = this.storeUrl;    
        }
    };
    HTMLImageElement.prototype.stop = function() {
        var canvas = document.createElement(‘canvas’);
        // 尺寸
        var width = this.width, height = this.height;
        if (width & height) {
            // 存储之前的地址
            if (!this.storeUrl) {
                this.storeUrl = this.src;
            }
            // canvas大小
            canvas.width = width;
            canvas.height = height;
            // 绘制图片帧(第一帧)
            canvas.getContext(‘2d’).drawImage(this, 0, 0, width, height);
            // 重置当前图片
            try {
                this.src = canvas.toDataURL("image/gif");
            } catch(e) {
                // 跨域
                this.removeAttribute(‘src’);
                // 载入canvas元素
                canvas.style.position = ‘absolute’;
                // 前面插入图片
                this.parentElement.insertBefore(canvas, this);
                // 隐藏原图
                this.style.opacity = ‘0’;
                // 存储canvas
                this.storeCanvas = canvas;
            }
        }
    };
}

大家只要在页面中自己的JS文件中复制上面的代码,然后就可以直接:

var image = document.getElementsByTagName(“img”)[0]; // 停止gif图片
image.stop(); // 播放gif图片 image.play();

1
2
3
4
5
var image = document.getElementsByTagName("img")[0];
// 停止gif图片
image.stop();
// 播放gif图片
image.play();

//zxx:
上面代码并未详尽测试,以及可能的体验问题(IE闪动)没有具体处理(影响原理示意),若要实际使用,需要自己再微调完美下。

不足

  1. IE9+支持。IE7/IE8不支持canvas没搞头。
    2.
    只能停止gif,不能真正意义的暂停。因为canvas获得的gif图片信息为第一帧的信息,后面的貌似获取不到。要想实现暂停,而不是停止,还需要进一步研究,如果你有方法,非常欢迎分享。

方案选型

任何技术方案的选型,其实都应该基于使用场景和现有条件。基于公司现有情况的几点考虑,在方案一上进一步优化,更加适合我们的需求。

  • 需求 Web技术 快速迭代、灵活开发的特点和线上热更新的机制。
  • 产品的核心能力是强大的拍照与底层图片处理能力,因此单纯的
    H5技术能做的事非常有限,不能满足需求,通过 Hybrid
    技术来强化H5,便是一种必需。
  • 公司业务上,并没有非常复杂的UI渲染需求,而且 App 中的一系列原生
    UI组件 已经非常成熟,因此我们并不强需类似 RN 这样的方案。

因此,如何既能利用 H5 强大的开发和迭代能力,又能赋予 H5
强大的底层能力和用户体验,同时能复用现有的成熟
Native组件
,便成为了我们最大的需求点 — 一套完整又强大的
Hybrid技术架构方案。😠

Cookies 的缺点

  • 增加了文档传输的负载
  • 只能存储少量的数据
  • 只能存储字符串
  • 潜在的
    安全问题
  • 自从有 Web Storage
    API
    (Local and Session Storage),cookies 就不再被推荐用于存储数据了

五、结束语

是胡不是霍,是霍躲不过!哈哈!
图片 9
上面这个gif也是demo示意gif强力候选。后来一琢磨,看我文章的还是宅男多,腐女少,所以,你懂的……
图片 10

——我是多年不见的低调的分隔线—–

本文gif比较多,如果您是移动设备查看本文,会发现,怎么我的电池怎么越来越瘦了!不是因为天冷冻小了,而是gif比较耗电。所以,从这个角度讲,我们其实有必要在移动端默认停止这些gif的播放,用户点击再播放。一来省流量,二来省电。

如果没有静态图片资源支持,那不妨试试文章出现的一些方法,有心得记得来这里反馈哈!
图片 11

最后,本文的方法都是有瑕疵的,自己也尚未在实际项目中使用过。因此,假如阅读本文的您:

  1. 有更完美的gif暂停与播放方法;
  2. 发现文中方法有不足和遗漏;

都非常希望可以不吝赐教!

感谢阅读!周末温暖!

 

1 赞 6 收藏
评论

图片 12

Hybrid技术原理

Hybrid App的本质,其实是在原生的 App 中,使用 WebView 作为容器直接承载
Web页面。因此,最核心的点就是 Native端 与 H5端
之间的双向通讯层,其实这里也可以理解为我们需要一套跨语言通讯方案,来完成
Native(Java/Objective-c/…) 与 JavaScript 的通讯。这个方案就是我们所说的
JSBridge,而实现的关键,便是作为容器的 WebView,一切的原理都是基于
WebView 的机制。

图片 13

浏览器支持

所有主流浏览器均支持 Cookies.

(一) JavaScript 通知 Native

基于 WebView 的机制和开放的 API, 实现这个功能有三种常见的方案:

  • API注入,原理其实就是 Native 获取
    JavaScript环境上下文,并直接在上面挂载对象或者方法,使 js
    可以直接调用,Android 与 IOS 分别拥有对应的挂载方式。
  • WebView 中的 prompt/console/alert 拦截,通常使用
    prompt,因为这个方法在前端中使用频率低,比较不会出现冲突;
  • WebView URL Scheme 跳转拦截

第二三种机制的原理是类似的,都是通过对 WebView
信息冒泡传递的拦截,从而达到通讯的,接下来我们主要从
原理-定制协议-拦截协议-参数传递-回调机制 5个方面详细阐述下第三种方案
— URL拦截方案。

Local Storage

Local Storage 是 Web Storage
API
的一种类型,能在浏览器端存储键值对数据。Local Storage
因提供了更直观和安全的API来存储简单的数据,被视为替代 Cookies
的一种解决方案。

从技术上说,尽管 Local Storage
只能存储字符串,但是它也是可以存储字符串化的JSON数据。这就意味着,Local
Storage 能比 Cookies 存储更复杂的数据。

1. 实现原理

在 WebView 中发出的网络请求,客户端都能进行监听和捕获

发表评论

电子邮件地址不会被公开。 必填项已用*标注