最近一周一直在改博客主题的代码,荒废了CTF的学习。主要是我个人有些强迫症,看到不太顺眼的样式就会难受。迫不得已,没有任何前端经验的、对js和css零接触、仅仅因为写爬虫而对html有一点点了解的我,踏上了改代码的旅途。

为防止时间一长,我忘记了代码中哪些是我修改或添加的,哪些是原主题的,同时巩固一下接触到的相关知识,故写下这篇笔记。由于篇幅太长,本文分html+js+css和php两篇文章来记录。

0x01 相关改动概述

关于html+js+css方面的改动有以下几点:

  • 为文章卡片的图片添加动态效果,鼠标移动至图片上时自动放大。同时将矩形的图片改为圆角
  • 阅读数、评论数从卡片底部提高至标题下方靠右侧。
  • 添加文章内点击图片弹出图片的功能。

    • PC端弹出图片后,鼠标滚轮可缩放图片。单击可关闭图片、
    • 移动端弹出图片后,单指滑动可移动图片,单指点击图片可关闭图片,双指滑动可缩放图片。
  • 将文字预览内容的全角空格替换为空、网址替换为###。提取文首400个字节,设定中文2字节英文1字节,将预览文字字节设为200。

0x02 图片动态效果

既然是给文章卡片的预览图添加效果,那么自然先找到index.php中卡片代码的位置

<article itemscope itemtype="http://schema.org/BlogPosting" class="card animated wow fadeIn" data-wow-duration="1s" data-wow-offset="10">
    ...
</article>

找到下面的代码:

<div class="card-thumbnail" style="background:url(<?php if($this->fields->thumbnail)
            $this->fields->thumbnail();
        else
            echo Utils::getThumbnail();
    ?>) center center no-repeat;background-size: 100% auto;">
</div>

这代代码是通过php从接口中获取图片url,写入div标签的style属性。

我们将其改为:

<div class="card-thumbnail" >
    <img class="card-thumbnail-pic" src="<?php if($this->fields->thumbnail)
            $this->fields->thumbnail();
        else
            echo Utils::getThumbnail();
    ?>" />
</div>

对比发现,原先通过div的style引入了图片并设置了图片样式,现在通过在div内添加img标签并通过class的控制样式。

在style.min.css中找到:

.card-thumbnail {
    display: block;
    height: 320px;
    width: 100%;
    margin: 10px auto;
    box-sizing: border-box;
    overflow: hidden
}

改为:

.card-thumbnail{
    display: block;
    height: 320px;
    width: 100%;
    margin: 10px auto;
    box-sizing: border-box;
    overflow: hidden;
    border-radius: 10px;
}

.card-thumbnail img{
    cursor: pointer;
    transition: all 0.6s;
}

.card-thumbnail img:hover{
    transform: scale(1.4);
}

在修改后的样式中,.card-thumbnail中多了border-radius: 10px;这是控制圆角的,半径为10px

后面的.card-thumbnail img,中间有个空格,意思是class card-thumbnail内部的img标签的样式。

transition控制放大时间,transform控制放大倍数。

另外说一下,你会发现css一大片代码都在一行,没有任何的空格或换行。我猜测是为了减少传输的流量?毕竟蚊子腿再细也是肉。可以在https://tool.oschina.net/codeformat/css 将其格式化。

上面的在html中的更改也要在archive.php中做相应的更改哦。archive.php展示1569226759989

0x03 阅读数、评论数位置的更改

还是在index.php中的卡片标签内。

原为:

<div class="card-meta-top">
    <span class="card-meta-cate"><i class="iconfont icon-aria-category"></i> <?php $this->category(' • ',true,'无'); ?></span><span class="card-meta-date"><i class="iconfont icon-aria-date"></i> <?php $this->date(); ?></span>
</div>

只有文章的分类。我们将位于卡片底部的阅读数和评论数的标签移动至此处:

<div class="card-meta-top">
    <span class="card-meta-cate"><i class="iconfont icon-aria-category"></i> <?php $this->category(' • ',true,'无'); ?></span><span class="card-meta-date"><i class="iconfont icon-aria-date"></i> <?php $this->date(); ?></span>
    <li class="card-meta-label card-meta-views card-meta-right"><i class="iconfont icon-aria-view"></i> <?php Contents::getPostView($this); ?></li>
    <li class="card-meta-label card-meta-comments card-meta-right"><i class="iconfont icon-aria-comment"></i> <?php $this->commentsNum('%d'); ?></li>
