您的位置:云顶娱乐v1.8 > 澳门云顶娱乐app官网 > 做可相信交互动画的,静态财富文件自动削减并

做可相信交互动画的,静态财富文件自动削减并

2019-10-01 21:21

H5 动画:轨迹移动

2017/11/10 · HTML5 · 动画

初稿出处: 坑坑洼洼实验室   

 

动画,是指由众多帧静止的镜头,以自然的速度(如每秒16张)一而再播放时,肉眼因视觉残象发生错觉,而误感到画面活动的小说。

在 Web 开拓中,常常必要贯彻各样卡通效果,举例:移动、变形、折射率变化等,明天我们任重(Ren Zhong)而道远来谈谈种种活动的落到实处。

Web前端开采本事栈

今天风行叁个说法,是Full Stack (全栈),轻易地正是万金油,说得赏心悦目一点就是前边多个、后台、存款和储蓄、架构等都懂,小编以为自身不是全栈,而是爆栈(stack overflow),开玩笑了。。。。

其一Web前端开垦技能栈,大约十多少个层级,大概玖20个技术点,从尾部向来到最顶层:

  • 浏览器
  • 渲染引擎、JavaScript引擎
  • HTML/JavaScript/CSS三支柱
  • 编辑器
  • 编写翻译职责
  • 编写翻译工具
  • 打包、调试、质量
  • 测试
  • JS基础类库
  • JS类库
  • UI框架
  • CSS预管理器
  • 模板
  • 现代化
  • 安全/模式
  • 个中语言
  • 跨平台施工方案

本条图片里的分类未必正确,相关技术也难免会有遗漏,款待大家引导以便不断创新。

Web前端工夫其实太相当多限于篇幅,,这里未有罗列一些本领。

以下是预览图:

云顶娱乐v1.8 1

点击查看原尺寸大图

别的版本

上面的版本已经契合了我们的急需,时间复杂度是 O(1),不用循环和递归。

其余,我们还足以有任何的本子,它们严酷来讲有的依旧“犯规”,不过我们如故得以学学一下那几个思路:

版本4:用 Math.sqrt

JavaScript

function isPowerOfFour(num) { num = Math.sqrt(num); return num > 0 && num === (0|num) && (num & (num-1)) === 0; };

1
2
3
4
function isPowerOfFour(num) {
    num = Math.sqrt(num);
    return num > 0 && num === (0|num) && (num & (num-1)) === 0;
};

本子5:用正则表明式

JavaScript

function isPowerOfFour(num) { return /^1(00)*$/g.test(num.toString(2)); };

1
2
3
function isPowerOfFour(num) {
    return /^1(00)*$/g.test(num.toString(2));
};

以上就是兼具的内容,那道题有特别各种思路,至极有意思,也正如考验基本功。如若您有谈得来的思路,能够留言参与钻探。

上一期大家研讨除此以外一道题,那道题比这两道题要难有的,但也更风趣:给定三个正整数 n,将它拆成最少三个正整数之和,对拆出的正整数求乘积,重返可以获得的乘积最大的结果

想一想你的解法是怎么样?你可知尽也许降低算法的时日复杂度吗?期望您的答案~~

打赏帮忙自身写出更加多好文章,多谢!

打赏小编

有关笔者:Abel

云顶娱乐v1.8 2

简单介绍还没来得及写 :) 个人主页 · 小编的小说 · 10

云顶娱乐v1.8 3

静态财富文件自动削减并替换来压缩版本(大型网址优化技艺)

2015/11/26 · HTML5 · 静态能源

原稿出处: Kelly   

这一遍,小编计算和分享一项大型网址优化技艺,那正是在品种中活动削减静态能源文件(css、js),并让网址自行加载压缩后的能源文件。当然,那项本领在雅虎35条前端优化建议里也会有记载,但它那只是给出四个辩解的方案而已,並且采纳的是外界压缩工具去收缩,而在自身的种类中,是间接通过协和的次第自动化去减弱全体css、js文件,然后让页面平素加载所减弱后的能源,接下去直接进去正题。

这次试验应用的是PHP脚本语言,版本是PHP5.6,是在LINUX下搭建的条件(网络搭建无论是搭建LAMP依然LNMP的学科都精彩纷呈杂乱无章,后一次笔者会总括和分享怎样在LINUX下搭建服务器情状的博文,何况搭建的景况必需一次性搭建成功的)。所选取的框架是CI框架,所选拔的模版是Smarty模板引擎。当然了,那么些只是自己所使用的条件而已,假若你是PHP开采者,若是你要测验下此次实验,那么,作者提出您的PHP版本接纳5.4以上,至于框架用如何都以足以的。而一旦您不是PHP开荒者(你是JSP恐怕是ASP开垦者可能是其余开垦者),那么您了解好这一思路后,完全能够在融洽熟习的语言里开展尝试测验。

一、原理图

第一自身画一张思路图,便于大家先明了。

率先是能源减弱原理图:

云顶娱乐v1.8 4

继而是能源文件替换的准则图:

云顶娱乐v1.8 5

要是大家认真明白何况看懂这两张原理图的话,基本上也就调整了自身所享受的思绪。借使还是不能够知晓的话,接下去笔者会结合代码,对以上原理图的每一步举行详尽解说。

二、思路详细剖析

1.率先是调用该滑坡的秘籍,你能够把该措施放在网址所要加载的公共类的地点,举例每一回访谈网址都会调用该滑坡方法举行压缩。当然,这几个只是在付出条件才会每回都调用,要是是线上的情况,在你的网址发二遍新本子的时候,调用三次用来生成压缩版的静态财富就可以了。

