如何开发一个用户脚本系列(4)——脚本二:一个返回顶部和到达底部的按钮


在这篇文章中,我们将一起学习脚本 一个返回顶部和到达底部的按钮 的开发。在正式开始之前,先说一下我认为开发脚本应该遵循的两个准则:

  • 功能实现。当你决定要开发一个脚本的时候,你肯定清楚你的脚本要实现什么功能,只有你的脚本实现了你所描述的功能,才会有更多的人安装使用,才会有更多的人给你好评;
  • 样式实现。什么叫样式实现?就是你在目标网站中添加的元素,要尽量与原网站的配色,样式相一致。这一项是非必须的,但我认为是非常重要的。你想想,如果原网站整体是蓝色,而你添加的按钮是红色,那该有多突兀,有多丑,虽然你的按钮确实突出了,但别人一看就是山寨,看着会很不舒服。而如果你的按钮也用它网站的颜色,这样就会跟原网站已有的元素契合,整体特别自然,做到以假乱真的效果。你的脚本让别人用的舒服,别人才更愿意给你好评。

需求分析

我们在平时上网的时候会发现,很多网站在网站右下角提供了一个返回顶部的按钮,当用户向下浏览网页时,该按钮就会出现,然后点击按钮网页就会滚动回到顶部,非常方便。但是有一部分网页没有提供这种按钮,如果需要返回网页顶部,就需要自己一点一点滚动,很不方便。同时,大多数网页也并没有提供一键到达网页底部的功能。有人可能会问,我们浏览网页就是从上往下浏览,为什么还需要一键到达网页底部?你要知道,你不需要不代表别人不需要,有些网页底部有评论,或者有网站的一些入口,而别人并不想看网页中的内容,只想赶快到达网页底部看他想看的内容,这时候,这个按钮就能提供方便。所以今天要做的,就是在网页中添加一个按钮,初始状态下,该按钮箭头向下,当用户点击后,网页就会快速滚动到底部,然后按钮箭头变为向上,用户再次点击后,网页又会快速滚动到顶部。而用户在浏览网页的过程中,按钮会根据用户的浏览方向,自动变换箭头方向,非常智能。比如说,用户向下浏览网页,按钮箭头会向下,用户向上浏览网页,按钮箭头会向上。

功能实现

要实现上面的功能,我们首先需要两张按钮箭头的图片。这里感谢为我切图的 UI 小姐姐,我觉得她切的图真漂亮。我把图片放在我的 coding.net 仓库,当然你放在任何一个可以公开访问到的地方都可以,然后我们在脚本开头用 @resource 引入我们需要用到的图片。而我们在代码中如果要使用图片,还需要脚本管理器的 GM_getResourceURL() 函数,所以我们使用 @grant 声明。我们希望我们的按钮在所有网站都生效,所以我们用 @match 匹配所有网站。在脚本编写过程中会用到 jQuery,所以我们使用 @require 引入 jQuery 库。

// @resource    up_button_icon    https://coding.net/u/mofiter/p/public_files/git/raw/master/back_to_top_button.png
// @resource down_button_icon https://coding.net/u/mofiter/p/public_files/git/raw/master/go_to_bottom_button.png
// @grant GM_getResourceURL
// @match *://*
// @require https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js

准备工作做完之后,我们开始编写代码。我们希望我们的按钮固定在网页右下角,距离底部 50px,距离右边 30px,按钮宽和高都为 35px,按钮默认显示向下的箭头,按钮初始化透明度为 0.5,当我们将鼠标移入按钮时,按钮透明度变为 0.8,有一个明暗变化使用体验更好。

var opacityMouseLeave = 0.5; //当鼠标不在按钮上时,按钮的不透明度,从 0.0(完全透明)到 1.0(完全不透明)
var opacityMouseEnter = 0.8; //当鼠标在按钮上时,按钮的不透明度,从 0.0(完全透明)到 1.0(完全不透明)
var goTopBottomButton = document.createElement("div");
goTopBottomButton.className = "goTopBottomButton";
goTopBottomButton.innerHTML = "<img class='toggleButton' style='width:35px;height:35px;display:block;cursor:pointer;'></img>"; //图片的宽和高可修改,原始图片宽高均为 40px
goTopBottomButton.style.position = "fixed"; // 按钮位置固定
goTopBottomButton.style.zIndex = 10000; // 按钮堆叠顺序,数字越大,越显示在前面
goTopBottomButton.style.bottom = "50px"; //距离网页底部 50px
goTopBottomButton.style.right = "30px"; //距离网页右边 30px
var toggleButton = goTopBottomButton.lastChild;
toggleButton.style.opacity = opacityMouseLeave; //按钮初始不透明度
toggleButton.src = GM_getResourceURL("down_button_icon"); //按钮初始显示向下的图片
document.getElementsByTagName("body")[0].appendChild(goTopBottomButton); // 将按钮添加到网页中

现在按钮已经可以正常加载出来了,下面我们进行事件的处理。为了让用户体验更好,我们添加了这样一个功能。当鼠标放在按钮上时,页面会根据当前浏览方向自动滚动,这个功能是否开启由变量 canScrollMouseOver 控制。当 canScrollMouseOver 为 true 时,我们判断当前网页滚动方向,如果用户在向下浏览网页,网页将自动向下滚动,当用户在向上浏览网页时,网页将自动向上滚动。这个滚动速度较慢,目的是为了让用户可以看得清。而当用户点击按钮时,网页将直接滚动到底部或顶部,这个滚动速度较快。当鼠标移出按钮时,自动滚动将会停止。在向下滚动的时候,有可能会遇到这样的问题。现在部分网页采用动态加载数据的方式,当前网页的所有数据并不会在网页初次加载的时候全部请求,而是会在用户向下浏览网页的时候再去请求数据,这样就会导致网页高度发生变化,为了避免当点击按钮后出现无休止的向下滚动,所以需要添加变量来记录网页动态加载数据的次数,如果次数超过了我们设置的最大次数,就应该停止向下滚动并告知用户。

var $ = window.$;
var canScrollMouseOver = false; //当鼠标在按钮上,但未点击时,页面能否自动滚动,true 为可以自动滚动,false 为不能自动滚动
var clickScrollTime = 500; //点击按钮时,网页滚动到顶部或底部需要的时间,单位是毫秒
var needScrollTime; //网页可以自动滚动时,滚动需要的时间,由网页高度计算得出,这样不同网页都会匀速滚动
var isClicked = false; //按钮是否被点击
var initialHeight = 0; //网页向底部滚动时,需要滚动的距离
var scrollDirection = "down"; //网页滚动方向,down 为向下,up 为向上
var loadTimes = 0; //网页中动态增加数据的次数
var maxLoadTimes = 10; //最大的动态增加数据的次数,如果动态增加数据的次数超过这个值,则说明当前网页不适合执行此脚本,建议将其加入排除的网站当中
toggleButton.addEventListener("mouseenter",function() { //鼠标移入时不透明度改变,如果 canScrollMouseOver 为 true,则网页可以自动滚动
isClicked = false;
if (canScrollMouseOver) {
if (scrollDirection == "up") {
needScrollTime = getScrollTop() * 10;
$('html,body').animate({scrollTop:'0px'},needScrollTime);
} else {
initialHeight = $(document).height();
var restHeight = $(document).height() - getScrollTop();
needScrollTime = restHeight * 10;
$('html,body').animate({scrollTop:initialHeight},needScrollTime,continueToBottom);
}
}
toggleButton.style.opacity = opacityMouseEnter;
})
toggleButton.addEventListener("mouseleave",function() { //鼠标移出时不透明度改变,如果 canScrollMouseOver 为 true,并且按钮未被点击,停止网页自动滚动的动画
if (canScrollMouseOver && !isClicked) {
$('html,body').stop();
}
toggleButton.style.opacity = opacityMouseLeave;
})
toggleButton.addEventListener("click",function() { //点击按钮时,网页滚动到顶部或底部
isClicked = true;
if (canScrollMouseOver) {
$('html,body').stop();
}
if (scrollDirection == "up") {
$('html,body').animate({scrollTop:'0px'},clickScrollTime);
} else {
initialHeight = $(document).height();
$('html,body').animate({scrollTop:initialHeight},clickScrollTime,continueToBottom);
}
})
function getScrollTop() { //获取垂直方向滑动距离
var scrollTop = 0;
if (document.documentElement && document.documentElement.scrollTop) {
scrollTop = document.documentElement.scrollTop;
} else if (document.body) {
scrollTop = document.body.scrollTop;
}
return scrollTop;
}
function continueToBottom() { //判断页面是否继续下滑(主要是为了处理网页动态增加数据导致网页高度变化的情况)
var currentHeight = $(document).height();
if (initialHeight != currentHeight) {
if (loadTimes >= maxLoadTimes) {
$('html,body').stop();
alert(" 本网站有太多的异步请求,不适合执行脚本《" + GM_info.script.name + "》,建议加入排除网站当中,具体方法请查看脚本主页");
loadTimes = 0;
return;
}
loadTimes ++;
initialHeight = currentHeight;
$('html,body').animate({scrollTop:initialHeight},1000,continueToBottom);
}
}

现在当你将鼠标放在按钮上和从按钮上移出时,按钮透明度会变化。并且,如果你的变量 canScrollMouseOver 为 true,那么网页也会自动向下滚动。下面我们要对网页滚动方向进行监听,如果网页向下滚动,或者网页滚动到了顶部,则按钮显示向下箭头,如果网页向上滚动,或者网页滚动到了底部,则按钮显示向上箭头。

var scrollAction = 'undefined';
document.onscroll = function() {
if (scrollAction == 'undefined') {
scrollAction = window.pageYOffset;
}
var diffY = scrollAction - window.pageYOffset;
scrollAction = window.pageYOffset;
if (diffY < 0) {
changeDirection("down");
} else if (diffY > 0) {
changeDirection("up");
}
if (getScrollTop() == 0) {
changeDirection("down");
}
if (getScrollTop() + $(window).height() >= $(document).height()) {
changeDirection("up");
}
}
function changeDirection(direction) { //改变按钮方向
scrollDirection = direction;
toggleButton.src = GM_getResourceURL(direction + "_button_icon");
}

至此,我们就完成了这个脚本的开发,至于发布脚本的流程可以参考上一篇文章 如何开发一个用户脚本系列(3)——脚本一:百度首页和搜索页面添加 Google 搜索框

总结

本文对脚本 一个返回顶部和到达底部的按钮 的开发过程进行了介绍,如果还有疑问,可以留言,下一篇文章将对脚本 网易云课堂下载助手 的开发过程进行介绍。想了解更多技术知识,可以关注“极课助手”公众号。
极课助手公众号


 评论