精华内容
下载资源
问答
  • 在网站开发过程中,对于页面的加载效率一般都想尽办法快。那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的方法... 一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片
     在网站开发过程中,对于页面的加载效率一般都想尽办法求快。那么,怎么让才能更快呢?减少页面请求
    是一个优化页面加载速度很好的方法。上一篇博文我们讲解了 “利用将小图标合成一张背景图来减少HTTP请求”,那么,这一篇博文将讲解  “ 
    将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片”。
    

      一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片的方法减少HTTP请求数?

      为什么我会讲解 “将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片” 这一种方式来减少HTTP请求,进而优化页面呢?这里呢,是涉及到移动端的图标使用。上一篇博文所讲的方法能否使用于手机端的网页呢?

       但是,它会出现一个问题:背景图+css显示图标时,图标本身无法缩放,比如背景图中64px*64px的图标,显示到界面时必须设置icon的大小也是64*64。在PC网页中这通常不会有什么问题,但在移动端设备上就完全行不通。同样是4英寸的手机屏幕,其分辨率有可能是320*400,也可能是640*800,甚至也可能是1920*1080。这样64px*64px的图标在不同的设备上看起来的大小就会差别非常明显。

      幸运的是,手机上的浏览器基本对此做了优化,会把设备模拟成更低的分辨率。比如在1136*640的IPHONE 5中获取$(window).width(),取出来的是320而不是640,这样一个宽度为160px的图片占用的是屏幕宽度的一半,而不是1/4。手机设备这样处理是为了解决兼容性问题。除了网页,包括手机上app的界面,在retina屏幕上和非retina屏幕上的大小是完全一样的,都是因为对分辨率做了处理。

      但是,移动设备这样的处理方式并不能完全解决问题,因为机器的假设性猜测在很多时候是不合适的,尤其是在android设备中。为了更好地控制元素显示的大小,解决的办法就是用pt代替ps,px是对应屏幕的分辨率,而pt是针对人眼睛实际感觉的大小,无论在何种分辨率的设备上,72pt固定是1英寸。

      HTML的img标签元素的src属性不只是可以指定url,也可以指定图片的二进制数据流。然后通过img元素的自动缩放功能,指定img的大小,就可以实现在不同分辨率的设备上显示一致的图标大小。

      二、使用Base64编码减少页面请求数

      当我们的一个页面中要传入很多图片时,特别是一些小图标,十几K、几K,甚至是字节级别大小的小图标,这些小图标都会增加HTTP请求,假如多了,就会给服务器带来很大的压力。比如要下载一些一两K大的小图标,其实请求时带上的额外信息有可能比图标的大小还要大。所以,在请求越多时,在网络传输的数据自然就越多了,传输的数据自然也就变慢了。而这里,我们采用Base64的编码方式将图片直接嵌入到网页中,而不是从外部载入,这样就减少了HTTP请求。当然了,它有一个小缺点,就是使当前页面的大小变大了(对于优化来说,其实这个可以忽略,影响不大)。看一下下图,小图标大小为2.4k,等待响应时间是14ms,而接受数据,也就是下载时间约为0ms;可想而知,在有大量小图标下载的时候,这样的方式去优化能大大提高网站的性能(在jquery mobile和天猫的手机站上面都有用到此技术)。

      

      三、开发思路

       将小图标放在以icon_开头的文件夹里(以区分不用生成base64的图片的文件夹)—>用程序去遍历文件夹图片 —>将每张图片的base64编码放在一个js对象里—>在HTML页面的img标签里 使用属性 icon-data = '图标名(不带后缀)'来显示图片 —> JS文件写一个函数对icon-data属性进行转换,转换成src属性,然后值就通过icon-data的属性值获得图标名,然后进行相应的替换得到相应图标的base64编码 —> 显示图片

      四、代码实现

    复制代码
      1 <?php
      2     $pathinfo = pathinfo($_SERVER['SCRIPT_FILENAME']);
      3     define('ROOT', $pathinfo['dirname']);
      4 
      5     function generateIcon_mobile() {
      6         $imgRoot = ROOT."/img/mobile";
      7         $iterator = new DirectoryIterator($imgRoot);
      8         foreach ($iterator as $file) {
      9             if ($file->isDot()) continue; 
     10             $filename = $file->getFilename();
     11 
     12             //识别出是否以icon_开头的文件夹,如果是,则对此文件夹的图标进行base64编码处理
     13             if ($file->isDir() && 0 === strncasecmp('icon_', $filename, 5)) {
     14                 generateIconMobileCallback("$imgRoot/$filename", ROOT."/js/mobile");
     15             }
     16         }
     17 
     18     }
     19     
     20     function generateIconMobileCallback($iconDir, $styleSaveDir) {
     21         //保存成js的文件名
     22         $saveName = array_pop(explode('/', $iconDir));
     23         //JS文件保存路径
     24         $styleSavePath = $styleSaveDir.'/'.$saveName.'.js';
     25 
     26         //将当前目录下的所有文件及MD5组成一个识别字符串
     27         $fileMap = array();
     28         $iterator = new DirectoryIterator($iconDir);
     29         foreach ($iterator as $file) {
     30             if ($file->isDot()) continue;
     31             $fileName = $file->getFilename();
     32             if ($file->isDir()) {
     33                 generateIconMobileCallback($iconDir.'/'.$fileName, $styleSaveDir.'/'.$fileName);
     34             } else {
     35                 $fileMap[$fileName] = md5_file($file->getRealPath());
     36             }
     37         }
     38         ksort($fileMap);
     39         $fileMapStr = json_encode($fileMap);
     40 
     41         //确保目录可写
     42         ensure_writable_dir($styleSaveDir);
     43 
     44         //js文件句柄
     45         $wirteHandle = fopen($styleSavePath, 'w');
     46         //当前小图标文件夹的相对路径
     47         $iconSaveRelative = substr($iconDir, strlen(ROOT));
     48         //写入,初始化保存数据的对象
     49         fwrite($wirteHandle, "/** icon in dir: $iconSaveRelative/ */ \nif(typeof(\$iconData) == 'undefined') \$iconData={};");
     50         foreach ($fileMap as $fileName => $md5) {
     51             //当前图片的绝对路径
     52             $fullPathName = "$iconDir/$fileName";
     53             //取得路径信息
     54             $pathInfo = pathinfo($fullPathName);
     55             //取得文件名(没有后缀)
     56             $fileNameNoExt = $pathInfo['filename'];
     57             //取得图片信息
     58             $imageSize = getimagesize($fullPathName);
     59 
     60             //取得文件的后缀
     61             switch ($imageSize[2]) {
     62                 case IMAGETYPE_GIF:
     63                     $imageType = 'gif';
     64                     break;
     65                 case IMAGETYPE_JPEG:
     66                     $imageType = 'jpg';
     67                     break;
     68                 case IMAGETYPE_PNG:
     69                     $imageType = 'png';
     70                     break;
     71                 
     72                 default:
     73                     $imageType = 'jpg';
     74                     break;
     75             }
     76 
     77             //取得图片资源
     78             $readHandle = fopen($fullPathName, 'r');
     79             //将图片转成二进制并生成Base64编码
     80             $base64 = base64_encode(fread($readHandle, filesize($fullPathName)));
     81             //关闭资源
     82             fclose($readHandle);
     83             //将Base64编码写入js文件中
     84             fwrite($wirteHandle, "\n\$iconData.$fileNameNoExt=\"data:image/$imageType;base64,$base64\";");
     85         }
     86         //最后换个行
     87         fwrite($wirteHandle, "\n");
     88         //关闭资源
     89         fclose($wirteHandle); 
     90 
     91         //处理成功的图标文件夹给予提示
     92         echo '<p>'.$iconSaveRelative. ' saved</p>';  
     93     }
     94 
     95     /**
     96     * 确保文件夹存在并可写
     97     *
     98     * @param string $dir
     99     */
    100     function ensure_writable_dir($dir) {
    101         if(!file_exists($dir)) {
    102             mkdir($dir, 0766, true);
    103             @chmod($dir, 0766);
    104             @chmod($dir, 0777);
    105         }
    106         else if(!is_writable($dir)) {
    107             @chmod($dir, 0766);
    108             @chmod($dir, 0777);
    109             if(!@is_writable($dir)) {
    110                 throw new BusinessLogicException("目录不可写", $dir);
    111             }
    112         }
    113     }
    114     generateIcon_mobile();
    115 ?>
    116 
    117 <!DOCTYPE html>
    118 <html>
    119 <head>
    120     <title></title>
    121 </head>
    122 <body>
    123 <br>
    124 <br>
    125 <br>
    126 
    127 <div>我们直接引入所生成的js文件,测试一下是否成功</div>
    128 <br>
    129 <div>直接在img标签里加入 icon-data = '图标文件名'  例如  <\img icon-data="tryit">,查看效果</div>
    130 <br>
    131 <br>
    132 <br>
    133     <img icon-data="tryit">
    134     <script src="js/mobile/icon_pink.js"></script>
    135     <script src="js/mobile/jquery.all.min.js"></script>
    136     <script src="js/mobile/attrHandle.js"></script>
    137 </body>
    138 </html>
    复制代码

     

      然后这里附上属性转换的JS代码

    复制代码
     1 $(function(){
     2     setIconData();
     3 });
     4 
     5 function setIconData() {
     6     if (typeof($iconData != 'undefined')) {
     7         $('img[icon-data]').each(function() {
     8             var self = $(this);
     9             var name = self.attr('icon-data');
    10             if (typeof($iconData[name]) != 'undefined') {
    11                 self.attr('src', $iconData[name]);
    12                 self.removeAttr('icon-data');
    13             }
    14         });
    15     }
    16 }
    复制代码

      五、实现效果

      这是页面输入效果,小图标正常显示出来了

     

      

     

      这里我们自动生成的JS文件是这样子的格式:

     

      页面调用的代码:

     

      JS对img的icon-data属性转换处理的代码:

     

      我们对比下用base64编码和不用base64时所花费的时间:

      先看不用的速度

      

      再看我们用了base64编码的速度   

     

      假如一个页面有很多小图标,那么这种方式对网站的性能优化会有大大的提升。如今此种优化方案是用在我现在的项目中移动端,而上一篇博文讲解的生成背景图的优化方案用在我们项目中的PC端。优化效果是很明显的!当然了,base64编码这种方法也可以用在PC端,我们的项目为啥将它用在手机端,本博文开头部分也有对其做解释。这里测试我就直接在PC端测试,手机端测试也是一个样的。

      这里我补充一点:

        (1)所生成的base64的js文件是在开发中就生成的了,而不是在用户访问时才去生成,我把HTML代码和PHP代码写在一个文件里是方便,在真实项目中是分开的;

        (2)使用此种优化技术有它的优点,当然也会有它的缺点,只有适合自己项目的优化技术才是好技术;

        (3)此中优化技术建议使用在手机端(可以解决背景图优化方式所不能解决的问题),而PC端的则用合并小图标生成背景图的方式(看此文:http://www.cnblogs.com/it-cen/p/4618954.html);

        (4)此种优化技术一般用于小图标(十几K以下),也就是HTTP响应时间远远大于下载时间的时候,用此方法优化会看到明显的效果;

        (5)当然可以配合其他优化技术一起使用,效果更明显,比如缓存等。

     

      这一次就分享那么多给大家,代码我都贴上了,而且很多都标上了注释,方便大家理解。

      

      如果此博文中有哪里讲得让人难以理解,欢迎留言交流,若有讲解错的地方欢迎指出。

      如果您觉得您能在此博文学到了新知识,请为我顶一个,如文章中有解释错的地方,欢迎指出。

    展开全文
  • 在网站开发过程中,对于页面的加载效率一般都想尽办法快。那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的方法。... 一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查...

      在网站开发过程中,对于页面的加载效率一般都想尽办法求快。那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的方法。上一篇博文我们讲解了 “利用将小图标合成一张背景图来减少HTTP请求”,那么,这一篇博文将讲解  “ 将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片”。

      一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片的方法减少HTTP请求数?

      为什么我会讲解 “将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片” 这一种方式来减少HTTP请求,进而优化页面呢?这里呢,是涉及到移动端的图标使用。上一篇博文所讲的方法能否使用于手机端的网页呢?

       但是,它会出现一个问题:背景图+css显示图标时,图标本身无法缩放,比如背景图中64px*64px的图标,显示到界面时必须设置icon的大小也是64*64。在PC网页中这通常不会有什么问题,但在移动端设备上就完全行不通。同样是4英寸的手机屏幕,其分辨率有可能是320*400,也可能是640*800,甚至也可能是1920*1080。这样64px*64px的图标在不同的设备上看起来的大小就会差别非常明显。

      幸运的是,手机上的浏览器基本对此做了优化,会把设备模拟成更低的分辨率。比如在1136*640的IPHONE 5中获取$(window).width(),取出来的是320而不是640,这样一个宽度为160px的图片占用的是屏幕宽度的一半,而不是1/4。手机设备这样处理是为了解决兼容性问题。除了网页,包括手机上app的界面,在retina屏幕上和非retina屏幕上的大小是完全一样的,都是因为对分辨率做了处理。

      但是,移动设备这样的处理方式并不能完全解决问题,因为机器的假设性猜测在很多时候是不合适的,尤其是在android设备中。为了更好地控制元素显示的大小,解决的办法就是用pt代替ps,px是对应屏幕的分辨率,而pt是针对人眼睛实际感觉的大小,无论在何种分辨率的设备上,72pt固定是1英寸。

      HTML的img标签元素的src属性不只是可以指定url,也可以指定图片的二进制数据流。然后通过img元素的自动缩放功能,指定img的大小,就可以实现在不同分辨率的设备上显示一致的图标大小。

      二、使用Base64编码减少页面请求数

      当我们的一个页面中要传入很多图片时,特别是一些小图标,十几K、几K,甚至是字节级别大小的小图标,这些小图标都会增加HTTP请求,假如多了,就会给服务器带来很大的压力。比如要下载一些一两K大的小图标,其实请求时带上的额外信息有可能比图标的大小还要大。所以,在请求越多时,在网络传输的数据自然就越多了,传输的数据自然也就变慢了。而这里,我们采用Base64的编码方式将图片直接嵌入到网页中,而不是从外部载入,这样就减少了HTTP请求。当然了,它有一个小缺点,就是使当前页面的大小变大了(对于优化来说,其实这个可以忽略,影响不大)。看一下下图,小图标大小为2.4k,等待响应时间是14ms,而接受数据,也就是下载时间约为0ms;可想而知,在有大量小图标下载的时候,这样的方式去优化能大大提高网站的性能(在jquery mobile和天猫的手机站上面都有用到此技术)。

      

      三、开发思路

       将小图标放在以icon_开头的文件夹里(以区分不用生成base64的图片的文件夹)—>用程序去遍历文件夹图片 —>将每张图片的base64编码放在一个js对象里—>在HTML页面的img标签里 使用属性 icon-data = '图标名(不带后缀)'来显示图片 —> JS文件写一个函数对icon-data属性进行转换,转换成src属性,然后值就通过icon-data的属性值获得图标名,然后进行相应的替换得到相应图标的base64编码 —> 显示图片

      四、代码实现

    复制代码
      1 <?php
      2     $pathinfo = pathinfo($_SERVER['SCRIPT_FILENAME']);
      3     define('ROOT', $pathinfo['dirname']);
      4 
      5     function generateIcon_mobile() {
      6         $imgRoot = ROOT."/img/mobile";
      7         $iterator = new DirectoryIterator($imgRoot);
      8         foreach ($iterator as $file) {
      9             if ($file->isDot()) continue; 
     10             $filename = $file->getFilename();
     11 
     12             //识别出是否以icon_开头的文件夹,如果是,则对此文件夹的图标进行base64编码处理
     13             if ($file->isDir() && 0 === strncasecmp('icon_', $filename, 5)) {
     14                 generateIconMobileCallback("$imgRoot/$filename", ROOT."/js/mobile");
     15             }
     16         }
     17 
     18     }
     19     
     20     function generateIconMobileCallback($iconDir, $styleSaveDir) {
     21         //保存成js的文件名
     22         $saveName = array_pop(explode('/', $iconDir));
     23         //JS文件保存路径
     24         $styleSavePath = $styleSaveDir.'/'.$saveName.'.js';
     25 
     26         //将当前目录下的所有文件及MD5组成一个识别字符串
     27         $fileMap = array();
     28         $iterator = new DirectoryIterator($iconDir);
     29         foreach ($iterator as $file) {
     30             if ($file->isDot()) continue;
     31             $fileName = $file->getFilename();
     32             if ($file->isDir()) {
     33                 generateIconMobileCallback($iconDir.'/'.$fileName, $styleSaveDir.'/'.$fileName);
     34             } else {
     35                 $fileMap[$fileName] = md5_file($file->getRealPath());
     36             }
     37         }
     38         ksort($fileMap);
     39         $fileMapStr = json_encode($fileMap);
     40 
     41         //确保目录可写
     42         ensure_writable_dir($styleSaveDir);
     43 
     44         //js文件句柄
     45         $wirteHandle = fopen($styleSavePath, 'w');
     46         //当前小图标文件夹的相对路径
     47         $iconSaveRelative = substr($iconDir, strlen(ROOT));
     48         //写入,初始化保存数据的对象
     49         fwrite($wirteHandle, "/** icon in dir: $iconSaveRelative/ */ \nif(typeof(\$iconData) == 'undefined') \$iconData={};");
     50         foreach ($fileMap as $fileName => $md5) {
     51             //当前图片的绝对路径
     52             $fullPathName = "$iconDir/$fileName";
     53             //取得路径信息
     54             $pathInfo = pathinfo($fullPathName);
     55             //取得文件名(没有后缀)
     56             $fileNameNoExt = $pathInfo['filename'];
     57             //取得图片信息
     58             $imageSize = getimagesize($fullPathName);
     59 
     60             //取得文件的后缀
     61             switch ($imageSize[2]) {
     62                 case IMAGETYPE_GIF:
     63                     $imageType = 'gif';
     64                     break;
     65                 case IMAGETYPE_JPEG:
     66                     $imageType = 'jpg';
     67                     break;
     68                 case IMAGETYPE_PNG:
     69                     $imageType = 'png';
     70                     break;
     71                 
     72                 default:
     73                     $imageType = 'jpg';
     74                     break;
     75             }
     76 
     77             //取得图片资源
     78             $readHandle = fopen($fullPathName, 'r');
     79             //将图片转成二进制并生成Base64编码
     80             $base64 = base64_encode(fread($readHandle, filesize($fullPathName)));
     81             //关闭资源
     82             fclose($readHandle);
     83             //将Base64编码写入js文件中
     84             fwrite($wirteHandle, "\n\$iconData.$fileNameNoExt=\"data:image/$imageType;base64,$base64\";");
     85         }
     86         //最后换个行
     87         fwrite($wirteHandle, "\n");
     88         //关闭资源
     89         fclose($wirteHandle); 
     90 
     91         //处理成功的图标文件夹给予提示
     92         echo '<p>'.$iconSaveRelative. ' saved</p>';  
     93     }
     94 
     95     /**
     96     * 确保文件夹存在并可写
     97     *
     98     * @param string $dir
     99     */
    100     function ensure_writable_dir($dir) {
    101         if(!file_exists($dir)) {
    102             mkdir($dir, 0766, true);
    103             @chmod($dir, 0766);
    104             @chmod($dir, 0777);
    105         }
    106         else if(!is_writable($dir)) {
    107             @chmod($dir, 0766);
    108             @chmod($dir, 0777);
    109             if(!@is_writable($dir)) {
    110                 throw new BusinessLogicException("目录不可写", $dir);
    111             }
    112         }
    113     }
    114     generateIcon_mobile();
    115 ?>
    116 
    117 <!DOCTYPE html>
    118 <html>
    119 <head>
    120     <title></title>
    121 </head>
    122 <body>
    123 <br>
    124 <br>
    125 <br>
    126 
    127 <div>我们直接引入所生成的js文件,测试一下是否成功</div>
    128 <br>
    129 <div>直接在img标签里加入 icon-data = '图标文件名'  例如  <\img icon-data="tryit">,查看效果</div>
    130 <br>
    131 <br>
    132 <br>
    133     <img icon-data="tryit">
    134     <script src="js/mobile/icon_pink.js"></script>
    135     <script src="js/mobile/jquery.all.min.js"></script>
    136     <script src="js/mobile/attrHandle.js"></script>
    137 </body>
    138 </html>
    复制代码

     

      然后这里附上属性转换的JS代码

    复制代码
     1 $(function(){
     2     setIconData();
     3 });
     4 
     5 function setIconData() {
     6     if (typeof($iconData != 'undefined')) {
     7         $('img[icon-data]').each(function() {
     8             var self = $(this);
     9             var name = self.attr('icon-data');
    10             if (typeof($iconData[name]) != 'undefined') {
    11                 self.attr('src', $iconData[name]);
    12                 self.removeAttr('icon-data');
    13             }
    14         });
    15     }
    16 }
    复制代码

      五、实现效果

      这是页面输入效果,小图标正常显示出来了

     

      

     

      这里我们自动生成的JS文件是这样子的格式:

     

      页面调用的代码:

     

      JS对img的icon-data属性转换处理的代码:

     

      我们对比下用base64编码和不用base64时所花费的时间:

      先看不用的速度

      

      再看我们用了base64编码的速度   

     

      假如一个页面有很多小图标,那么这种方式对网站的性能优化会有大大的提升。如今此种优化方案是用在我现在的项目中移动端,而上一篇博文讲解的生成背景图的优化方案用在我们项目中的PC端。优化效果是很明显的!当然了,base64编码这种方法也可以用在PC端,我们的项目为啥将它用在手机端,本博文开头部分也有对其做解释。这里测试我就直接在PC端测试,手机端测试也是一个样的。

      这里我补充一点:

        (1)所生成的base64的js文件是在开发中就生成的了,而不是在用户访问时才去生成,我把HTML代码和PHP代码写在一个文件里是方便,在真实项目中是分开的;

        (2)使用此种优化技术有它的优点,当然也会有它的缺点,只有适合自己项目的优化技术才是好技术;

        (3)此中优化技术建议使用在手机端(可以解决背景图优化方式所不能解决的问题),而PC端的则用合并小图标生成背景图的方式(看此文:http://www.cnblogs.com/it-cen/p/4618954.html);

        (4)此种优化技术一般用于小图标(十几K以下),也就是HTTP响应时间远远大于下载时间的时候,用此方法优化会看到明显的效果;

        (5)当然可以配合其他优化技术一起使用,效果更明显,比如缓存等。

     

      这一次就分享那么多给大家,代码我都贴上了,而且很多都标上了注释,方便大家理解。

      

      如果此博文中有哪里讲得让人难以理解,欢迎留言交流,若有讲解错的地方欢迎指出。

      如果您觉得您能在此博文学到了新知识,请为我顶一个,如文章中有解释错的地方,欢迎指出。

      互相学习,共同进步!

    转载于:https://www.cnblogs.com/jpfss/p/10037994.html

    展开全文
  • 在网站开发过程中,对于页面的加载效率一般都想尽办法...上一篇博文我们讲解了 “利用将小图标合成一张背景图来减少HTTP请求”,那么,这一篇博文将讲解 “ 将图片转成二进制并生成Base64编码,可以在网页

    原文地址: http://www.cnblogs.com/it-cen/p/4624939.html


    在网站开发过程中,对于页面的加载效率一般都想尽办法求快。那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的方法。上一篇博文我们讲解了 “利用将小图标合成一张背景图来减少HTTP请求”,那么,这一篇博文将讲解  “ 将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片”。

      一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片的方法减少HTTP请求数?

      为什么我会讲解 “将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片” 这一种方式来减少HTTP请求,进而优化页面呢?这里呢,是涉及到移动端的图标使用。上一篇博文所讲的方法能否使用于手机端的网页呢?

       但是,它会出现一个问题:背景图+css显示图标时,图标本身无法缩放,比如背景图中64px*64px的图标,显示到界面时必须设置icon的大小也是64*64。在PC网页中这通常不会有什么问题,但在移动端设备上就完全行不通。同样是4英寸的手机屏幕,其分辨率有可能是320*400,也可能是640*800,甚至也可能是1920*1080。这样64px*64px的图标在不同的设备上看起来的大小就会差别非常明显。

      幸运的是,手机上的浏览器基本对此做了优化,会把设备模拟成更低的分辨率。比如在1136*640的IPHONE 5中获取$(window).width(),取出来的是320而不是640,这样一个宽度为160px的图片占用的是屏幕宽度的一半,而不是1/4。手机设备这样处理是为了解决兼容性问题。除了网页,包括手机上app的界面,在retina屏幕上和非retina屏幕上的大小是完全一样的,都是因为对分辨率做了处理。

      但是,移动设备这样的处理方式并不能完全解决问题,因为机器的假设性猜测在很多时候是不合适的,尤其是在android设备中。为了更好地控制元素显示的大小,解决的办法就是用pt代替ps,px是对应屏幕的分辨率,而pt是针对人眼睛实际感觉的大小,无论在何种分辨率的设备上,72pt固定是1英寸。

      HTML的img标签元素的src属性不只是可以指定url,也可以指定图片的二进制数据流。然后通过img元素的自动缩放功能,指定img的大小,就可以实现在不同分辨率的设备上显示一致的图标大小。

      二、使用Base64编码减少页面请求数

      当我们的一个页面中要传入很多图片时,特别是一些小图标,十几K、几K,甚至是字节级别大小的小图标,这些小图标都会增加HTTP请求,假如多了,就会给服务器带来很大的压力。比如要下载一些一两K大的小图标,其实请求时带上的额外信息有可能比图标的大小还要大。所以,在请求越多时,在网络传输的数据自然就越多了,传输的数据自然也就变慢了。而这里,我们采用Base64的编码方式将图片直接嵌入到网页中,而不是从外部载入,这样就减少了HTTP请求。当然了,它有一个小缺点,就是使当前页面的大小变大了(对于优化来说,其实这个可以忽略,影响不大)。看一下下图,小图标大小为2.4k,等待响应时间是14ms,而接受数据,也就是下载时间约为0ms;可想而知,在有大量小图标下载的时候,这样的方式去优化能大大提高网站的性能(在jquery mobile和天猫的手机站上面都有用到此技术)。

      

      三、开发思路

       将小图标放在以icon_开头的文件夹里(以区分不用生成base64的图片的文件夹)—>用程序去遍历文件夹图片 —>将每张图片的base64编码放在一个js对象里—>在HTML页面的img标签里 使用属性 icon-data = '图标名(不带后缀)'来显示图片 —> JS文件写一个函数对icon-data属性进行转换,转换成src属性,然后值就通过icon-data的属性值获得图标名,然后进行相应的替换得到相应图标的base64编码 —> 显示图片

      四、代码实现

    复制代码
      1 <?php
      2     $pathinfo = pathinfo($_SERVER['SCRIPT_FILENAME']);
      3     define('ROOT', $pathinfo['dirname']);
      4 
      5     function generateIcon_mobile() {
      6         $imgRoot = ROOT."/img/mobile";
      7         $iterator = new DirectoryIterator($imgRoot);
      8         foreach ($iterator as $file) {
      9             if ($file->isDot()) continue; 
     10             $filename = $file->getFilename();
     11 
     12             //识别出是否以icon_开头的文件夹,如果是,则对此文件夹的图标进行base64编码处理
     13             if ($file->isDir() && 0 === strncasecmp('icon_', $filename, 5)) {
     14                 generateIconMobileCallback("$imgRoot/$filename", ROOT."/js/mobile");
     15             }
     16         }
     17 
     18     }
     19     
     20     function generateIconMobileCallback($iconDir, $styleSaveDir) {
     21         //保存成js的文件名
     22         $saveName = array_pop(explode('/', $iconDir));
     23         //JS文件保存路径
     24         $styleSavePath = $styleSaveDir.'/'.$saveName.'.js';
     25 
     26         //将当前目录下的所有文件及MD5组成一个识别字符串
     27         $fileMap = array();
     28         $iterator = new DirectoryIterator($iconDir);
     29         foreach ($iterator as $file) {
     30             if ($file->isDot()) continue;
     31             $fileName = $file->getFilename();
     32             if ($file->isDir()) {
     33                 generateIconMobileCallback($iconDir.'/'.$fileName, $styleSaveDir.'/'.$fileName);
     34             } else {
     35                 $fileMap[$fileName] = md5_file($file->getRealPath());
     36             }
     37         }
     38         ksort($fileMap);
     39         $fileMapStr = json_encode($fileMap);
     40 
     41         //确保目录可写
     42         ensure_writable_dir($styleSaveDir);
     43 
     44         //js文件句柄
     45         $wirteHandle = fopen($styleSavePath, 'w');
     46         //当前小图标文件夹的相对路径
     47         $iconSaveRelative = substr($iconDir, strlen(ROOT));
     48         //写入,初始化保存数据的对象
     49         fwrite($wirteHandle, "/** icon in dir: $iconSaveRelative/ */ \nif(typeof(\$iconData) == 'undefined') \$iconData={};");
     50         foreach ($fileMap as $fileName => $md5) {
     51             //当前图片的绝对路径
     52             $fullPathName = "$iconDir/$fileName";
     53             //取得路径信息
     54             $pathInfo = pathinfo($fullPathName);
     55             //取得文件名(没有后缀)
     56             $fileNameNoExt = $pathInfo['filename'];
     57             //取得图片信息
     58             $imageSize = getimagesize($fullPathName);
     59 
     60             //取得文件的后缀
     61             switch ($imageSize[2]) {
     62                 case IMAGETYPE_GIF:
     63                     $imageType = 'gif';
     64                     break;
     65                 case IMAGETYPE_JPEG:
     66                     $imageType = 'jpg';
     67                     break;
     68                 case IMAGETYPE_PNG:
     69                     $imageType = 'png';
     70                     break;
     71                 
     72                 default:
     73                     $imageType = 'jpg';
     74                     break;
     75             }
     76 
     77             //取得图片资源
     78             $readHandle = fopen($fullPathName, 'r');
     79             //将图片转成二进制并生成Base64编码
     80             $base64 = base64_encode(fread($readHandle, filesize($fullPathName)));
     81             //关闭资源
     82             fclose($readHandle);
     83             //将Base64编码写入js文件中
     84             fwrite($wirteHandle, "\n\$iconData.$fileNameNoExt=\"data:image/$imageType;base64,$base64\";");
     85         }
     86         //最后换个行
     87         fwrite($wirteHandle, "\n");
     88         //关闭资源
     89         fclose($wirteHandle); 
     90 
     91         //处理成功的图标文件夹给予提示
     92         echo '<p>'.$iconSaveRelative. ' saved</p>';  
     93     }
     94 
     95     /**
     96     * 确保文件夹存在并可写
     97     *
     98     * @param string $dir
     99     */
    100     function ensure_writable_dir($dir) {
    101         if(!file_exists($dir)) {
    102             mkdir($dir, 0766, true);
    103             @chmod($dir, 0766);
    104             @chmod($dir, 0777);
    105         }
    106         else if(!is_writable($dir)) {
    107             @chmod($dir, 0766);
    108             @chmod($dir, 0777);
    109             if(!@is_writable($dir)) {
    110                 throw new BusinessLogicException("目录不可写", $dir);
    111             }
    112         }
    113     }
    114     generateIcon_mobile();
    115 ?>
    116 
    117 <!DOCTYPE html>
    118 <html>
    119 <head>
    120     <title></title>
    121 </head>
    122 <body>
    123 <br>
    124 <br>
    125 <br>
    126 
    127 <div>我们直接引入所生成的js文件,测试一下是否成功</div>
    128 <br>
    129 <div>直接在img标签里加入 icon-data = '图标文件名'  例如  <\img icon-data="tryit">,查看效果</div>
    130 <br>
    131 <br>
    132 <br>
    133     <img icon-data="tryit">
    134     <script src="js/mobile/icon_pink.js"></script>
    135     <script src="js/mobile/jquery.all.min.js"></script>
    136     <script src="js/mobile/attrHandle.js"></script>
    137 </body>
    138 </html>
    复制代码

     

      然后这里附上属性转换的JS代码

    复制代码
     1 $(function(){
     2     setIconData();
     3 });
     4 
     5 function setIconData() {
     6     if (typeof($iconData != 'undefined')) {
     7         $('img[icon-data]').each(function() {
     8             var self = $(this);
     9             var name = self.attr('icon-data');
    10             if (typeof($iconData[name]) != 'undefined') {
    11                 self.attr('src', $iconData[name]);
    12                 self.removeAttr('icon-data');
    13             }
    14         });
    15     }
    16 }
    复制代码

      五、实现效果

      这是页面输入效果,小图标正常显示出来了

     

      

     

      这里我们自动生成的JS文件是这样子的格式:

     

      页面调用的代码:

     

      JS对img的icon-data属性转换处理的代码:

     

      我们对比下用base64编码和不用base64时所花费的时间:

      先看不用的速度

      

      再看我们用了base64编码的速度   

     

      假如一个页面有很多小图标,那么这种方式对网站的性能优化会有大大的提升。如今此种优化方案是用在我现在的项目中移动端,而上一篇博文讲解的生成背景图的优化方案用在我们项目中的PC端。优化效果是很明显的!当然了,base64编码这种方法也可以用在PC端,我们的项目为啥将它用在手机端,本博文开头部分也有对其做解释。这里测试我就直接在PC端测试,手机端测试也是一个样的。

      这里我补充一点:

        (1)所生成的base64的js文件是在开发中就生成的了,而不是在用户访问时才去生成,我把HTML代码和PHP代码写在一个文件里是方便,在真实项目中是分开的;

        (2)使用此种优化技术有它的优点,当然也会有它的缺点,只有适合自己项目的优化技术才是好技术;

        (3)此中优化技术建议使用在手机端(可以解决背景图优化方式所不能解决的问题),而PC端的则用合并小图标生成背景图的方式(看此文:http://www.cnblogs.com/it-cen/p/4618954.html);

        (4)此种优化技术一般用于小图标(十几K以下),也就是HTTP响应时间远远大于下载时间的时候,用此方法优化会看到明显的效果;

        (5)当然可以配合其他优化技术一起使用,效果更明显,比如缓存等。


    展开全文
  • 遗传算法三元函数极值(python)-采用实数编码想看二进制编码编码的博客地址在这遗传算法三元函数极值(python)-采用二进制编码本文的遗传算法采用实数编码三元函数极值所函数为`其完整代码如下:x1x1-x1x2+x3...

    遗传算法求三元函数极值(python)-采用实数编码

    想看二进制编码编码的博客地址在这

    遗传算法求三元函数极值(python)-采用二进制编码

    本文的遗传算法采用实数编码求三元函数极值

    所求函数为

    866fc7ee147a373ffa6765eacd692bf2.png

    `

    其完整代码如下:

    x1

    x1-x1

    x2+x3

    import numpy as np

    import random

    DNA_SIZE =1

    POP_SIZE =100

    CROSSOVER_RATE = 0.8

    MUTATION_RATE = 0.015

    N_GENERATIONS = 500

    X_BOUND = [3.0,5.0]#x1

    Y_BOUND = [2.1,6.7]#x2

    Z_BOUND = [1.2,9.6]#x3

    def F(x, y,z):

    val=x

    x-x

    y+z

    ‘’’

    for index in range(len(val)):

    if val[index] <0.2:

    val[index]=0.2

    '''

    print(val.shape) #(100,) 100

    return val

    def get_fitness(pop):

    x,y ,z= translateDNA(pop)

    pred = F(x, y,z)

    return pred

    def translateDNA(pop): #pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目

    # x_pop = pop[:,0:DNA_SIZE]#这样的写法shape 是(3, 1) 3行1列 ndim维度是2(行,列 矩阵 )

    # 也可以认为是二维数组,有3行,每行有1个元素 size为3 [[3.18796615]\n [3.32110516]\n [4.34665405]]

    ‘’'因为这样写x_pop = pop[:, 0:DNA_SIZE] shape是(3,1)是二维数组,所以会报"对象太深,无法容纳所需的数组"的错误,

    第一种解决方法是进行reshape,比如reshape(3,)即变成了一维数组,元素个数是3个,即语法是x_pop=pop[:,0:DNA_SIZE].reshape(POP_SIZE,)

    这时x_pop就变为[4.96893731 3.24515899 3.51500566] 一维数组

    第二种方法是在矩阵(二维数组)pop中直接选择某一列元素,比如 pop[:, 0],表示选择pop第0列所有的元素

    '''

    x_pop = pop[:, 0] # 取前DNA_SIZE个列表示x 这样的写法shape是(3,) ndim维度是1 一维数组 ,数组元素有3个 size为3 [4.28040552 3.25412449 4.61336022]

    # print(x_pop.shape)

    y_pop = pop[:,1]#取中间DNA_SIZE个列表示y

    z_pop = pop[:,2]#取后DNA_SIZE个列表示z

    # print(x_pop)

    '''pop:(POP_SIZE,DNA_SIZE)*(DNA_SIZE,1) --> (POP_SIZE,1)'''#二进制--->十进制

    # x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0]

    # y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0]

    # z = z_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Z_BOUND[1]-Z_BOUND[0])+Z_BOUND[0]

    # print(x,z)

    return x_pop,y_pop,z_pop

    def mutation(child, MUTATION_RATE=0.003):

    if np.random.rand() < MUTATION_RATE: #以MUTATION_RATE的概率进行变异

    mutate_point = np.random.randint(0, DNA_SIZE*3)#随机产生一个实数,代表要变异基因的位置

    if mutate_point

    0:

    child[mutate_point] =np.random.uniform(3.0,5.0)

    elif mutate_point

    1:

    child[mutate_point] =np.random.uniform(2.1,6.7)

    else:

    child[mutate_point] =np.random.uniform(1.2,9.6)

    def crossover_and_mutation(pop, CROSSOVER_RATE = 0.015):

    new_pop = []

    for father in pop:#遍历种群中的每一个个体,将该个体作为父亲

    child = father#孩子先得到父亲的全部基因

    if np.random.rand() < CROSSOVER_RATE:#产生子代时不是必然发生交叉,而是以一定的概率发生交叉

    mother = pop[np.random.randint(POP_SIZE)]#再种群中选择另一个个体,并将该个体作为母亲

    cross_points = np.random.randint(low=0, high=DNA_SIZE*3)#随机产生交叉的点

    child[cross_points:] = mother[cross_points:]#孩子得到位于交叉点后的母亲的基因

    mutation(child)#mutation(child,MUTATION_RATE)每个后代有一定的机率发生变异

    new_pop.append(child)

    return new_pop

    def select(pop, fitness): # nature selection wrt pop’s fitness

    # fitnew=fitness.copy() #浅拷贝

    fitnew = fitness

    # for index in range(len(fitnew)):

    # if fitnew[index] <0:

    # fitnew[index]=0

    fitnew=fitnew + 1e-3 - np.min(fitnew)

    p=(fitnew)/(fitnew.sum())

    # print(fitnew)

    # print(fitnew.sum())

    # print(np.arange(POP_SIZE)) #0,1,2,3,...,99

    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE,replace=True,p=p)

    # print(pop[idx].shape) #shape (3, 3)

    '''

    [[3.43993966 5.19547684 5.17821964]

    [4.0803077 5.19547684 5.17821964]

    [3.43993966 5.19547684 5.17821964]]

    '''

    return pop[idx] #尽量选择适应值高的函数值的个体

    ‘’’

    如果POP_SIZE=3,即种群个数是3,则从交叉,变异后的种群中,选择3个适应值高 pop[idx]=[2 0 0]的新个体去

    更新pop种群,之后再进行不断的迭代,直到达到迭代次数终止。

    ‘’’

    def print_info(pop):

    fitness = get_fitness(pop)

    max_fitness_index = np.argmax(fitness)

    print(“max_fitness:”, fitness[max_fitness_index])

    x,y,z = translateDNA(pop)

    print("最优的基因型:", pop[max_fitness_index])

    print("(x, y, z):", (x[max_fitness_index], y[max_fitness_index],z[max_fitness_index]))

    if

    name

    == “

    main

    ”:

    pop1 = np.random.uniform(3.0,5.0, size=(POP_SIZE, DNA_SIZE)) #matrix (POP_SIZE, DNA_SIZE)

    pop2 = np.random.uniform(2.1, 6.7, size=(POP_SIZE, DNA_SIZE))

    pop3 = np.random.uniform(1.2, 9.6, size=(POP_SIZE, DNA_SIZE))

    print(type(pop1))# (100,1) 维度是2(行列 矩阵)

    pop={pop1,pop2,pop3}

    pop=np.hstack((pop1,pop2,pop3))

    print(pop)

    ‘’’

    [[3.44603448 4.51707625 7.90178727]

    [4.57616299 5.11309286 4.86911781]

    [3.24273815 2.9253602 4.45149325]

    [4.39321276 3.1657492 5.16654786]]

    ‘’’

    print(type(pop)) # n维数组

    print(pop.shape) #(100,3) 矩阵有 100行,3列

    print(pop.ndim) # 2 因为矩阵有行和列两个维度

    print(pop.size) #300 矩阵共有300个元素

    print(pop.dtype) #float64 矩阵元素类型是float64

    for _ in range(N_GENERATIONS):#迭代N代

    x,y,z = translateDNA(pop) #这句代码,我觉得没啥作用

    # print(x) #(100,) [4.82264692 4.04610252 4.92107325 4.49556859 3.1322498 3.60757363…] 一维数组100个数据

    pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))

    # print(pop.dtype)# (100, 3) 2 300 float64

    fitness = get_fitness(pop)

    # print(fitness) # (100,) 一维数组 100

    pop = select(pop, fitness) #选择生成新的种群

    # print(pop.shape) (100,3)

    print_info(pop)

    `

    展开全文
  • 二元函数为y=x1^2+x2^2,x∈[-5,5]NIND=121; %初始种群的个数(Number of individuals)NVAR=2;... %变量的二进制位数(Precision of variables)MAXGEN=200; %最大遗传代数(Maximum number of generations)GGAP=0.8; %代...
  • 为了更好的理解遗传算法的运算过程,下面用手工的计算间的模拟遗传算法的各个主要的执行步骤:例、下述二元...因x1,x2为0-7之间的正数,所以分别用3位无符号二进制整数来表示,将他们连接在一起所组成的6位无符号...
  • //以二进制方式打开hfmTree.dat文件,并当重新运行时覆盖原文件 fop.open("hfmTree.dat",ios::out|ios::binary|ios::trunc); if(fop.fail()) //文件打开失败 cout文件打开失败!\n"; fop.write((char*)&...
  • 【问题描述】 设计一个哈夫曼编码/译码系统,对一个文本文件中的字符进行哈夫曼...(6)把哈夫曼编码二进制位紧缩到一个变量中,利用位运算进行真正的数据压缩,并压缩比。 (7)显示哈夫曼树; (8)使用汉字显示。
  • 为什么要有原码反码和补码不同的编码数值在计算机中表示形式为机器数,计算机只能识别0和1,使用的是二进制,而在日常生活中人们使用的是十进制,"正如亚里士多德早就指出的那样,今天十进制的广泛采用,只不过我们绝大...
  • NOI 2015 荷马史诗

    2015-08-04 12:47:35
    扩展的Huffman编码(由以前的二进制变为了k进制) 求编码后文章最短长度和Huffman树的最小高度(或者说最长串最短长度,当然是在文章最短前提下) 你不知道Huffman编码? 你知道Huffman编码但不知道是怎么回事? 看CLRS...
  • AES加密之openssl使用(2)

    千次阅读 2012-12-03 22:14:52
    书接上篇《AES加密只openssl安装》,在...加密后的结果因为是二进制数字,而base64编码之中要求传入编码的长度,于是使用strlen就不怎么靠谱了,加密后的长度怎么求出。解决1.使用MD5加密为固定长度,缺点不可逆。2.me
  • 在网站开发过程中,对于页面的加载效率一般都想尽办法快。那么,怎么让才能更快呢?减少页面请求 是一个优化页面加载速度很好的...一、为何选择将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片...
  • c++ 构建哈夫曼树

    2020-05-08 18:55:09
    哈夫曼树是一种用来对字符进行编码的数据结构,可以根据字符的使用频率来决定字符的二进制表示,使得转化后的二进制序列尽可能短。 哈夫曼树的具体介绍见此博客用漫画介绍哈弗曼树 接下来介绍哈夫曼树的构造方法,...
  • 0190. 颠倒二进制位 0191. 位 1 的个数 0198. 打家劫舍 0203. 移除链表元素 0206. 反转链表 0219. 存在重复元素 II 0226. 翻转二叉树 0232. 用栈实现队列 91 0263. 丑数 0283. 移动零 0342. 4 ...
  • CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。接收端根据同样的...
  • 格雷码的输出

    2015-12-21 16:53:54
    在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码 例如当n为1的时候,格雷码为0,1;n为2的时候,格雷码为00,01,11,10;n为3的时候,格雷码为000,001,011,010,110,111,...
  • JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】 JDBC【事务、元数据、改造JDBC工具类】 JDBC【数据库连接池、DbUtils框架、分页】 JDBC面试题都在这里 Druid数据库连接池就是这么简单...
  • //mysql_real_query比mysql_query多了个参数: 字符串query的长度, 所以适合有二进制数据的query, 而mysql_query的字符串query不能包含二进制,因为它以\0为结尾 //mysql_query() 不能传二进制BLOB字段,因为二进制...
  • 这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 2.15 如何确定域在结构中的字节偏移量...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 27  2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 28 2.15 如何确定域在结构中的...
  • 这导致空间浪费而且无法与外部数据文件进行“二进制”读写。能否关掉填充,或者控制结构域的对齐方式? 27  2.14 为什么sizeof返回的值大于结构大小的期望值,是不是尾部有填充? 28 2.15 如何确定域在结构中的...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

二进制编码怎么求