class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss能源文件 $this->compressResHandle(); } /** * 压缩js、css财富文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('Res迷你fier'); //压缩钦命文件夹下的能源文件 $this->resminifier->compressRes(); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}

2.跟着就调用了 ResMinifier类里的 compressRes方法。在这里自身先附上 ResMinifier那一个类的代码,然后方便一步步开展剖析教学

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 财富压缩类 */ class ResMinifier { /** 供给减小的能源目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的门径,举例此处是js/icon开首的路子忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 财富根目录*/ public $resRootDir; /** 财富版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; } public function compressRes() { //获取存放版本的财富文件 $resState = $this->getResState(); $count = 0; //早先遍历要求裁减的财富目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该财富文件的绝对路径$filePath = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //计算文件的版本号 $state = $this->_getResStateVersion($filePath); //获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; } //压缩文件的相对路线 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p判别是最注重部分之一*****************// //决断文件是不是存在且早已改成过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; } //确认保障/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); } $resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState); } public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取财富相对路线 $filePath = $this->resRootDir . $object; //判断能源是还是不是留存 if (!file_exists($filePath)) return "能源文件空中楼阁{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是或不是要缩减 $needCompress = true; //判别财富文件是不是是以 .min.css可能.min.js结尾的 //此类结尾经常都是已回降过,比如jquery.min.js,就不要再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的资源寄放路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是索要减小的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是或不是是忽略的路线前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; } /** * 获取存放能源版本的文书 * 它是身处叁个数组里 * $resState = array( * '文件路径' => '对应的本子号', * '文件路线' => '对应的版本号', * '文件路线' => '对应的本子号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; } /** * 统计文件的本子号,那些是依据总计文件MD5散列值获得版本号 * 只要文件内容改换了,所总括获得的散列值就能够不平等 * 用于剖断能源文件是还是不是有退换过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); } /** * 确定保障目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } } /** * 将精减后的财富文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFile帕特h}败北"); show_error("写入文件{$minFilePath}退步", -1); } } /** * 压缩能源文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]"); show_error("不帮忙压缩{extension}文件[$filePath]", -1); } } private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resState帕特h, $content); } } 点击打开财富压缩类

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 资源压缩类
*/
class ResMinifier {
    /** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }
 
    public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;
 
        //开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);
 
                //获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }
 
                //压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }
 
                //确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }
 
                $resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);
    }
 
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }
 
    /**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }
 
    /**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }
 
    /**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }
 
    /**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }
 
    private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }
 
}
 
点击打开 资源压缩类

全副类半数以上代码小编都加了解说,方便大家急迅领悟。这里笔者也会对每一行代码实行解释。

(1)

PHP

/** 需求减小的财富目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的路线,举个例子此处是js/icon初阶的门径忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 能源根目录*/ public $resRootDir; /** 能源版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; }

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }

$compressResDir变量是亟需减小的能源目录,倘让你有新的拍卖目录,能够在此变量里如若新的目录名就能够管理。附上自个儿测试项指标目录图

云顶娱乐v1.8 6

$compressResIngorePrefix 忽略被审核消减的不二等秘书诀的不二秘籍前有个别是该数组变量的字符串,比如有壹个能源路线为 js/icon/bg.js也许是js/icon_index.js或然是js/icon.header.js,如果在该数组中步入了 js/icon这么些字符串,那么能源路线为js/icon开始的都会被忽视掉,也正是直接跳过,不用压缩。(因为财富文件里总有一对是没有须要减弱的呗)

$resRootDir存放能源根目录的

$resStatePath 这几个是财富版本文件路线

(2)进入compressRes() 方法,大家先剖判前边这一段代码

PHP

public function compressRes() { //获取贮存版本的能源文件 $resState = $this->getResState(); $count = 0;

1
2
3
4
public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;

——————————-调用getResState() 讲解start————————————————————-

那边首先是调用 $this->getResState() 方法来获得贮存版本的能源文件,此处先跳到该措施看看是如何写的,其实正是含有该公文,然后回来里面寄放版本号的数组,大家看注释能够清楚该文件里寄放版本号的格式(顺便附上海教室让我们看看)

PHP

/** * 获取寄放资源版本的文书 * 它是放在二个数组里 * $resState = array( * '文件路线' => '对应的本子号', * '文件路线' => '对应的本子号', * '文件路径' => '对应的版本号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }

(财富版本文件截图:)

云顶娱乐v1.8 7

——————————-调用getResState() 讲解end————————————————————-

紧接着看compressRes()里的这一段代码

PHP

//开始遍历须要减小的能源目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该资源文件的相对路径$filePath = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //计算文件的本子号 $state = $this->_getResStateVersion($filePath);

1
2
3
4
5
6
7
8
9
//开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);

第一个遍历的是js和css目录 第二个遍历是将js目录只怕css目录里的文件都成为路线方式,

比方获取文件的相对路线 $filePath 的值是那样子的:

/usr/local/apache2/htdocs/project/www/css/home/index.css

而文件的相对路线$object是这样子的 :

css/home/index.css

此间就起来调用$this->_getResStateVersion($filePath)来计量文件的版本号

——————————-调用_getResStateVersion($filePath) 讲解start————————————————————

PHP

/** * 总计文件的本子号,那些是依赖总括文件MD5散列值获得版本号 * 只要文件内容退换了,所总计得到的散列值就能不一致样 * 用于决断能源文件是或不是有退换过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); }

1
2
3
4
5
6
7
8
9
10
/**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }

——————————-调用_getResStateVersion($filePath) 讲解end————————————————————-

恐怕到版本号后,再看下一段代码,这里起初调用$this->getObjectInfo()方法,这里收获到压缩文件的相对路线$minObject,是或不是必要压缩$needCompress,版本号$state,文件后缀$extension。

PHP

//获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; }

1
2
3
4
//获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }

——————————调用$this->getObjectInfo() 讲解start————————————————————

PHP

/** * 获取能源文件有关新闻 * @param [type] $object 能源文件路线(www/css/home/index.css) * @param [type] $minObject 压缩能源文件路径(www/min/css/home/index.ae123a.css) * @param [type] $needCompress 是或不是须要压缩 * @param [type] $state 文件版本号 * @param [type] $extension 文件名后缀 * @return [type] [description] */ public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取能源相对路线 $filePath = $this->resRootDir . $object; //推断财富是不是留存 if (!file_exists($filePath)) return "资源文件不设有{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($file帕特h, PATHINFO_EXTENSION); //是还是不是要压缩 $needCompress = true; //推断能源文件是还是不是是以 .min.css也许.min.js结尾的 //此类结尾日常都以已回退过,比如jquery.min.js,就无需再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的能源寄存路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是急需减小的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是还是不是是忽略的不二法门前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; }

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
/**
     * 获取资源文件相关信息
     * @param  [type] $object       资源文件路径 (www/css/home/index.css)
     * @param  [type] $minObject    压缩资源文件路径 (www/min/css/home/index.ae123a.css)
     * @param  [type] $needCompress 是否需要压缩
     * @param  [type] $state        文件版本号
     * @param  [type] $extension    文件名后缀
     * @return [type]               [description]
     */
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }

本条主意里的每一行代码基本上都有注释了,所以就不一句句实行解说了,这里关键看下边包车型客车判定部分:

if (str_end_with($object, ‘.min.’.$extension, true)) 那个推断是比较财富文件路线字串尾部是不是以 .min.$extension 结尾,比如是 jquery.min.js,这种文件本来正是
压缩过的公文,所以就不用再举办压缩管理了, $minObject 那几个变量贮存的是压缩后的能源文件路线。
此处附上str_end_with()函数的代码:

PHP

/** * 决断 subject 是不是以 search结尾, 参数内定是不是忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_end_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len2 > $len1) return false; if ($ignore_case) { return 0 === strcmp(substr($subject, $len1 - $len2), $search); } else { return 0 === strcasecmp(substr($subject, $len1 - $len2), $search); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
     * 判断 subject 是否以 search结尾, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_end_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len2 > $len1) return false;
        if ($ignore_case) {
            return 0 === strcmp(substr($subject, $len1 - $len2), $search);
        } else {
            return 0 === strcasecmp(substr($subject, $len1 - $len2), $search);
        }
    }

if (in_array($extension, $this->compressResDir),这么些判别正是是还是不是是需求管理的多少个目录里的。

接下来里面包车型大巴foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } }

本条是决断是不是是以$this->compressResIngorePrefix属性定义的尾部字串发轫的路子,是的话就忽略压缩该财富文件。

判定到最终else 便是认证该财富文件不须要减弱了,最终是回去$minObject,$needCompress,$state,$extension这两个变量。

——————————-调用$this->getObjectInfo() 讲解end————————————————————-

到那边继续回来看 compressRes()方法里面包车型客车代码

PHP

//压缩文件的相对路径 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p判断是最注重片段之一*****************// //判定文件是还是不是留存且已经转移过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; }

1
2
3
4
5
6
7
8
//压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }

这段代码首先是东拼西凑出压缩文件的相对路线,

随后下边这一个论断是重要的有的,通过那几个判定就能够知道该财富文件是不是被改成过,如若更换过的话,就再一次对该财富文件进行削减,就算没改动过,就继续管理下一个财富文件。看这里的推断:isset($resState[$object]) && $resState[$object] == $state,这么些论断便是判别该公文路径是或不是存在  况且文件中对应的版本号和计算出的版本号是或不是还同样;isset($resState[$minObject]) &&file_exists($minFilePath),那些是判断压缩文件路线是不是留存,并且该压缩文件是还是不是真实存在目录中。

看下一段代码,假设能走到这一有的,表达当前的这么些财富文件是被改成过的(代码修改过),那么此时就对文件举办削减操作了

PHP

//确定保证/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); }

1
2
3
4
5
6
7
8
//确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }

$this->_ensureWritableDir(),此方式是要力保新创设的www/min目录是可写的,这里附上代码:

——————————-调用$this->_ensureWritableDir() 讲解start————————————————————-

PHP

/** * 确定保障目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }

——————————-调用$this->_ensureWritableDir() 讲解end————————————————————-

if ($needCompress),这一个论断能源文件是还是不是须要裁减,要求的话调用$this->compressResFileAndSave($filePath, $minFilePath);不必要的话,直接复制文件到压缩文件路线 copy($filePath, $minFilePath);

先看$this->compressResFileAndSave()

——————————-调用$this->compressResFileAndSave() 讲解start————————————————————-

PHP

/** * 将核减后的能源文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFilePath}失利"); show_error("写入文件{$minFilePath}退步", -1); } } /** * 压缩能源文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不扶助压缩{extension}文件[$filePath]"); show_error("不帮衬压缩{extension}文件[$filePath]", -1); } }

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
/**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }

先削减,再将削减后的内容写入到 压缩文件路线里去。

咱俩先看下那些压缩方法:

$this->compressResFile($filePath); 此方法中分两类压缩,第一类时对js文件进行压缩,第二类的对css文件进行削减。先说js压缩,这里是调用二个JShrink的类,它

二个用来压缩js文件的PHP类,百度得以找到,调用这么些类的minify()那些主意就可以减去了;而css的滑坡利用正则替换成压缩,把这几个空格换行什么的都去掉。到此就收缩成功

了,然后再将回退后的财富写入到相应的压缩文件路线里去。

——————————-调用$this->compressResFileAndSave() 讲解end————————————————————-

随着继续看compressRes()这么些方法里的代码,这里开头正是保存新的版本号到$resState数组里 $object=>$state,还会有正是新的缩减路线$minObject,而那边$count++的效应是,当那一个轮回四17次就将 $resState这么些数组写入一回到 resState.php文件里,这里是出于审慎思索而已,若是你不加这个$count的管理这一部分也足以,最终写入一遍就行了。

PHP

$resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState);

1
2
3
4
5
6
7
8
9
10
11
12
$resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);

这里看$this->_saveResState($resState),这些主意便是将$resState数组写入到resState.php文件里去的不二秘籍。

——————————-调用$this->_saveResState($resState) 讲解start————————————————————-

PHP

private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resStatePath, $content); }

1
2
3
4
5
6
7
8
9
private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }

——————————-调用$this->_saveResState($resState) 讲解end————————————————————-

管理完后,看看所生成的文本,这里四个文书会有三个本子,旧版本从没有过去除掉,在开垦景况下删不删除都没难点,这里怎么不删除旧版本的压缩文件,这就涉嫌到在更新多少个应用服务器代码时所要注意的标题里。在此笔者就多解说一点啊,轻易地举例吗,日常大型项目中的静态财富和模板文件是布局在分裂的机械集群上的,上线的经过中,静态财富和页面文件的配置时间间隔大概会格外长,对于三个大型互连网应用来讲即使在多少个相当的小的时间间隔内,都有希望出现新顾客访谈,若是旧版本的静态财富删除了,但新本子的静态能源还没安插到位,那么客商就加载不到该静态财富,结果显而易见,所以,平时意况下大家会保留旧版本的静态财富,然后等全数片段安插产生了,再经过一定的本子删除掉也没涉及,其实,这么些不必删除也是足以的,你思量,贰个项目发三次版本,才会调用壹回财富文件收缩方法,它只会对修改过的公文举办生成新版本号的静态文件而已。这个就看个人的做法了。

云顶娱乐v1.8 8

我们得以展开看看,上边这么些正是降低后的文本的代码了,文件原大小为16K,压缩后大致少了5K,现在是11K,压缩比差不离是2/3,假设在大型项目中,五个复杂点的页面会有不小的静态能源文件要加载,通过此措施,大大地加强了加载的进度。(恐怕有个别朋友以为压缩个几K可能十几K算什么,完全能够忽略,其实笔者想说的是,当你在大型项目中优化项指标时候,能够收缩几K的代码,也给网址的质量升高了一大截)

云顶娱乐v1.8 9

到此,财富缩短处理就深入分析实现了。其实,有早晚基础的相恋的人,能够间接看笔者享受的那三个代码就足以了,若是驾驭不了,再看本人上面这一步步的剖析教学,小编是地处能看过来此博客的对象,无论技能是好也许是稍弱,都能看懂,所以才对代码一步步地扩充深入分析教学。(希望各位不吝指教二哥)

————————————————————————————————————————-

  1. 接下去正是教授怎么着替换压缩后的能源文件了。

这个到Home.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Home extends MY_Controller { public function index() { $this->smartyData['test'] = 111; //那一个暗中认可是加载 www/css/home/index.css文件 $this->addResLink('index.css'); //那一个暗中同意是加载www/js/jquery.all.min.js文件 $this->addResLink('/jquery.all.min.js'); //这几个默许是加载www/js/index.js文件 $this->addResLink('index.js'); $this->displayView('home/index.tpl'); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class Home extends MY_Controller {
    public function index() {
        $this->smartyData['test'] = 111;
        //这个默认是加载 www/css/home/index.css文件
        $this->addResLink('index.css');
        //这个默认是加载www/js/jquery.all.min.js文件
        $this->addResLink('/jquery.all.min.js');
        //这个默认是加载www/js/index.js文件
        $this->addResLink('index.js');
        $this->displayView('home/index.tpl');
    }
}

地点有加载八个财富文件,大家先看看$this->addResLink();这么些点子,这些点子放在My_Controller.php里:

PHP

/** * 能源路线 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }

这里重若是剖断了财富文件是css依然js,然后将其存放在 $this->_resLink那特特性里。

那就是说这里作者就先附上My_Controller.php那么些父类的享有代码吧

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss能源文件 $this->compressResHandle(); } //==========================使用SMARTY模板引擎================================// /* 斯马特y母版页文件路线 */ protected $masterPage = 'default.tpl'; /* 视图像和文字件路线*/ protected $smartyView; /* 要赋值给smarty视图的数码*/ protected $smartyData = []; /* 能源文件*/ protected $_resLink = ['js'=>[], 'css'=>[]]; /** * 使用母版页输出贰个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则采用暗中同意母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的出口内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //尾巴部分增加js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最终输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DI路虎极光.'斯马特y.class.php'; $this->smarty = new 斯马特y(); $this->smarty->setCompileDir(APPPATH . 'cache/'); $this->smarty->setCacheDir(应用程式PATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } } /** * 能源路线 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; } private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) { if ('/' === $viewName[0]) $viewName = substr($viewName, 1); //是还是不是使用模板,有,则路由到 /views/master_page/*****.tpl下去 if ($masterPage) { $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage); } //是或不是设置模板目录 if ($setTemplateDir) { $templateDir = VIEWPATH; $this->smarty->setTemplateDir($templateDir); } } /** * 压缩js、css财富文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('ResMinifier'); //压缩钦点文件夹下的财富文件 $this->resminifier->compressRes(); } } 点击张开 My_Controller.php

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
 
    //==========================使用SMARTY模板引擎================================//
    /* Smarty母版页文件路径 */
    protected $masterPage = 'default.tpl';
    /* 视图文件路径*/
    protected $smartyView;
    /* 要赋值给smarty视图的数据*/
    protected $smartyData = [];
    /* 资源文件*/
    protected $_resLink = ['js'=>[], 'css'=>[]];
 
    /**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }
 
    /**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }
 
    private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) {
        if ('/' === $viewName[0]) $viewName = substr($viewName, 1);
 
        //是否使用模板,有,则路由到 /views/master_page/*****.tpl下去
        if ($masterPage) {
            $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage);
        }
 
        //是否设置模板目录
        if ($setTemplateDir) {
            $templateDir = VIEWPATH;
            $this->smarty->setTemplateDir($templateDir);
        }
    }
 
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}
 
点击打开 My_Controller.php

打印出来 $this->_云顶娱乐v1.8 ,resLink那天天性的结构是那样子的:

PHP

Array ( [js] => Array ( [0] => /jquery.all.min.js [1] => index.js ) [css] => Array ( [0] => index.css ) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Array
(
    [js] => Array
        (
            [0] => /jquery.all.min.js
            [1] => index.js
        )
 
    [css] => Array
        (
            [0] => index.css
        )
 
)

再回去Home.php里面调用 $this->displayView(‘home/index.tpl’);

咱们看这些法子:

PHP

/** * 使用母版页输出三个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则选取暗许母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的出口内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //尾巴部分增添js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最后输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DI宝马7系.'斯马特y.class.php'; $this->smarty = new 斯马特y(); $this->smarty->setCompileDir(APPPATH . 'cache/'); $this->smarty->setCacheDir(应用程式PATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } }

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
46
47
48
49
50
51
52
53
/**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }

这一段代码未有一部分正是调用了Smarty模板引擎的内容,这么些关于斯马特y的知识笔者就不讲了,我们能够友善百度,这里关键讲 res_link() 这些函数,正是通过这么些函数来进展财富文件替换的。先看这几个函数的代码:

PHP

/** * 输出 HttpHead 中的能源总是。 css/js 自动推断真实路线 * @param string 文件路线 * @return string */ function res_link($file) { $file = res_path($file, $extension); if ($extension === 'css') { return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>'; } else if ($extension === 'js') { return '<script type="text/javascript" src="'.$file.'"></script>'; } else { return false; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
     * 输出 HttpHead 中的资源连接。 css/js 自动判断真实路径
     * @param  string  文件路径
     * @return string      
     */
    function res_link($file) {
        $file = res_path($file, $extension);
 
        if ($extension === 'css') {
           return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>';
        } else if ($extension === 'js') {
            return '<script type="text/javascript" src="'.$file.'"></script>';
        } else {
            return false;
        }
    }

此处最要害就是 res_path() 函数了,那一个函数能半自动路由财富的真实路线。比方:index.css = > css/home/index.css

该函数最要紧的三个效益是替换能源的滑坡版本。

直接看代码:

PHP

/** * 智能路由能源实际路线 * @param string 路径 * @param string 扩展名 * @return string 真实路线 */ function res_path($file, &$extension) { //检查是还是不是存在询问字符串 list($file, $query) = explode('?', $file . '?'); //取得扩大名 $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); // $file = str_replace('\', '/', $file); //取稳当前调控器名 global $class; if ($class == null) exit('can not get class name'); $className = strtolower($class); //此处的条条框框是这么: //举例,假诺不加 / ,Home调控器对应的格式是: index.css,那么 此处的路线会形成css/home/index.css //若是有 / ,调控器的格式能够是 /main.css,那么这里的路线会产生 css/main.css(公用的css类) if ('/' !== $file[0]) { //index.css => css/home/index.css $object = $extension .'/'. $className .'/' . $file; } else { // /css/main.css 大概 /main.css => css/main.css $object = substr($file, 1); //若object是 main.css ,则自动抬高 扩张名目录 => css/main.css if (0 !== strncasecmp($extension, $object, strlen($extension))) { $object = $extension . '/' . $object; } } //能源真实路线 $filepath = WEBROOT.'www/'.$object; //替换压缩版本,这一部分逻辑与公事减弱逻辑对应 if (in_array($extension, array('css', 'js'))) { if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) { require_once APPPATH.'libraries/ResMinifier.php'; $resminifier = new ResMinifier(); //获取寄存资源版本的文件的数组变量 $resState = $resminifier->getResState(); //总计取安妥前文件版本号 $state = $resminifier->_getResStateVersion($filepath); //判定该版本号是或不是存在 if (isset($resState[$object])) { //决断是不是是.min.css或.min.js结尾 if (str_end_with($object, '.min.'.$extension)) { //将版本号拼接上去,然后拿走min的文本路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension; } else { //将版本号拼接上去,然后拿走min的文书路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; } //判别min的不二等秘书技是或不是留存在$resState里面 if (isset($resState[$minObject])) { $object = $minObject; $query = ''; } } } $file = RES_老版本云顶娱乐 ,BASE_URL . $object; } return ($query == null) ? $file : ($file .'?'. $query); }

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
     * 智能路由资源真实路径
     * @param  string      路径
     * @param  string      扩展名
     * @return string       真实路径
     */
    function res_path($file, &$extension) {
        //检查是否存在查询字符串
        list($file, $query) = explode('?', $file . '?');
        //取得扩展名
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        //
        $file = str_replace('\', '/', $file);
        //取得当前控制器名
        global $class;
        if ($class == null) exit('can not get class name');
        $className = strtolower($class);
 
        //此处的规则是这样:
        //例如,如果不加 / ,Home控制器对应的格式是: index.css,那么 此处的路径会变成css/home/index.css
        //假如有 / ,控制器的格式可以是 /main.css,那么此处的路径会变成 css/main.css(公用的css类)
        if ('/' !== $file[0]) {
            //index.css => css/home/index.css
            $object = $extension .'/'. $className .'/' . $file;
        } else {
            // /css/main.css 或者 /main.css => css/main.css
            $object = substr($file, 1);
 
            //若object是 main.css ,则自动加上 扩展名目录 => css/main.css
            if (0 !== strncasecmp($extension, $object, strlen($extension))) {
                $object = $extension . '/' . $object;
            }
        }
        //资源真实路径
        $filepath = WEBROOT.'www/'.$object;
 
        //替换压缩版本,这部分逻辑与文件压缩逻辑对应
        if (in_array($extension, array('css', 'js'))) {
            if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) {
                require_once APPPATH.'libraries/ResMinifier.php';
                $resminifier = new ResMinifier();
                //获取存放资源版本的文件的数组变量
                $resState = $resminifier->getResState();
                //计算得到当前文件版本号
                $state = $resminifier->_getResStateVersion($filepath);
                //判断该版本号是否存在
                if (isset($resState[$object])) {
                    //判断是否是.min.css或.min.js结尾
                    if (str_end_with($object, '.min.'.$extension)) {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension;
                    } else {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
                    }
                    //判断min的路径是否存在在$resState里面
                     if (isset($resState[$minObject])) {
                        $object = $minObject;
                        $query = '';
                     }
                }
 
            }
 
            $file = RES_BASE_URL . $object;
        }
 
        return ($query == null) ? $file : ($file .'?'. $query);
 
    }

代码基本上都给了批注,方便大家轻易去理解,后边一部分是智能路线css、js财富的门径,后边一部分是替换压缩版本,这一部分的逻辑其实和能源减弱这里的逻辑基本同样,正是经过财富文件路线,进行决断和拍卖,最终获得财富的压缩版本的门路,最终就将资源的削减版本的不二诀窍再次回到去,放在'<link rel=”stylesheet” type=”text/css” href=”‘ . $file . ‘”/>’里面。那样  ,就成功地将财富文件路线替换来了削减版本的财富文件路线,况且在模板输出时,输出的是减掉后的财富文件。

到此,财富替换的剧情就到此解说甘休。而整一项手艺也解析到此。

三、总结

在此间小编聚集地附着本博文讲授中的多少个文件代码:

Home.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Home extends MY_Controller { public function index() { $this->smartyData['test'] = 111; //这些暗许是加载 www/css/home/index.css文件 $this->addResLink('index.css'); //这一个私下认可是加载www/js/jquery.all.min.js文件 $this->addResLink('/jquery.all.min.js'); //这么些私下认可是加载www/js/index.js文件 $this->addResLink('index.js'); $this->displayView('home/index.tpl'); } } 点击展开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class Home extends MY_Controller {
    public function index() {
        $this->smartyData['test'] = 111;
        //这个默认是加载 www/css/home/index.css文件
        $this->addResLink('index.css');
        //这个默认是加载www/js/jquery.all.min.js文件
        $this->addResLink('/jquery.all.min.js');
        //这个默认是加载www/js/index.js文件
        $this->addResLink('index.js');
        $this->displayView('home/index.tpl');
    }
}
 
点击打开

My_Controller.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Controller extends CI_Controller { public function __construct() { parent::__construct(); //压缩jscss财富文件 $this->compressResHandle(); } //==========================使用SMARTY模板引擎================================// /* 斯马特y母版页文件路线 */ protected $masterPage = 'default.tpl'; /* 视图像和文字件路径*澳门云顶娱乐app官网 ,/ protected $smartyView; /* 要赋值给smarty视图的数目*/ protected $smartyData = []; /* 能源文件*/ protected $_resLink = ['js'=>[], 'css'=>[]]; /** * 使用母版页输出七个视图 * @return [type] [description] */ protected function displayView($viewName = null, $masterPage = null) { //为空则采用默许母版 if ($masterPage == null) $masterPage = $this->masterPage; //获取视图的出口内容 $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage); $output = ''; //添加css Link foreach ($this->_resLink['css'] as $v) { $output .= res_link($v); } //内容部分 $output .= $viewContent; //后面部分增多js 链接 foreach ($this->_resLink['js'] as $v) { $output .= res_link($v); } //发送最后输出结果以及服务器的 HTTP 头到浏览器 $this->output->_display($output); return $output; } private function _fetchView($smartyData, &$viewName, &$masterPage) { if ($viewName == null) $viewName = $this->smartyView; if (empty($this->smarty)) { require_once SMARTY_DIEscort.'斯马特y.class.php'; $this->smarty = new Smarty(); $this->smarty->setCompileDir(应用软件PATH . 'cache/'); $this->smarty->setCacheDir(应用程式PATH . 'cache/'); } //设置视图真实路线 $this->_getViewDir(true, $viewName, $masterPage, $templateDir); foreach ($smartyData as $k => $v) { $this->smarty->assign($k, $v); } if (empty($masterPage)) { return $this->smarty->fetch($viewName); } else { $this->smarty->assign('VIEW_MAIN', $viewName); return $this->smarty->fetch($masterPage); } } /** * 财富路径 * @param [type] $filePath [description] */ protected function addResLink($filePath) { list($filePath, $query) = explode('?', $filePath . '?'); $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); foreach ($this->_resLink as $v) { if (false === array_search($filePath, $this->_resLink[$extension])) { $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query; } } return $this; } private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) { if ('/' === $viewName[0]) $viewName = substr($viewName, 1); //是不是使用模板,有,则路由到 /views/master_page/*****.tpl下去 if ($masterPage) { $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage); } //是不是设置模板目录 if ($setTemplateDir) { $templateDir = VIEWPATH; $this->smarty->setTemplateDir($templateDir); } } /** * 压缩js、css财富文件(优化) * @return [type] [description] */ private function compressResHandle() { $this->load->library('ResMinifier'); //压缩内定文件夹下的财富文件 $this->resminifier->compressRes(); } } 点击展开

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
 
class MY_Controller extends CI_Controller {
    public function __construct() {
        parent::__construct();
 
        //压缩jscss资源文件
        $this->compressResHandle();
    }
 
    //==========================使用SMARTY模板引擎================================//
    /* Smarty母版页文件路径 */
    protected $masterPage = 'default.tpl';
    /* 视图文件路径*/
    protected $smartyView;
    /* 要赋值给smarty视图的数据*/
    protected $smartyData = [];
    /* 资源文件*/
    protected $_resLink = ['js'=>[], 'css'=>[]];
 
    /**
     * 使用母版页输出一个视图
     * @return [type] [description]
     */
    protected function displayView($viewName = null, $masterPage = null) {
        //为空则选用默认母版
        if ($masterPage == null) $masterPage = $this->masterPage;
        //获取视图的输出内容
        $viewContent = $this->_fetchView($this->smartyData, $viewName, $masterPage);
 
        $output = '';
 
        //添加css Link
        foreach ($this->_resLink['css'] as $v) {
            $output .= res_link($v);
        }
 
        //内容部分
        $output .= $viewContent;
        //尾部添加js 链接
        foreach ($this->_resLink['js'] as $v) {
            $output .= res_link($v);
        }
        //发送最终输出结果以及服务器的 HTTP 头到浏览器
 
        $this->output->_display($output);
        return $output;
    }
 
    private function _fetchView($smartyData, &$viewName, &$masterPage) {
        if ($viewName == null) $viewName = $this->smartyView;
 
        if (empty($this->smarty)) {
            require_once SMARTY_DIR.'Smarty.class.php';
            $this->smarty = new Smarty();
            $this->smarty->setCompileDir(APPPATH . 'cache/');
            $this->smarty->setCacheDir(APPPATH . 'cache/');
        }
 
        //设置视图真实路径
        $this->_getViewDir(true, $viewName, $masterPage, $templateDir);
 
        foreach ($smartyData as $k => $v) {
            $this->smarty->assign($k, $v);
        }
 
        if (empty($masterPage)) {
            return $this->smarty->fetch($viewName);
        } else {
            $this->smarty->assign('VIEW_MAIN', $viewName);
            return $this->smarty->fetch($masterPage);
        }
    }
 
    /**
     * 资源路径
     * @param [type] $filePath [description]
     */
    protected function addResLink($filePath) {
        list($filePath, $query) = explode('?', $filePath . '?');
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        foreach ($this->_resLink as $v) {
            if (false === array_search($filePath, $this->_resLink[$extension])) {
                $this->_resLink[$extension][] = $query == null ? $filePath : $filePath .'?'. $query;
            }
        }
 
        return $this;
    }
 
    private function _getViewDir($setTemplateDir, &$viewName, &$masterPage = null, &$templateDir) {
        if ('/' === $viewName[0]) $viewName = substr($viewName, 1);
 
        //是否使用模板,有,则路由到 /views/master_page/*****.tpl下去
        if ($masterPage) {
            $masterPage = '/' === $masterPage[0] ? substr($masterPage, 1) : ('master_page' .'/'. $masterPage);
        }
 
        //是否设置模板目录
        if ($setTemplateDir) {
            $templateDir = VIEWPATH;
            $this->smarty->setTemplateDir($templateDir);
        }
    }
 
    /**
     * 压缩js、css资源文件(优化)
     * @return [type] [description]
     */
    private function compressResHandle() {
        $this->load->library('ResMinifier');
        //压缩指定文件夹下的资源文件
        $this->resminifier->compressRes();
    }
}
 
点击打开

ResMinifier.php

PHP

<?php defined('BASEPATH') OR exit('No direct script access allowed'); /** * 能源压缩类 */ class ResMinifier { /** 要求减小的能源目录*/ public $compressResDir = ['css', 'js']; /** 忽略压缩的路径,举个例子此处是js/icon开首的门路忽略压缩*/ public $compressResIngorePrefix = ['js/icon']; /** 财富根目录*/ public $resRootDir; /** 能源版本文件路线*/ private $resStatePath; public function __construct() { $this->resRootDir = WEBROOT . 'www/'; $this->resStatePath = WEBROOT . 'www/resState.php'; } public function compressRes() { //获取寄存版本的财富文件 $resState = $this->getResState(); $count = 0; //开端遍历要求减弱的财富目录 foreach ($this->compressResDir as $resDir) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) { //获取该财富文件的相对路线$filePath = str_replace('\', '/', $file->getRealPath()); //获取文件相对路线 $object = substr($filePath, strlen($this->resRootDir)); //计算文件的本子号 $state = $this->_getResStateVersion($filePath); //获取文件的多少个参数值 if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) { continue; } //压缩文件的相对路线 $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject); //************此处p判别是最主要部分之一*****************// //决断文件是或不是存在且早就改成过 if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) { continue; } //确定保障/www/min/目录可写 $this->_ensureWritableDir(dirname($minFilePath)); if ($needCompress) { $this->compressResFileAndSave($filePath, $minFilePath); } else { copy($filePath, $minFilePath); } $resState[$object] = $state; $resState[$minObject] = ''; $count++; if ($count == 50) { $this->_saveResState($resState); $count = 0; } } } if($count) $this->_saveResState($resState); } /** * 获取能源文件有关音信 * @param [type] $object 财富文件路径 (www/css/home/index.css) * @param [type] $minObject 压缩财富文件路线 (www/min/css/home/index.ae123a.css) * @param [type] $needCompress 是不是供给压缩 * @param [type] $state 文件版本号 * @param [type] $extension 文件名后缀 * @return [type] [description] */ public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) { //获取财富相对路线 $filePath = $this->resRootDir . $object; //推断能源是还是不是存在 if (!file_exists($file帕特h)) return "财富文件官样文章{$filePath}"; //版本号 $state = $this-> _getResStateVersion($filePath); //文件名后缀 $extension = pathinfo($filePath, PATHINFO_EXTENSION); //是还是不是要缩减 $needCompress = true; //判定能源文件是或不是是以 .min.css只怕.min.js结尾的 //此类结尾日常都是已压缩过,举例jquery.min.js,就不要再压缩了 if (str_end_with($object, '.min.'.$extension, true)) { //压缩后的财富贮存路线,放在 /www/min/ 目录下 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension; $needCompress = false; } else if (in_array($extension, $this->compressResDir)) { //此处是索要减小的文件目录 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; //看看是不是是忽略的路径前缀 foreach ($this->compressResIngorePrefix as $v) { if (str_start_with($object, $v, true)) { $needCompress = false; } } } else { $minObject = 'min/'.$object; $needCompress = false; } return true; } /** * 获取寄存财富版本的文件 * 它是放在三个数组里 * $resState = array( * '文件路线' => '对应的本子号', * '文件路线' => '对应的版本号', * '文件路线' => '对应的本子号', * ); * @return [type] [description] */ public function getResState() { if (file_exists($this->resStatePath)) { require $this->resStatePath; return $resState; } return []; } /** * 总结文件的本子号,这么些是基于总括文件MD5散列值获得版本号 * 只要文件内容退换了,所总括获得的散列值就能分歧样 * 用于决断财富文件是不是有退换过 * @param [type] $filePath [description] * @return [type] [description] */ public function _getResStateVersion($filePath) { return base_convert(crc32(md5_file($filePath)), 10, 36); } /** * 确认保证目录可写 * @param [type] $dir [description] * @return [type] [description] */ private function _ensureWritableDir($dir) { if (!file_exists($dir)) { @mkdir($dir, 0777, true); @chmod($dir, 0777); } else if (!is_writable($dir)) { @chmod($dir, 0777); if (!is_writable($dir)) { show_error('目录'.$dir.'不可写'); } } } /** * 将核减后的财富文件写入到/www/min/下去 * @param [type] $filePath [description] * @param [type] $minFilePath [description] * @return [type] [description] */ private function compressResFileAndSave($filePath, $minFilePath) { if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) { //$CI->exceptions->show_exception("写入文件{$minFilePath}败北"); show_error("写入文件{$minFilePath}退步", -1); } } /** * 压缩能源文件 * @param [type] $filePath [description] * @return [type] [description] */ private function compressResFile($filePath) { $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); if ($extension === 'js') { require_once 'JShrink/Minifier.php'; return JShrinkMinifier::minify(file_get_contents($filePath)); } else if ($extension ==='css') { $content = file_get_contents($filePath); $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content); $content = str_replace(["rn", "r", "n"], '', $content); $content = preg_replace('/([{}),;:>])s+/', '$1', $content); $content = preg_replace('/s+([{}),;:>])/', '$1', $content); $content = str_replace(';}', '}', $content); return $content; } else { //$CI->exceptions->show_exception("不帮助压缩{extension}文件[$filePath]"); show_error("不协助压缩{extension}文件[$filePath]", -1); } } private function _saveResState($resState) { ksort($resState); $content = "<?phpnn$resState = array(n"; foreach ($resState as $k => $v) { $content .= "t '$k' => '$v',n"; } $content .= ");nn"; file_put_contents($this->resStatePath, $content); } } 点击张开

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* 资源压缩类
*/
class ResMinifier {
    /** 需要压缩的资源目录*/
    public $compressResDir = ['css', 'js'];
    /** 忽略压缩的路径,例如此处是js/icon开头的路径忽略压缩*/
    public $compressResIngorePrefix = ['js/icon'];
    /** 资源根目录*/
    public $resRootDir;
    /** 资源版本文件路径*/
    private $resStatePath;
 
    public function __construct() {
        $this->resRootDir = WEBROOT . 'www/';
        $this->resStatePath = WEBROOT . 'www/resState.php';
    }
 
    public function compressRes() {
        //获取存放版本的资源文件
        $resState = $this->getResState();
        $count = 0;
 
        //开始遍历需要压缩的资源目录
        foreach ($this->compressResDir as $resDir) {
            foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->resRootDir . $resDir , FilesystemIterator::SKIP_DOTS)) as $file) {
                //获取该资源文件的绝对路径
                $filePath = str_replace('\', '/', $file->getRealPath());
 
                //获取文件相对路径
                $object = substr($filePath, strlen($this->resRootDir));
 
                //计算文件的版本号
                $state = $this->_getResStateVersion($filePath);
 
                //获取文件的几个参数值
                if (true !== $this->getObjectInfo($object, $minObject, $needCompress, $state, $extension)) {
                    continue;
                }
 
                //压缩文件的绝对路径
                $minFilePath = str_replace('\', '/', $this->resRootDir. $minObject);
 
                //************此处p判断是最重要部分之一*****************//
                //判断文件是否存在且已经改动过
                if (isset($resState[$object]) && $resState[$object] == $state && isset($resState[$minObject]) && file_exists($minFilePath)) {
                    continue;
                }
 
                //确保/www/min/目录可写
                $this->_ensureWritableDir(dirname($minFilePath));
 
                if ($needCompress) {
                    $this->compressResFileAndSave($filePath, $minFilePath);
                } else {
                    copy($filePath, $minFilePath);
                }
 
                $resState[$object] = $state;
                $resState[$minObject] = '';
                $count++;
 
                if ($count == 50) {
                    $this->_saveResState($resState);
                    $count = 0;
                }
 
            }
        }
        if($count) $this->_saveResState($resState);
    }
 
    /**
     * 获取资源文件相关信息
     * @param  [type] $object       资源文件路径 (www/css/home/index.css)
     * @param  [type] $minObject    压缩资源文件路径 (www/min/css/home/index.ae123a.css)
     * @param  [type] $needCompress 是否需要压缩
     * @param  [type] $state        文件版本号
     * @param  [type] $extension    文件名后缀
     * @return [type]               [description]
     */
    public function getObjectInfo($object, &$minObject, &$needCompress, &$state, &$extension) {
        //获取资源绝对路径
        $filePath = $this->resRootDir . $object;
        //判断资源是否存在
        if (!file_exists($filePath)) return "资源文件不存在{$filePath}";
        //版本号
        $state = $this-> _getResStateVersion($filePath);
        //文件名后缀
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        //是否要压缩
        $needCompress = true;
 
        //判断资源文件是否是以 .min.css或者.min.js结尾的
        //此类结尾一般都是已压缩过,例如jquery.min.js,就不必再压缩了
        if (str_end_with($object, '.min.'.$extension, true)) {
            //压缩后的资源存放路径,放在 /www/min/ 目录下
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state .'.'. $extension;
            $needCompress = false;
        } else if (in_array($extension, $this->compressResDir)) {
            //此处是需要压缩的文件目录
            $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
            //看看是否是忽略的路径前缀
            foreach ($this->compressResIngorePrefix as $v) {
                if (str_start_with($object, $v, true)) {
                    $needCompress = false;
                }
            }
        } else {
            $minObject = 'min/'.$object;
            $needCompress = false;
        }
        return true;
    }
 
    /**
     * 获取存放资源版本的文件
     * 它是放在一个数组里
     * $resState = array(
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *         '文件路径' => '对应的版本号',
     *     );
     * @return [type] [description]
     */
    public function getResState() {
        if (file_exists($this->resStatePath)) {
            require $this->resStatePath;
            return $resState;
        }
        return [];
    }
 
    /**
     * 计算文件的版本号,这个是根据计算文件MD5散列值得到版本号
     * 只要文件内容改变了,所计算得到的散列值就会不一样
     * 用于判断资源文件是否有改动过
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    public function _getResStateVersion($filePath) {
        return base_convert(crc32(md5_file($filePath)), 10, 36);
    }
 
    /**
     * 确保目录可写
     * @param  [type] $dir [description]
     * @return [type]      [description]
     */
    private function _ensureWritableDir($dir) {
        if (!file_exists($dir)) {
            @mkdir($dir, 0777, true);
            @chmod($dir, 0777);
        } else if (!is_writable($dir)) {
            @chmod($dir, 0777);
            if (!is_writable($dir)) {
                show_error('目录'.$dir.'不可写');
            }
        }
    }
 
    /**
     * 将压缩后的资源文件写入到/www/min/下去
     * @param  [type] $filePath    [description]
     * @param  [type] $minFilePath [description]
     * @return [type]              [description]
     */
    private function compressResFileAndSave($filePath, $minFilePath) {
        if (!file_put_contents($minFilePath, $this->compressResFile($filePath))) {
 
            //$CI->exceptions->show_exception("写入文件{$minFilePath}失败");
            show_error("写入文件{$minFilePath}失败", -1);
        }
    }
 
    /**
     * 压缩资源文件
     * @param  [type] $filePath [description]
     * @return [type]           [description]
     */
    private function compressResFile($filePath) {
        $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        if ($extension === 'js') {
            require_once 'JShrink/Minifier.php';
            return JShrinkMinifier::minify(file_get_contents($filePath));
        } else if ($extension ==='css') {
            $content = file_get_contents($filePath);
            $content = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', '', $content);
            $content = str_replace(["rn", "r", "n"], '', $content);
            $content = preg_replace('/([{}),;:>])s+/', '$1', $content);
            $content = preg_replace('/s+([{}),;:>])/', '$1', $content);
            $content = str_replace(';}', '}', $content);
            return $content;
        } else {
            //$CI->exceptions->show_exception("不支持压缩{extension}文件[$filePath]");
            show_error("不支持压缩{extension}文件[$filePath]", -1);
 
        }
    }
 
    private function _saveResState($resState) {
        ksort($resState);
        $content = "<?phpnn$resState = array(n";
        foreach ($resState as $k => $v) {
            $content .= "t '$k' => '$v',n";
        }
        $content .= ");nn";
        file_put_contents($this->resStatePath, $content);
    }
 
}
 
点击打开

Common.php

PHP

<?php /** * 输出 HttpHead 中的财富总是。 css/js 自动判定真实路线 * @param string 文件路线 * @return string */ function res_link($file) { $file = res_path($file, $extension); if ($extension === 'css') { return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>'; } else if ($extension === 'js') { return '<script type="text/javascript" src="'.$file.'"></script>'; } else { return false; } } /** * 智能路由财富实际路线 * @param string 路径 * @param string 扩展名 * @return string 真实路线 */ function res_path($file, &$extension) { //检查是或不是留存询问字符串 list($file, $query) = explode('?', $file . '?'); //获得扩大名 $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); // $file = str_replace('\', '/', $file); //取稳妥前调整器名 global $class; if ($class == null) exit('can not get class name'); $className = strtolower($class); //此处的平整是那样: //比如,假如不加 / ,Home调节器对应的格式是: index.css,那么 此处的路线会产生css/home/index.css //假使有 / ,调控器的格式能够是 /main.css,那么这里的路线会变成 css/main.css(公用的css类) if ('/' !== $file[0]) { //index.css => css/home/index.css $object = $extension .'/'. $className .'/' . $file; } else { // /css/main.css 大概 /main.css => css/main.css $object = substr($file, 1); //若object是 main.css ,则自动抬高 扩张名目录 => css/main.css if (0 !== strncasecmp($extension, $object, strlen($extension))) { $object = $extension . '/' . $object; } } //能源真实路线 $filepath = WEBROOT.'www/'.$object; //替换压缩版本,那有的逻辑与公事收缩逻辑对应 if (in_array($extension, array('css', 'js'))) { if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) { require_once 应用软件PATH.'libraries/ResMinifier.php'; $resminifier = new ResMinifier(); //获取寄放能源版本的文件的数组变量 $resState = $resminifier->getResState(); //计算取妥贴前文件版本号 $state = $resminifier->_getResStateVersion($filepath); //决断该版本号是不是留存 if (isset($resState[$object])) { //推断是还是不是是.min.css或.min.js结尾 if (str_end_with($object, '.min.'.$extension)) { //将版本号拼接上去,然后拿走min的文本路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension; } else { //将版本号拼接上去,然后拿走min的文件路线 $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension; } //剖断min的门径是还是不是存在在$resState里面 if (isset($resState[$minObject])) { $object = $minObject; $query = ''; } } } $file = RES_BASE_URL . $object; } return ($query == null) ? $file : ($file .'?'. $query); } /** * 判定 subject 是还是不是以 search最初, 参数内定是还是不是忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_start_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len1 < $len2) return false; if ($ignore_case) { return 0 === strncmp($subject, $search, $len2); } else { return 0 === strncasecmp($subject, $search, $len2); } } /** * 推断 subject 是不是以 search结尾, 参数内定是还是不是忽略大小写 * @param [type] $subject [description] * @param [type] $search [description] * @param boolean $ignore_case [description] * @return [type] [description] */ function str_end_with($subject, $search, $ignore_case = false) { $len2 = strlen($search); if (0 === $len2) return true; $len1 = strlen($subject); if ($len2 > $len1) return false; if ($ignore_case) { return 0 === strcmp(substr($subject, $len1 - $len2), $search); } else { return 0 === strcasecmp(substr($subject, $len1 - $len2), $search); } } 点击打开

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
    /**
     * 输出 HttpHead 中的资源连接。 css/js 自动判断真实路径
     * @param  string  文件路径
     * @return string      
     */
    function res_link($file) {
        $file = res_path($file, $extension);
 
        if ($extension === 'css') {
           return '<link rel="stylesheet" type="text/css" href="' . $file . '"/>';
        } else if ($extension === 'js') {
            return '<script type="text/javascript" src="'.$file.'"></script>';
        } else {
            return false;
        }
    }
 
    /**
     * 智能路由资源真实路径
     * @param  string      路径
     * @param  string      扩展名
     * @return string       真实路径
     */
    function res_path($file, &$extension) {
        //检查是否存在查询字符串
        list($file, $query) = explode('?', $file . '?');
        //取得扩展名
        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        //
        $file = str_replace('\', '/', $file);
        //取得当前控制器名
        global $class;
        if ($class == null) exit('can not get class name');
        $className = strtolower($class);
 
        //此处的规则是这样:
        //例如,如果不加 / ,Home控制器对应的格式是: index.css,那么 此处的路径会变成css/home/index.css
        //假如有 / ,控制器的格式可以是 /main.css,那么此处的路径会变成 css/main.css(公用的css类)
        if ('/' !== $file[0]) {
            //index.css => css/home/index.css
            $object = $extension .'/'. $className .'/' . $file;
        } else {
            // /css/main.css 或者 /main.css => css/main.css
            $object = substr($file, 1);
 
            //若object是 main.css ,则自动加上 扩展名目录 => css/main.css
            if (0 !== strncasecmp($extension, $object, strlen($extension))) {
                $object = $extension . '/' . $object;
            }
        }
        //资源真实路径
        $filepath = WEBROOT.'www/'.$object;
 
        //替换压缩版本,这部分逻辑与文件压缩逻辑对应
        if (in_array($extension, array('css', 'js'))) {
            if(!str_start_with($object, 'min/') && file_exists(APPPATH.'libraries/ResMinifier.php')) {
                require_once APPPATH.'libraries/ResMinifier.php';
                $resminifier = new ResMinifier();
                //获取存放资源版本的文件的数组变量
                $resState = $resminifier->getResState();
                //计算得到当前文件版本号
                $state = $resminifier->_getResStateVersion($filepath);
                //判断该版本号是否存在
                if (isset($resState[$object])) {
                    //判断是否是.min.css或.min.js结尾
                    if (str_end_with($object, '.min.'.$extension)) {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension) - 4) . $state . '.' . $extension;
                    } else {
                        //将版本号拼接上去,然后得到min的文件路径
                        $minObject = 'min/'.substr($object, 0, strlen($object) - strlen($extension)) . $state . '.' . $extension;
                    }
                    //判断min的路径是否存在在$resState里面
                     if (isset($resState[$minObject])) {
                        $object = $minObject;
                        $query = '';
                     }
                }
 
            }
 
            $file = RES_BASE_URL . $object;
        }
 
        return ($query == null) ? $file : ($file .'?'. $query);
 
    }
 
    /**
     * 判断 subject 是否以 search开头, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_start_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len1 < $len2) return false;
        if ($ignore_case) {
            return 0 === strncmp($subject, $search, $len2);
        } else {
            return 0 === strncasecmp($subject, $search, $len2);
        }
    }
 
    /**
     * 判断 subject 是否以 search结尾, 参数指定是否忽略大小写
     * @param  [type]  $subject     [description]
     * @param  [type]  $search      [description]
     * @param  boolean $ignore_case [description]
     * @return [type]               [description]
     */
    function str_end_with($subject, $search, $ignore_case = false) {
        $len2 = strlen($search);
        if (0 === $len2) return true;
        $len1 = strlen($subject);
        if ($len2 > $len1) return false;
        if ($ignore_case) {
            return 0 === strcmp(substr($subject, $len1 - $len2), $search);
        } else {
            return 0 === strcasecmp(substr($subject, $len1 - $len2), $search);
        }
    }
 
点击打开

$resState.php(里面包车型大巴代码是自动生成的)

XHTML

<?php $resState = array( 'css/home/index.css' => 'gwy933', 'js/echarts-all.min.js' => 'wqrf1c', 'js/home/index.js' => 's2z6f5', 'js/icon.js' => 'pgcyih', 'js/icon_home.js' => 'zhl9iu', 'js/ion.rangeSlider.min.js' => 'akq381', 'js/jquery-ui-autocomplete.js' => '8nzacv', 'js/jquery-ui.min.js' => 'i6tw8z', 'js/jquery.all.min.js' => 'd2w76v', 'js/jquery.city.js' => 'toxdrf', 'js/jquery.easydropdown.min.js' => '2ni3i0', 'js/jquery.matrix.js' => '3vrqkk', 'js/jquery.mobile.all.min.js' => 'ernu7r', 'js/jquery.qrcode.min.js' => 'yuhnsj', 'js/jquery.tinyscrollbar.min.js' => 'oakk3c', 'js/mobiscroll.custom.min.js' => 'kn8h2e', 'js/store.min.js' => 'n50jwr', 'js/swiper.animate1.0.2.min.js' => 'mm27zc', 'js/swiper.min.js' => 'jicwhh', 'min/css/home/index.6a4e83eb.css' => '', 'min/css/home/index.gwy933.css' => '', 'min/css/home/index.puzbnf.css' => '', 'min/css/home/index.thv8x7.css' => '', 'min/js/echarts-all.76025ee0.js' => '', 'min/js/echarts-all.wqrf1c.js' => '', 'min/js/home/index.65363d41.js' => '', 'min/js/home/index.s2z6f5.js' => '', 'min/js/icon.5bbd4db9.js' => '', 'min/js/icon.pgcyih.js' => '', 'min/js/icon_home.7fe74076.js' => '', 'min/js/icon_home.zhl9iu.js' => '', 'min/js/ion.rangeSlider.261d8ed1.js' => '', 'min/js/ion.rangeSlider.akq381.js' => '', 'min/js/jquery-ui-autocomplete.1f3bb62f.js' => '', 'min/js/jquery-ui-autocomplete.8nzacv.js' => '', 'min/js/jquery-ui.418e9683.js' => '', 'min/js/jquery-ui.i6tw8z.js' => '', 'min/js/jquery.all.2f248267.js' => '', 'min/js/jquery.all.d2w76v.js' => '', 'min/js/jquery.city.6b036feb.js' => '', 'min/js/jquery.city.toxdrf.js' => '', 'min/js/jquery.easydropdown.2ni3i0.js' => '', 'min/js/jquery.easydropdown.98fa138.js' => '', 'min/js/jquery.matrix.3vrqkk.js' => '', 'min/js/jquery.matrix.dfe2a44.js' => '', 'min/js/jquery.mobile.all.3539ebb7.js' => '', 'min/js/jquery.mobile.all.ernu7r.js' => '', 'min/js/jquery.qrcode.7d9738b3.js' => '', 'min/js/jquery.qrcode.yuhnsj.js' => '', 'min/js/jquery.tinyscrollbar.578e4cb8.js' => '', 'min/js/jquery.tinyscrollbar.oakk3c.js' => '', 'min/js/mobiscroll.custom.4a684f66.js' => '', 'min/js/mobiscroll.custom.kn8h2e.js' => '', 'min/js/store.536545cb.js' => '', 'min/js/store.n50jwr.js' => '', 'min/js/swiper.4650ad75.js' => '', 'min/js/swiper.animate1.0.2.517f82e8.js' => '', 'min/js/swiper.animate1.0.2.mm27zc.js' => '', 'min/js/swiper.jicwhh.js' => '', ); 点击展开

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
 
$resState = array(
     'css/home/index.css' => 'gwy933',
     'js/echarts-all.min.js' => 'wqrf1c',
     'js/home/index.js' => 's2z6f5',
     'js/icon.js' => 'pgcyih',
     'js/icon_home.js' => 'zhl9iu',
     'js/ion.rangeSlider.min.js' => 'akq381',
     'js/jquery-ui-autocomplete.js' => '8nzacv',
     'js/jquery-ui.min.js' => 'i6tw8z',
     'js/jquery.all.min.js' => 'd2w76v',
     'js/jquery.city.js' => 'toxdrf',
     'js/jquery.easydropdown.min.js' => '2ni3i0',
     'js/jquery.matrix.js' => '3vrqkk',
     'js/jquery.mobile.all.min.js' => 'ernu7r',
     'js/jquery.qrcode.min.js' => 'yuhnsj',
     'js/jquery.tinyscrollbar.min.js' => 'oakk3c',
     'js/mobiscroll.custom.min.js' => 'kn8h2e',
     'js/store.min.js' => 'n50jwr',
     'js/swiper.animate1.0.2.min.js' => 'mm27zc',
     'js/swiper.min.js' => 'jicwhh',
     'min/css/home/index.6a4e83eb.css' => '',
     'min/css/home/index.gwy933.css' => '',
     'min/css/home/index.puzbnf.css' => '',
     'min/css/home/index.thv8x7.css' => '',
     'min/js/echarts-all.76025ee0.js' => '',
     'min/js/echarts-all.wqrf1c.js' => '',
     'min/js/home/index.65363d41.js' => '',
     'min/js/home/index.s2z6f5.js' => '',
     'min/js/icon.5bbd4db9.js' => '',
     'min/js/icon.pgcyih.js' => '',
     'min/js/icon_home.7fe74076.js' => '',
     'min/js/icon_home.zhl9iu.js' => '',
     'min/js/ion.rangeSlider.261d8ed1.js' => '',
     'min/js/ion.rangeSlider.akq381.js' => '',
     'min/js/jquery-ui-autocomplete.1f3bb62f.js' => '',
     'min/js/jquery-ui-autocomplete.8nzacv.js' => '',
     'min/js/jquery-ui.418e9683.js' => '',
     'min/js/jquery-ui.i6tw8z.js' => '',
     'min/js/jquery.all.2f248267.js' => '',
     'min/js/jquery.all.d2w76v.js' => '',
     'min/js/jquery.city.6b036feb.js' => '',
     'min/js/jquery.city.toxdrf.js' => '',
     'min/js/jquery.easydropdown.2ni3i0.js' => '',
     'min/js/jquery.easydropdown.98fa138.js' => '',
     'min/js/jquery.matrix.3vrqkk.js' => '',
     'min/js/jquery.matrix.dfe2a44.js' => '',
     'min/js/jquery.mobile.all.3539ebb7.js' => '',
     'min/js/jquery.mobile.all.ernu7r.js' => '',
     'min/js/jquery.qrcode.7d9738b3.js' => '',
     'min/js/jquery.qrcode.yuhnsj.js' => '',
     'min/js/jquery.tinyscrollbar.578e4cb8.js' => '',
     'min/js/jquery.tinyscrollbar.oakk3c.js' => '',
     'min/js/mobiscroll.custom.4a684f66.js' => '',
     'min/js/mobiscroll.custom.kn8h2e.js' => '',
     'min/js/store.536545cb.js' => '',
     'min/js/store.n50jwr.js' => '',
     'min/js/swiper.4650ad75.js' => '',
     'min/js/swiper.animate1.0.2.517f82e8.js' => '',
     'min/js/swiper.animate1.0.2.mm27zc.js' => '',
     'min/js/swiper.jicwhh.js' => '',
);
 
点击打开

 

其余附上JShrink那几个PHP类的链接给大家下载 

如果大家要么感到非常不足OK的话,小编直接将这一个试验项目打包供大家下载下来学习和掌握:

四、结语

末尾本身来享受我们线上项目标有血有肉落到实处方案:

我们的类型分线上情况、开拓条件和测验蒙受,在付出和测量试验境遇中,大家每二回访谈都会调用压缩文件的接口,然后再对转移的资源文件的轻重是要做推断的,要是缩减后文件过小,将要求将该能源文件的代码合併到其余能源文件里去,以此收缩不需求的HTTP央求(因为文件太小,能源的下载时间远小于HTTP央浼响应所费用的时间);另二个是图形的管理,全体图片都要经过压缩技艺透过(举例在:  那几个网站去收缩图片),在PC端,如若是小Logo的话,使用图片合併的不二诀要张开优化,详细的情况可参看本人的那篇博文:http://www.cnblogs.com/it-cen/p/4618954.html    而在wap端的图片管理利用的是base64编码方式来拍卖图片,详细情形能够参谋本身的那篇博文:  ,当页面输出时,会使用redis来缓存页面(为何用内存来缓存并不是行使页面缓存,这些今后再享受给咱们)。假若是线上情状,每发三次版本,才会调用一下财富文件减弱那么些接口,并且线上的静态财富(css、js、图片)是存放在Ali云的OSS里的,与大家的应用服务器是分离的。那是大家线上系列的一有的优消除决方案,当然了,还应该有越来越多优化技能,笔者会在事后各类总计和享用出来,方便大家一齐学习和调换。

本次博文就享受到此,感激观看此博文的情大家。

1 赞 1 收藏 评论

云顶娱乐v1.8 10

门路移动

云顶娱乐v1.8 11

那也是曲线移动,不过想像上面那样,这几个很难拆分成几个样子的活动叠合。那样的活动路径能够尝试以下多少个点子:

  • SVG Animation

如此那般的路线能够相比较好的用 SVG path 来说述,然后采纳 SVG Animation 做跟随动画,并得以高达预期的轨道效果。

主要代码(在线示例):

JavaScript

<svg width="420px" height="260px" viewBox="0 0 420 260" version="1.1" xmlns="" xmlns:xlink="; <g stroke="#979797" stroke-width="1" fill="none"> <path id="motionPath" d="M370.378234,219.713623 C355.497359,218.517659 ..." ></path> </g> <g id="cray" transform="translate(0, -24)" stroke="#979797"> <image id="cray-img" xlink:href="" x="0" y="0" width="100px"/> </g> <animateMotion xlink:href="#cray" dur="5s" begin="0s" fill="freeze" repeatCount="indefinite" rotate="auto-reverse" > <mpath xlink:href="#motionPath" /> </animateMotion> </svg>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<svg width="420px" height="260px" viewBox="0 0 420 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g stroke="#979797" stroke-width="1" fill="none">
    <path id="motionPath" d="M370.378234,219.713623 C355.497359,218.517659 ..." ></path>
  </g>
  <g id="cray" transform="translate(0, -24)" stroke="#979797">
   <image id="cray-img" xlink:href="http://7xt5iu.com1.z0.glb.clouddn.com/img/cray.png" x="0" y="0" width="100px"/>
  </g>
  <animateMotion
    xlink:href="#cray"
    dur="5s"
    begin="0s"
    fill="freeze"
    repeatCount="indefinite"
    rotate="auto-reverse"
  >
    <mpath xlink:href="#motionPath" />
  </animateMotion>
</svg>

效果:

云顶娱乐v1.8 12

  • JavaScript

运用 JavaScript 能够一向操作成分进行移动,理论上能够完毕别的动画,只是达成部分复杂的卡通片花费比较高,幸好有各类已经支付好了的工具库能够供大家应用。譬喻,使用 Greensock 的 Tween马克斯 和 MorphSVGPlugin(收取金钱),通过 MorphSVGPlugin 提供的 pathDataToBezier 方法将 SVG path 转成曲线数组,然后给 TweenMax使用:

JavaScript

var hill = document.getElementById('hill') var path = MorphSVGPlugin.pathDataToBezier("#motionPath"); TweenMax.to(hill, 5, { bezier:{ values:path, type:"cubic", autoRotate: 180 }, ease:Linear.easeNone, repeat: -1 })

1
2
3
4
5
6
7
8
9
10
11
var hill = document.getElementById('hill')
var path = MorphSVGPlugin.pathDataToBezier("#motionPath");
TweenMax.to(hill, 5, {
  bezier:{
    values:path,
    type:"cubic",
    autoRotate: 180
  },
  ease:Linear.easeNone,
  repeat: -1
})

在线示例

  • CSS

兑现动画,其实正是在对应的岁月点做相应的“变化”。再回头看直线移动的达成格局,其实只要能交到丰盛多点的岗位和该点的时刻与持续时间的比率,那其实曲线也能够一贯用 CSS 来实现。

广大时候设计员运用 AE 来安排动画,当我们得到设计稿后,能够给动画增添关键帧,然后借助一些工具把关键帧的音讯导出来,这里介绍三个 keyframes-cli,能够导出那样结构的数量

云顶娱乐v1.8 13

附属性名字能够看清出来 X_POSITIONY_POSITIONxy 的岗位消息,而 key_values 里的 data 正是大家要求的点位置该点的时间与持续时间的比值 能够依据 start_frame 得出,
写个剧本把那么些数量管理下,可获取近似上面包车型大巴 CSS 代码

云顶娱乐v1.8 14

设置的关键帧越来越多,动画会越流畅,但 CSS 也会扩展。

小心:不是 AE 关键帧里全数的音信都足以导出来,还跟 AE 里使用的交接性质有关,这里有介绍。

最后,总计一下,移动动画就是用一种适于的诀要把时间和任务的浮动关系显得出来。除了上面方法,料定还或然有为数不菲此外的措施和帮扶工具,迎接留言沟通研讨。

多谢您的读书,本文由 坑坑洼洼实验室 版权全体。倘使转发,请评释出处:凹凸实验室()

1 赞 1 收藏 评论

云顶娱乐v1.8 15

爆栈三部曲

  •  Web前端开拓大系概览(前端开垦工夫栈) ,包蕴大概1七十六个技巧点
  •  数据库开荒大系技巧栈 (300多技术点)
  •  .NET本事大系大概浏览(迄今截止最全的.NET技能栈)

至于我:十年踪迹

云顶娱乐v1.8 16

月影,奇舞蹈艺术团中校,热爱前端开辟,JavaScript 程序员一枚,能写代码也能打杂卖萌说段子。 个人主页 · 小编的稿子 · 14 ·     

云顶娱乐v1.8 17

做可相信交互动画的 5 种格局

2015/04/19 · HTML5 · 互动动画

本文由 伯乐在线 - Abel 翻译,黄利民 校稿。未经许可,防止转载!
德文出处:24ways.org。接待加入翻译组。

从本人在这么些网址上起来写《Flashless Animation》这篇小提及未来已经五年了。从那时起,交互动画已经从像圆润的APP一样的客商分界面到交互式杂志在网站上流行。对网页交互动书法家、交互开荒人士、客户体验师、顾客界面设计人士和广大另外与互动动画有关的人手的话,那是二个多么令人欢腾的日子。

而是匆忙的安排性互动动画,如同表示大家少之甚少商量是不是必供给动用交互动画,而是越来越多地研商我们用交互动画能干什么?我们费用比很多日子为怎么以 60fps 使具备东西得以动画而发急,并不是设计有个别主意让初级客户防止障碍。

自己热爱网页动画,并以它为生。我驾驭动画能被滥用,何况大家都拿flash-trubation来娱乐。不过在网页设计时期积存的训诫,大家忘记它是如此的快啊。视差滚动作效果应只怕是对那原因发生的大致介绍。在Flash和网页动画API这一令人深思的不平时,大家的确学到了无数。

由此这里的五点提议,我们得以用来把处于交互动画滥用边缘的使用者拉回去高水准上。有这几点建议在心尖,我们得以让二零一六的网页动画年真正地属于它和睦。

有指标性的应用动画片

非常不满,大批量的Web开荒社区感觉动画片是装饰性的。UI设计师和相互开垦人士当然知道的更到位。可是当自身给一个专门的学问室培养训练相互动画的时候,笔者了然小编的上学的小孩子是在和一部分官员做勤奋的埋头单干,这个集团主认为有动画会特别卓越并须要尽量的在类型的最终附上动画,而自身的学员则感觉不然。

这种价值观差距很难动摇,可是当大家紧凑做动画的时候这种守旧差距恐怕就能够磨灭。附加动画带来的加害比益处要多,这一点少之甚少被客户思虑。举例,客商只怕会埋怨动画太快可能太慢,或许他们不通晓动画在体现怎样。

当本身今年参加 Chrome 开拓高峰会议的时候,作者有和 Roma Shah 交换的时机,她是 Polymer Material Design 背后的 UX 首席试行官。笔者问她有哪些建议给在统一筹算当中使用动画片和转场的设计员。她轻巧的答复:有目标地使用动画片。若是您不能够慢下来想想什么做交互动画并表示顾客做贰个足够知晓和精心制作的主宰,那么您Infiniti不用做这些尝试。动画须求开销精力来制作,而八个弱智的卡通比一直不更不好。

随处《生活的错觉》这把书中提到的卡通片 12 条法规

作者们连年试着在刺激大家感兴趣却毫不相干的专业里面找到相关性。近日更是多的人把《生活的错觉》放在挨着《精通漫画》那本书的同一个书架上。那几个书给大家带来非常多起点别的领域的灵光的理念。然则,我们不该在网址上犯类似与漫画书与动画片的荒谬。即便它们得以扶持大家用新的角度了解大家的劳作,但是那个概念会或多或少发生上述混淆两个概念的功力。

本身直接在严慎地思索《生活的错觉》,迪士尼动画专门的职业室的经验丰硕的程序员们在书中提出了动画片十二条准则。那么些准绳对做使人陶醉的、逼真的卡通片非常有用,如像弹起的球、蹦跳的松鼠、靓丽的情理极光一样的页面转场动画。不过曾几何时依然怎样把一个动画作为七个重型交互体验的一有的,那么些轨道未有对那么些标题做方向性的辅导。比如二个下拉操作供给多长时间技巧展开达成,只怕一组可操作对象是应该根据顺序,依然依据总体做成动画。

那十二条规则仅仅是三个开端地方,除却大家还有别的众多东西要上学。笔者早就写过最少六条使用到web和app的宏图互动动画效果。当我们想想做交互动画时,大家不光思考做什么动画、动画的物管理学,还要考虑怎么要做动画,怎么样做动画。假如动画是多余的要么令人费解的,再严刻的大要设计也是不得要领的。

有用、有供给,然后是可观

做可相信交互动画的,静态财富文件自动削减并替换到压缩版本。有一句行内话:除非一个卡通既是必得又是行得通的,要不然不要做它;假设它既是必需的,又是实用的,那就坚决去把它做能够。当聊到动画和网页,最近少之甚少有小说写什么的卡通片是立竿见影也许要求的。大家大多数都以同情于做可以、令人高兴、令人风趣的卡通。就算动画的外观突出很要紧,可是外观是小于顾客的完全部验的。

先是次小编在掌机看见金红口袋鬼怪的开机动画时,小编被迷住了。到了第四次的时候,当Freak的嬉戏图标出现在显示屏上时,笔者被最初按键搞的嫌恶了。当咱们在做计划的时候,令大家高兴和有含义的东西对顾客来讲却是未必的。像鲜红口袋魔鬼令人和颜悦色的开机动画同样,纯粹令人雅观的卡通片尽管是被客户欣然的接受,不过太频仍的双重却最终无意义的卡通,客户就能稳步对该动画发生恨恶之情。

借使二个动画片不能够在某种格局上帮衬顾客,如让顾客了然他们在网址的什么样岗位依旧一个页面上的七个元素是如何互相相关的,那么它是在成本电瓶并在不停地发生仅仅令客商快乐的法力。能源相当少获得合理合法的采纳。

卡通不是独自为了令客商开心,首先,大家必需能让动画给客商清晰的表明五个乐趣。以从 Finethought.com 网址上这么些菜单Logo为例。当我们点击这几个菜单Logo时,它向我们表明了八个野趣。

1.那些菜单开关用动画给客商以报告,表面那么些Logo已经被点击了。

2.以此菜单开关注脚通过点击关闭Logo,页面包车型地铁内容将会发出转移。

假如大家有几个好的说辞来做交互动画,那么就能够有理由来投其所好顾客。

以四倍速度让动画越来越快

有多个价值观木偶剧的大概浏览法符合于网页动画:不管你的动画应该任何时间任何地方多长时间,把动画的持续时间减半,然后再减半。当大家规划动画多少个钟头之后,我们对时间的认为会变长。对大家来讲速度迅速的动画片,对超过51%顾客来说已经到了相当的小概忍受的慢。事实上,近来源于于顾客对网址动画接口的绝大数讨论就如是:“它太慢了。”二个好的卡通是不唐突的相同的时间速度是极其快的。

例如让您的卡通片持续时间处于一个最好值,那么请把动画持续时间收缩到原本的四分一。

安装二个关门开关

随意二个卡通是何等的富有眼光和必要性,总有局地人对动画片不高烧。对这一个人来讲,我们必得扩充一种办法来让他们关闭网页上的动画。

幸而的是,网页设计员已经在思考给予顾客一些和好做决定来退换网页体验的权能。以上边包车型地铁动画片为例,那几个《小鱼商号》的动画电影网址允许顾客关闭视差效果。即使它不可能移除全体卡通,然则这几个网址确实收缩了动画片的视觉给客商带来的眩晕的痛感。

在我们网页设计的工具库中,动画是三个强大的工具。可是我们亟须当心:假使大家滥用动画,动画大概会带来不佳的作用;若是我们低估动画,它就不可能一心表明它的效果与利益。不过假若大家正好的运用动画片,当既有须要又有效的选拔动画片,赋予顾客关闭的动画片的权限,那么动画会产生三个协理大家建造一些用起来大约、带给大家快乐的事物。

让我们把2014的网页动画年带给客商吧!

赞 收藏 评论

本文由云顶娱乐v1.8发布于澳门云顶娱乐app官网,转载请注明出处:做可相信交互动画的,静态财富文件自动削减并

关键词: