最近一周一直在改博客主题的代码,荒废了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展示
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会找到id
为dedecmsok
的内部的img
标签(们)(第2行),并为其添加点击事件(第7行)。点击图片时会触发showBig
事件(第10行)。showBig()
会把img
的src
添加给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代码。
由于个人水平的缘故,我没有完全地整合到一个函数里面。由于html代码中鼠标滚轮事件onmousewheel="return bigimg(this)"
,如果把bigimg()
`整合到zoomOnPC()中,js会找不到
bigimg()`,从而报错。所以只好单独放在外面了。
html
在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.scrollTop
和 document.documentElement.scrollTop
的作用都是获取滚条坐标,但是存在不同的兼容性。考虑到无论兼容性如何,这二者肯定只能有一个有值,所以写成两者相加的形式。
此问题的相关阅读:http://blog.haoji.me/document-body-scrolltop-is-zero.html
我在github上提交了issue,不知道作者会不会看到,毕竟是两三年前的代码了。
修改后的代码:
不过,这个代码(包括原代码)遇到长图(如手机截的长图)会出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。话说哪天有时间我去请教一下承淳大佬?
之后的movePos()
被_move()
调用,用于坐标的变换,贼复杂,此处不深究。
然后是reset
重置数据,被_touchend
调用
refresh
执行图片的移动,被movePos
(间接是_move
)、_zoom
、reset
调用
末尾的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"));
}
id
为nav-menu
的标签的class
为headroom headroom--not-top headroom--not-bottom headroom--unpinned
时无导航栏,为headroom headroom--not-top headroom--not-bottom headroom--pinned
时有导航栏。
document.getElementById
获取id
为nav-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的压缩包。
CSS中如何嵌入php代码
css是不能嵌入PHP的。
所以我一直在想
background:url(<?php getUrl()?>)
这种css如何通过.css文件外联进html中
html如何调用外部js中得方法
引入外部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为重新下载的文件。
缓存是现代网站提高用户体验必备的技术。