</div>

同时要把原先的卡片底部的阅读数和评论数的标签以及分割线标签、六个点标签删掉。删掉下面的代码:

<div class="card-line"></div>
<ul class="card-meta-bottom">
    <li class="card-meta-label card-meta-more"><a href="<?php $this->permalink(); ?>" title="Read More" target="_blank"><i class="iconfont icon-aria-more"></i><i class="iconfont icon-aria-more"></i></a></li>
    <li class="card-meta-label card-meta-views card-meta-right"><i class="iconfont icon-aria-view"></i> <?php Contents::getPostView($this); ?></li>
    <li class="card-meta-label card-meta-comments card-meta-right"><i class="iconfont icon-aria-comment"></i> <?php $this->commentsNum('%d'); ?></li>
    <!--li class="card-meta-label card-meta-likes"></li-->
</ul>

同样在archive.php中修改。

0x04 PC端弹出图片+滚轮缩放

PC弹窗图片源码分析

代码来源http://www.dedecmsok.com/html/n172.html

css

<style>
    #popup{
        position: fixed;
        left: 0px;
        top: 0px;
        width: 100%;
        height: 100%;
        text-align: center;
        display: none;
        z-index: 9999999;
    }
    #popup .bg{
        background-color: rgba(0,0,0,0.5);
        width: 100%;
        height: 100%;
    }
    @media \0screen\,screen\9 {
        #popup .bg{
            background-color:#000000;
            filter:Alpha(opacity=50);
            position:static;
        }
        #popup .bg img{
            position: relative;
        }
    }
    #popup img{
        margin-top: 2%;
        max-height: 90%;
    }
</style>

没太搞明白,特别时@media,暂且先放一放。

html

<div id="dedecmsok">
    <img src="111.jpg" />
    <img src="222.jpg" />
</div>
<div id="popup">
  <div class="bg">
    <img src=""/>
  </div>
</div>

第一个div内放图片,第二个div设置为弹窗图片层。

javascript

<script type="text/javascript">
    var imgs = document.getElementById("dedecmsok").getElementsByTagName("img");
    var lens = imgs.length;
    var popup = document.getElementById("popup");

    for(var i = 0; i < lens; i++){
        imgs[i].onclick = function (event){
            event = event||window.event;
            var target = document.elementFromPoint(event.clientX, event.clientY);
            showBig(target.src);
        }
    }
    popup.onclick = function (){
        popup.style.display = "none";
    }
    function showBig(src){
        popup.getElementsByTagName("img")[0].src = src;
        popup.style.display = "block";
    }
</script>

js代码必须出现在html代码的后面,因为js中要获取html中的标签并添加事件。js的事件我没有搞太明白,毕竟刚开开始接触。

js会找到iddedecmsok的内部的img标签(们)(第2行),并为其添加点击事件(第7行)。点击图片时会触发showBig事件(第10行)。showBig()会把imgsrc添加给popup(即第二个div)(第17行)。

popup标签添加点击事件,效果为不显示,即弹窗图片后再次点击会关闭图片(第13行)。

代码中引入了jquery,其实此代码不依赖于jquery。可以将之删掉。

导入jquery就是在head里插入:

<head>
    <script src="jquery-1.8.2.min.js"></script>
</head>

顺便放一个点击图片放大至父级框架最大允许尺寸,再点击恢复原状,放大图片的demo,代码来自http://www.dedecmsok.com/html/n171.html

滚轮缩放源码分析

<img id="chgImg" src="1.jpg" width="760" onmousewheel="return bigimg(this)" style="cursor:pointer" />
<script>
function bigimg(obj){
        var zoom = parseInt(obj.style.zoom,10)||100;
        zoom += event.wheelDelta / 12;
        if(zoom > 0 )
            obj.style.zoom=zoom+'%';
        return false;
    }
</script>

代码很简短。

滚轮滚动时运行函数bigimg

以上两代码整合到主题

js

/assets/js中新建imagesZoom.min.js,专门放图片缩放相关的js代码。

img

