嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

周梦康 发表于 2014-06-25 3132 次浏览 标签 : ZzBlogjquerylazyload

由于公司的项目要搞手机版,对于手机的网速,所以图片还是要增加一个懒加载的功能,为了我高大上的博客小带宽应对大流量访问,所以也给添加上了懒加载。

思路是与我之前写博客里面的markdown小标签思路一样。存在数据库的数据都是正常的数据(这样也方便修改编辑),只是在读取的时候,在输出到页面之前,在控制器里做了一次正则匹配的处理,来把里面的img标签的内容全部“格式化”一次!把

<img src="xxxx">

都替换为:

<img data-original="xxx.jpg" width="xxx" height="xxx">

之所以是要把宽和高计算出来,是为了防止页面加载而导致整个页面膨胀,而使得别人拉动页面的时候有跳跃感。

懒加载插件使用的是:https://github.com/tuupola/jquery_lazyload

整理了下,代码如下:

//下面的 $contents 代表页面输出的内容
//还原被替换了的html标签方便匹配<img xxx>
$contents = htmlspecialchars_decode($contents,ENT_QUOTES);
//做懒加载匹配
$contents = preg_replace_callback(
    '/<\s*img\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i',
    function($matches){
        $info = getimagesize('http:'.'//'.$_SERVER['HTTP_HOST'].'/'.$matches[2]);
        //如果宽于480的,给480;窄于480的给实际的宽度
        //如果不写高度,网速快的时候可能感觉不到,如果网速慢,可能会导致页面拉倒下面之后,会“弹回到上面”的效果,之前逛淘宝深受其害。
        if($info[0] < 480){
            return "<img data-original=\"".$matches[2]."\" width=\"".$info[0]."\" height=\"".$info[1]."\">";
        }else{
            $_tmpHeight = intval((480*$info[1])/$info[0]);
            return "<img data-original=\"".$matches[2]."\" width=\"480\" height=\"".$_tmpHeight."\">";
        }
        return $matches[2];
    },
    $contents
);

最后为了SEO给百度能抓到一张截图,考虑把第一张图给展示出来

//把第一张图显示出来方便百度抓取做为该文章的缩略图
$this->title = htmlspecialchars_decode($res[0]['title'],ENT_QUOTES);//把双引号等转义回来
$title = str_replace('"',"'",$this->title);
$res[0]['content'] = preg_replace_callback(
    '/<\s*img\s+[^>]*?data-original\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i',
    function($matches) use($title){
        //考虑到有的gif图片很大,如果这种情况则直接直接显示,保持懒加载模式
        if(filesize(ROOT.$matches[2])>240000){
            return $matches[0];
        }else{
            return str_replace(">"," alt=\"{$title}\" >",str_replace("data-original","src",$matches[0]));
        }
    },
    $res[0]['content'],1
);

最后小小的优化,又将上面两次匹配回调处理放到一次处理,同时更大可能性的保证有缩略图的存在:

//还原被替换了的html标签方便匹配<img xxx>
$res[0]['content'] = htmlspecialchars_decode($res[0]['content'],ENT_QUOTES);
//把双引号等转义回来
$this->title = htmlspecialchars_decode($res[0]['title'],ENT_QUOTES);
$title = str_replace('"',"'",$this->title);
$count = 0;
//做懒加载匹配
$res[0]['content'] = preg_replace_callback(
    '/<\s*img\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i',
    function($matches) use($title,&$count){
        if(strstr($matches[2],"http://")){
            $info = getimagesize($matches[2]);
        }else{
            $info = getimagesize(ROOT.$matches[2]);
        }
        //如果宽于480的,给480;窄于480的给实际的宽度
        //如果不写高度,网速快的时候可能感觉不到,如果网速慢,可能会导致页面拉倒下面之后,会“弹回到上面”的效果,之前逛淘宝深受其害。
        if($info[0] < 480){
            $lazyImg = "<img data-original=\"".$matches[2]."\" width=\"".$info[0]."\" height=\"".$info[1]."\">";
        }else{
            $_tmpHeight = intval((480*$info[1])/$info[0]);
            $lazyImg = "<img data-original=\"".$matches[2]."\" width=\"480\" height=\"".$_tmpHeight."\">";
        }
        //找一张比较小的图作为文章的缩略图,供搜索引擎抓取
        if(($count< 1) && (filesize(ROOT.$matches[2])<240000)){
            $lazyImg = str_replace(">"," alt=\"{$title}\" >",str_replace("data-original","src",$lazyImg));
            $count++;
        }
        return $lazyImg;
    },
    $res[0]['content']
);

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表

回复 Ping 2017-05-12 22:27:51
博主的是什么博客框架?
回复 康哥 2017-06-03 12:35:07
回复Ping: 没有框架哦,就随便写的