写在前面

最近迁移博客到了hexo平台,在各位大佬的博客里寻找各种美化、自定义教程,偶然间发现有位大佬的博客上有个侧边栏,鼠标悬停弹出,移出鼠标自动收回,感觉很不错,非常适合容纳我喜欢的摸鱼日历图片,于是乎各种寻找解决方法,奈何这位大佬并没有做教程,所以只能去寻找替代方案

  • 这是大佬的博客

轻笑Chuckle

  • 这是收回的效果

image-20230118173923539

  • 这是展开的效果

image-20230118173935593

查询资料

经过不断的搜索->获得新的关键词->再搜索->尝试仿写->……循环一天之后,终于找到一篇很符合我需求效果的教程

鼠标滑过侧边弹出内容(JS) - tyouu - 博客园 (cnblogs.com)

image-20230118174524984

这已经非常接近我想要的效果了,只要把分享二字换成一个svg图片,然后把左面的div里面加上一个img标签,调整下高度等样式,基本就可以实现了

踩坑记录

但这个教程做的是在左侧弹出,而我想要在右侧弹出,正想着这不是只要把所有left改成right就可以了吗的时候,发现这个弹出的js方法使用了offsetLeft 这个属性来记录左侧边距,然而在js里是没有 offsetRight这个属性的,所以必须另寻他法


再使用各种console.log测试之后,我发现在弹出和收回的过程中,offsetLeft 输出的值与该组件的left属性是相等的,或许是因为本来就是从左边沿弹出,所以距离左边沿的距离其实就等于left现在的值,我豁然开朗,我直接把所有offsetLeft 都直接改成style.right不就行了

这时遇到一个不算问题的小问题,我设置了console.log不断监测移动时的right值,结果发现在开始移动的一瞬间用style.right读取出来的竟然是NaN,这就百思不得其解了,我明明设置了right样式啊,经过查询资料后发现,如果样式是写在css里面的,用style.right就是读取不出来,必须在标签上加上style属性才可以第一时间读出,不过好在也不麻烦

经过一番不复杂的改动之后,成功实现了在右侧弹出

完成效果展示

  • 收回效果

    image-20230118175413296

  • 展开效果

    image-20230118175430365

只能说非常符合我的预期,很完美

代码展示

  • html部分

使用方法是将下面的代码写进butterfly的配置文件_config.yml的inject的bottom部分

image-20230118175957170

1
<div id="moyu_sidebar" class="mysidebar" style="width:200px;height:200px;position:fixed;right:-200px;top:200px;z-index:9999"><a href="https://api.vvhan.com/api/moyu" data-fancybox="gallery" data-caption="" data-thumb="https://api.vvhan.com/api/moyu"><img class="image moyu-calendar"src="https://api.vvhan.com/api/moyu"></a><div class="sidebar-icon"><svg t="1673860832732" class="myIcon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2049"><path d="M512 85.333333c23.573333 0 42.666667 20.117333 42.666667 44.906667v763.52C554.666667 918.549333 535.573333 938.666667 512 938.666667s-42.666667-20.117333-42.666667-44.906667V130.24C469.333333 105.450667 488.426667 85.333333 512 85.333333z"fill="#8c8c8c" p-id="2050"></path></svg></div></div>
  • css部分

使用方法是在主题文件夹的source目录下新建一个custom.css,并在_config.yml的inject的head部分引入

1
<link rel="stylesheet" href="/css/custom.css"  media="defer" onload="this.media='all'">
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
.myIcon {
position: absolute;
right: -1px;
/* left: 0px; */
transform: scale(2, 2);
}

.sidebar-icon {
background: rgb(230, 230, 230);
width: 21px;
height: 60px;
position: absolute;
right: 200px;
top: 0px;
text-align: center;
line-height: 25px;
display: flex;
justify-content: center;
align-items: Center;
border-radius: 7px 0 0 7px;
}
/*深色模式下给箭头增加遮罩*/
[data-theme="dark"] .sidebar-icon {
background: rgb(44 44 44) !important;
}
  • js部分(重要)

使用方法同上,建立一个custom.js文件并在bottom里引入

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
var timer = null;
function startMove(obj, iTarget) {//iTarget为offsetLeft目标值
//开始前清除所有定时器
clearInterval(timer);
var oDiv = obj;
timer = setInterval(function () {
var myOffset = parseFloat(oDiv.style.right)
// if (isNaN(myOffset)) { myOffset = -200; console.log(1) }
//设置速度(分母越小速度越快)
var speed = (iTarget - myOffset) / 8;
//负-->向下取整,正-->向上取整(未达到目标值时speed不能为0)
//如果不取整最后会不能完全达到目标值(下面有效果图)
speed = speed < 0 ? Math.floor(speed) : Math.ceil(speed);

if (myOffset == iTarget) {
//到达目标值清除定时器
clearInterval(timer);
} else {
console.log(myOffset);

//现在的位置加上改变的距离
oDiv.style.right = myOffset + speed + 'px';
}
}, 30);
}
window.onload = f;
function f() {
oDiv = document.getElementById('moyu_sidebar');
oDiv.onmouseover = function () {
startMove(oDiv, 0);//0为目标值
}
oDiv.onmouseout = function () {
startMove(oDiv, -200);//-200为目标值
}
}

注意事项

  • 我博客设置了两个相同类型的侧边栏,为了美观,其收回的时候两个小标签是紧挨着的,弹出的时候大图肯定会有重叠,所以如果设置多个侧边栏,请使用z-index属性为他们设置上下关系,高度在上面的小工具的z轴高度要更高

  • 不知道怎么设置多个timer,现在只能存在一个timer如果在一张图片还没收回的时候移动到另一张图上使其弹出,就会让前一张图片的收回暂停,如果不多的话,我认为可以在函数里设置个让另一个对象的right值直接回到-200的代码,但本人没试

image-20230118180545538

  • 我为了让图片有点击放大的功能,使用了a标签嵌套在img外面,这个a标签是直接在文章内图片的源码里复制过来的,如果要使用这个功能,请在主题配置文件里将图片放大方法改为gallery(butterfly官方教程博客里有,我就不赘述了)