由于个人水平的缘故,我没有完全地整合到一个函数里面。由于html代码中鼠标滚轮事件onmousewheel="return bigimg(this)",如果把bigimg()`整合到zoomOnPC()中,js会找不到bigimg()`,从而报错。所以只好单独放在外面了。

html

img

post.php(文章)和page.php(独立页面)中插入上图框中代码。

框1为引入js代码

框2为PC端的弹出图片的div

框3为移动端的弹出图片的div

框4为调用js代码

css

插入到style.min.css末尾

/*电脑图片缩放*/
#popup{
    position: fixed;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
    text-align: center;
    display: none;
    z-index: 9999999;
}
#popup .bg{
    background-color: rgba(0,0,0,0.95);
    width: 100%;
    height: 100%;
}
@media \0screen\,screen\9 {
    #popup .bg{
        background-color:#000000;
        filter:Alpha(opacity=50);
        position:static;
    }
    #popup .bg img{
        position: relative;
    }
}
.center-in-center{                      /*居于页面正中间*/
    position: absolute;                 /*绝对坐标*/
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);  
}
.center-in-center img{
    max-height: 100%;
}

0x05 移动端弹出图片+双指缩放

源码的修改

代码来自 https://github.com/onlyhom/touch-scale-img

但此代码不兼容现在的移动端浏览器,需要改动三处代码。

需修改touch_scale_image.js的几处代码:

document.addEventListener("touchmove", self.eventStop, false);
改为
document.addEventListener("touchmove", self.eventStop, { passive: false });

document.removeEventListener("touchmove", self.eventStop, false);
改为
document.removeEventListener("touchmove", self.eventStop, { passive: false });

y1 = e.touches[0].pageY - document.body.scrollTop;
y2 = e.touches[1].pageY - document.body.scrollTop;
改为
y1 = e.touches[0].pageY - (document.body.scrollTop + document.documentElement.scrollTop);
y2 = e.touches[1].pageY - (document.body.scrollTop + document.documentElement.scrollTop);

第一二处改动修复了图片弹出时,没有禁止页面滚动的问题。

控制台报错

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.

解决办法1:

在touch的事件监听方法上绑定第三个参数{ passive: false },

通过传递 passive 为 false 来明确告诉浏览器:事件处理程序调用 preventDefault 来阻止默认滑动行为。

太高深了,真正的小白肯定无法理解透彻,先放一放吧,能解决问题就好。相关参考http://www.365jz.com/article/24677

第三处改动修复了因获取滚条坐标失败,而使纵坐标不是相对屏幕的坐标而是相对页面开头的坐标,使得图片缩放时,图片的坐标计算错误,从而使图片跑到屏幕外。

此问题当图片位于页面最上方时不会重现,因为此时滚条坐标为0,对图片的坐标计算无影响。所以重现时请务必不要让图片位于页面的最顶部。

document.body.scrollTopdocument.documentElement.scrollTop的作用都是获取滚条坐标,但是存在不同的兼容性。考虑到无论兼容性如何,这二者肯定只能有一个有值,所以写成两者相加的形式。

此问题的相关阅读:http://blog.haoji.me/document-body-scrolltop-is-zero.html

我在github上提交了issue,不知道作者会不会看到,毕竟是两三年前的代码了。

img

修改后的代码:

不过,这个代码(包括原代码)遇到长图(如手机截的长图)会出bug,坐标变换不合理。日后再解决吧。估计我的博客中很难会出现长图。

源码的分析

html

整体分为四部分

头部引入js和css,图片div,弹出图片的div

重点是第四部分

document.addEventListener("DOMContentLoaded", function(event){
    ImagesZoom.init({
        "elem": ".zhengwen"
    });
}, false);

我没搞明白这段代码是如何触发js的,反正就是把id='zhengwen'传进js中了。

js

(function(window, undefined){ //第1行

一个类?还是一个DOM?我真的不清楚。

var ImagesZoom = function(){}; //第17行

初始化,html中的那段代码应该就是从这里走进来的。

var imgList   = document.querySelectorAll(params.elem + " img"),
    zoomMask  = document.querySelector(".imgscale-pack"),
    zoomImg   = document.querySelector(".imgscale-pack .imgscale-img img"),
    zoomClose = document.querySelector(".imgscale-pack .imgscale-close"),
    imgSrc    = "";

拿到相应的标签

zoomClose.addEventListener("click", function(){
    self._close();
}, false);

点击右上角的关闭图片则触发自定义的_close()函数(不喜欢这个关闭图片的话,可以删除这段代码。同时css中的那段设置这个图片的代码也可以删掉,还有上面的zoomClose的那一行也可以删掉)

for(var len=imgList.length,i=0; i<len; i++){
    imgList[i].addEventListener("click", function(){
        imgSrc = this.getAttribute("src");
        zoomMask.style.cssText = "display:block";
        zoomImg.src = imgSrc;

拿到所有图片url

document.addEventListener("touchmove", self.eventStop, { passive: false });

禁止页面滚动

_close: function(){
    var self = this;
    var zoomMask  = document.querySelector(".imgscale-pack"),
        zoomImg   = document.querySelector(".imgscale-pack .imgscale-img img");

        zoomMask.style.cssText = "display:none";
        zoomImg.src = "";
        zoomImg.style.cssText = "";
        self._destroy();
        document.removeEventListener("touchmove", self.eventStop, { passive: false });
},

清空弹出图片div层的数据,取消禁用滚条。

重头戏来了:

addEventStart: function(param){

事件开始,流程为:

获取地图、可视区域等的信息,_touchstart()_touchmove()_touchend()

后面三个都是自定义的函数

_touchstart()流程为:

获取触控点数,重新初始化图片_changeData(),根据一根手指或多跟手指进行相关坐标的计算

_touchmove()的流程为:

获取触控点数,一根手指则_move(),多手指则_zoom()

_touchend()的流程为:

_close(),重新计算数据_changeData(),相关坐标的处理。

接下来定义了前面用到的那些函数:

_move()单指移动,_zoom()双指缩放

说一下_zoom()中的坐标计算

self.imgNewX = Math.round(self.startFingerX * ratio - self.startFingerX - self.newX * ratio);
self.imgNewY = Math.round((self.startFingerY * ratio - self.startFingerY)/2 - self.newY * ratio);

Math.round()取整。

ratio是缩放比例,由放大后对角线的长度/开始时图片的对角线长度得来。

self.startFingerX是双指连线中点的横坐标。

self.startFingerX * ratio - self.startFingerX即为self.startFingerX * (ratio - 1),即缩放中心点的偏移。

self.newX是原来的图片基点坐标,乘上ratio自然就是放大后的坐标了。

我个人感觉这个基点是弹出图片时的图片左上顶点。然后放大时图片左上顶点向左上方移动,横纵坐标均由0变为负值。

它这个坐标的正负很复杂,烦死我了,特别是正负的谁减谁,把我搞晕了。

放一张自己画的图,先这样吧。我果然不适合搞ACM。话说哪天有时间我去请教一下承淳大佬?

img

之后的movePos()_move()调用,用于坐标的变换,贼复杂,此处不深究。

然后是reset重置数据,被_touchend调用

refresh执行图片的移动,被movePos(间接是_move)、_zoomreset调用

末尾的getTouchDist获取多点触控要说一下

获取两个指头的横纵坐标(单指时第二组x和y为0)

计算两点的中点坐标和两点间距离。

整个流程就是:

触发ImagesZoom.init初始化。

init内部流程为:

获取各标签,设置缩放的相关系数,重置数据,(监听关闭按钮的点击),循环体。

循环体内部为:

监听每个图片的点击事件,将url传入弹出图片div层中,禁用页面滚动,计算相关坐标,调用addEventStart函数。

addEventStart函数的流程为:

获取地图、可视区域等的信息,_touchstart()_touchmove()_touchend()

源码的整合到主题

html部分的代码在前面PC端部分已经说了,此处不在赘述。

js

function zoomOnMobile(){
    document.addEventListener("DOMContentLoaded", function(event){
        ImagesZoom.init({
            "elem": ".post-content"
        });
    }, false);
}

把之前代码中的".zhengwen"类比地改成".post-content",当然css中相应的也得改喽。

调用移动端的函数。

移动端具体的函数就不粘贴了,改动不大(只添加了一句调用禁用导航栏的函数的代码)

css

也是插入到style.min.css末尾即可。

/*手机图片缩放*/
.imgscale-pack{
    width:100%;
    height:100%;
    position:fixed;
    left:0;
    top:0;
    background:rgba(0,0,0,0.8);
    display:none;
    z-index:9999;
}
.imgscale-pack .imgscale-img{
    width:100%;
    height:100%;
    position:absolute;
    left:0;
    top:0;
    overflow:hidden;
}
.imgscale-pack .imgscale-img img{
    width:100%;
    position:absolute;
    top:50%;
}

0x06 PC端、移动端图片缩放的整合

function imagesZoom(){
    if (IsPC()){
        zoomOnPC();
    }else{
        zoomOnMobile();
    }
}

html中调用此函数

function IsPC() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone","SymbianOS", "Windows Phone", "iPod"];
    var flag = true;
    for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    if(window.screen.width>=768){
        flag = true;
    }
    return flag;
}

判断是否为PC端

/*禁用网页的导航栏*/
function noMenu(){
    var menu = document.getElementById('nav-menu');
    menu.setAttribute("class", "headroom headroom--not-top headroom--not-bottom headroom--unpinned");
    console.log(menu.getAttribute("class"));
}

idnav-menu的标签的classheadroom headroom--not-top headroom--not-bottom headroom--unpinned时无导航栏,为headroom headroom--not-top headroom--not-bottom headroom--pinned时有导航栏。

document.getElementById获取idnav-menu的标签

.setAttribute()设置指定元素上的某个属性值。如果属性已经存在,则更新该值;否则,使用指定的名称和值添加一个新的属性。

console.log()控制台输出,便于调试

禁用导航栏noMenu();在PC端插入在:

function showBig(src){
    noMenu();
    popup.getElementsByTagName("img")[0].src = src;
    popup.style.display = "block";
}

在移动端插入在addEventStart的开头:

addEventStart: function(param){
    noMenu();
    var self   = this,
        params = param || {};

0x07 文字预览内容

此部分涉及php与js的交叉,比例对半分吧。

但由于没有还没有介绍过php(主要是困了),所以留待下篇文章吧。

0x08 190929更新

解决代码盒子中的图片也被弹出缩放的问题。

解决方法:分别在PC端和移动端相应的函数中,修改获取img标签的的代码。

之前是获取post-content内的全部img标签,现在改为获取post-content内的class不是link-avatar的img标签。

PC端:var imgsList = document.querySelectorAll(".post-content img:not(.link-avatar)");

移动端:var imgList = document.querySelectorAll(params.elem + " img:not(.link-avatar)"),

其中params.elem在前面的代码中被传入post-content

解释一下,document.querySelectorAll是css选择器,:not()是选择不是括号内属性。

0x09 一些零散的知识

Iconfont

Aria主题中,会看到一些图标,但是在img文件夹内并没有发现这些图标。这些图标不可能无中生有,那它们存在哪里呢?

答案是/assets/css/iconfont.css

实际上就是一个字体库,图标就是字体。

拓展阅读:https://juejin.im/entry/58d374671b69e6006b9dde70

在阿里巴巴矢量图标库中,将选中的图片加入购物车,点击下载代码,即可获得包含此css的压缩包。

img

CSS中如何嵌入php代码

css是不能嵌入PHP的。

所以我一直在想

background:url(<?php getUrl()?>)

这种css如何通过.css文件外联进html中

html如何调用外部js中得方法

img

引入外部js文件,<script>包含js函数

getElemet(s)By系列

var element = document.getElementById(id);    //没有s
var elements = document.getElementsByName(name);    //<form name="up"><input type="text"></form>
var elements = document.getElementsByClassName(names);
var elements = element.getElementsByTagName(tagName)

有无s是严格的。

获取/设置元素的属性

设置属性 .setAttribute("属性","值")
获取属性 .getAttribute("属性")

.setAttribute()设置指定元素上的某个属性值。如果属性已经存在,则更新该值;否则,使用指定的名称和值添加一个新的属性。

304跳转

如果刷新或者跳转页面,js肯定会被重新加载,但不一定会下载。

缓存可以避免资源重复下载,打开f12,Network,然后刷新,status是304的为从浏览器缓存中读取的文件,200为重新下载的文件。

缓存是现代网站提高用户体验必备的技术。

Last modification:September 9th, 2020 at 03:16 pm