以下文章归类于 ‘技术类’

一个偶然的机会在你土鳖上刷视频刷到一个利用CSS制作一个很酷的按钮的视频,最终效果确实很酷。于是兴致勃勃的打开了作者提供的codepen,然后吧,怎么总感觉里面出来的东西和视频里的不一样。进一步看了一下,竟然是firefox在同一段代码上显示的和chrome不一样!而很显然,firefox显示的效果是正确的。

于是开始了在网上四处查找问题,四处询问的过程。很庆幸,在S1发帖后有大神帮忙解决了这个问题。

https://bbs.saraba1st.com/2b/thread-2007751-1-1.html

总结一下就是chrome在filter和transform的渲染顺序上存在问题,并没有依照要求先filter再transform的顺序来,从而导致了渲染出来的效果不对。相关内容可参考

https://drafts.csswg.org/css-transforms-2/#grouping-property-values

依照这个问题,S1的大神给出了修复的方法,增加一个div取代原来的伪类。再利用这个div和它自身的伪类分别设定transform和filter,这样一来显示效果就对了。

左半红印发表于2021.06.3rd

承接上一篇日志,当我们在使用setInterval来循环js方法时,会遇到一个bug。就是当用户切换网页后,再切换回来后会发现当前循环运行的js出现问题,比如动画速度发生变化或者动画卡住等。本篇日志就是来解决这个问题。

解决的思路首先是引入visibility,为网页添加这个事件的监听,就能知道网页是什么时候被切换或者正在看。mozilla的举例代码如下

document.addEventListener("visibilitychange", function() {
  if (document.visibilityState === 'visible') {
    backgroundMusic.play();
  } else {
    backgroundMusic.pause();
  }
});

从上面的代码可以看出,先要添加visibilitychange事件监听,再通过visibilityState的值来判断当前网页的可视状态,visibilityState的状态包括以下

  • 'visible' : 此时页面内容至少是部分可见. 即此页面在前景标签页中,并且窗口没有最小化.
  • 'hidden‘ : 此时页面对用户不可见. 即文档处于背景标签页或者窗口处于最小化状态,或者操作系统正处于 ‘锁屏状态’ .
  • 'prerender' : 页面此时正在渲染中, 因此是不可见的 (considered hidden for purposes of document.hidden). 文档只能从此状态开始,永远不能从其他值变为此状态.注意: 浏览器支持是可选的.

通过以上学习,我们来整理一下解决思路。首先当页面第一次打开后,先需要动画函数运行一遍,然后进行循环运行。随后进行网页可视状态监听,在切换网页时,要做以下事情,1、停止循环;2、所有动画停止;3、所有动画元素回到初始状态。在网页回到可视状态时,继续执行循环函数并重新启动循环。在下面代码中的border_loop()就是动画方法,也是上一篇日志中编写的动画方法。利用定义border_loop_start来控制setInterval启停。.border_top到.border_left都是动画涉及到的具体元素,用来控制动画停止和回到原来位置。

    border_loop();
    let border_loop_start = setInterval(border_loop,3300);
    document.addEventListener("visibilitychange",function () {
        if (document.visibilityState == 'hidden'){
            clearInterval(border_loop_start);
            $('.border_top').stop(true,true);
            $('.border_right').stop(true,true);
            $('.border_bottom').stop(true,true);
            $('.border_left').stop(true,true);
            $('.border_top').css({
                right: '100%',
                left: '-100px'
            });
            $('.border_left').css({
                top: '100%',
                bottom: '-40px'
            });
            $('.border_right').css({
                top: '-40px',
                bottom: '100%'
            });
            $('.border_bottom').css({
                right: '-100px',
                left: '100%'
            });
        }
        else {
            border_loop();
            border_loop_start = setInterval(border_loop,3300);
        }
    });
左半红印发表于2021.04.5th

分两种说明吧,CSS3的相对简单作为基础版,而Jquery的作为进阶版,当然进阶版的效果要更好一点。具体样式看首页的“展开网页”按钮。先说基础版吧。

基础版

也是从网上进行学习后的成果,学习代码来自:

https://github.com/code-fx/Pure-CSS3-Animated-Border

这里涉及一个CSS的基础知识,即当表层div的position为relative,里层div的position为absolute时,里层div和表层div是重复叠加在一起的。而当我们把里层div或者span的位置css(包括top,bottom,left,right)都设置成0时,里层和表层完全重叠。不仅如此,里层div可以是多个,只要position都设置为absolute就全部和表层重叠。

这时我们会发现一个情况,就是里层的div或者span其实可以用伪类来替换,这样代码更简单。

.div{
  position: relative;
}
.div:before, .div:after{
  content: '';
  position: absolute;
}

这样之后我们可以单独设置伪类的边框border和位置,再利用transition或者animation来使其运动。比如:

.div:before {
    border-top: 2px solid #00ff00;
    transition-property: all;
    transition-timing-function: linear;
    transition-duration: 2s;
    transition-delay: 0s;
    animation: border_top 2s infinite linear;
}

@keyframes border_top {
    0%{
        top: 0px;
        bottom: 0px;
        left: 0;
        right: 178px;
    }
    100%{
        top: 0px;
        bottom: 0px;
        left: 178px;
        right: 0;
    }
}

这样就可以利用div的before伪类,创建并移动了上边框border-top。animation的infinite属性是循环动画,你可以更改为其他需要的样式,比如加个:hover来达到鼠标覆盖动画的效果等等。当然我们很容易发现一个伪类只能创建一面边框,这个取决于你需要的样式,我这里需要四面边框都有各自的运动动画。所以很自然可以想到,利用after伪类再创建一面边框。可还剩下两面边框呢?很简单,在div里面套一层span或div即可,这样里层的span或者div又可以在多两个伪类。这样操作后,一个div的四面边框就都有了。做完之后,经过调整,主要是animation时间上的调整,就可以得到下面这种效果

CSS3边框

进阶版

基础版是相对简单的操作,极少代码编写就可以实现。但是这样的效果可能是你无法满意的,我们需要更加炫酷的效果,比如边框的渐变效果。那么这里就又出了问题,正如和background-image一样,如果使用border-image的话,animation是同样不会生效的,反正我这里是无法使用。所以需要和我以前的一篇文正提到的方法一样,利用jQuery来达成效果。但是立刻你会发现问题,jQuery无法选择伪类。因为伪类不是DOM元素,所以无法抓取。所以这里排除伪类的编写方式,直接写层进去即可。

<div>
    <span class="border_top"></span>
    <span class="border_right"></span>
    <span class="ui-border-element">
        <a>展开网页</a>
    </span>
    <span class="border_left"></span>
    <span class="border_bottom"></span>
</div>

和上面的操作一样,表层position是relative,里层span的position为absolute。然后给里层span加上CSS3的border-image样式,我这里很简单的使用了linear-gradient的渐变效果。接下来利用jQuery的animate()方法改变其位置即可。这里我贴出本站目前使用的function作为举例,具体样式情况各位需要根据自己的需求进行编写。同时也贴出加了渐变特效后的边框动画作为对比。

jquery边框
function border_loop() {
	$('.border_top').animate({
		right:"0px",
		left:'50px'
	}, 2000, 'linear', function () {
		$('.border_right').animate({
			top:'100%',
			bottom:'-40px'
		},2000,'linear',function () {
			$('.border_right').css({
				top: '-40px',
				bottom: '100%'
			});
		});
		$('.border_top').animate({
			right:"-100px",
			left:'100%'
		},500,'linear',function () {
			$('.border_top').css({
				right: '100%',
				left: '-100px'
			});
		});
	});

	$('.border_bottom').animate({
		right:"50px",
		left:'0px'
	}, 2000, 'linear', function () {
		$('.border_left').animate({
			top:'-40px',
			bottom:'100%'
		},2000,'linear',function () {
			$('.border_left').css({
				top: '100%',
				bottom: '-40px'
			});
		});
		$('.border_bottom').animate({
			right:"100%",
			left:'-100px'
		},500,'linear',function () {
			$('.border_bottom').css({
				right: '-100px',
				left: '100%'
			});
		});
	});
}

直接用setInterval()方法调用循环播放即可,循环的时间根据自己的情况慢慢调,说实话我非常不喜欢setInterval这个方法,用起来很不靠谱。实际上如用户切换网页的话,这个动画会出现问题。不过这个不是现在可以解决的问题了,以后再说。

左半红印发表于2021.04.4th

准确来说是动画过程消失,有开头有结尾,但是看不到中间过程。这是我今天发现的一个问题。问题并不在与jquery而是在网页代码本身。其实在原理上我并不知道jquery是如何实现动画效果的,这也导致了这个问题的出现。下面我来描述一下这个问题,算做一次笔记防止以后再发。

在有些时候,我们希望网页中的几个元素成为一个整体进行jquery动画。比如

<div id="div1">
<div id="div2">...</div>
<div id="div3">...</div>
...
</div>

这里我们懒得把div2和div3单独做动画,也没必要。我们直接用jquery做div1的动画,这样被包裹的div2和div3会形成一个整体随着div1的动画来展现。这样做一般来说是没问题的,但有些动画需要div1的尺寸。什么意思呢?一般来说当div1包裹div2和div3的时候,div1的尺寸和div2+div3。但这并不绝对,比如当你设定div2和div3的css中float时,如果此时div1没有设定float你会发现div1的尺寸并不是div2+div3。OK,我相信会写网页代码的人应该都很熟悉这个特点。当div1里的所有元素全部都float的话,此时div1的尺寸是0。然后我们再对div1做jquery动画时,你就会发现有些动画对尺寸为0的元素会消失。这就是这个问题的由来。

总结一下就是用jquery动画有个原则,就是我们让jquery作用的元素一定要有尺寸。当然最好尺寸和所包含元素的尺寸之和一致,这样动画的表现最为准确。

左半红印发表于2020.08.3rd

5月7日更新,时间校准后依然还会有500报错,下方的方法是无效的。目前可知最简单的解决方法就是重启一下客户端。

这是我自己架设VPN服务器后遇到的问题,不好说是否已经解决,只是暂时OK了,需要在日后使用中继续观察。以下是报错信息。

500 Internal Privoxy Error
Privoxy encountered an error while processing your request:

Could not load template file no-server-data or one of its included components.

Please contact your proxy administrator.

If you are the proxy administrator, please put the required file(s)in the (confdir)/templates directory. The location of the (confdir) directory is specified in the main Privoxy config file. (It’s typically the Privoxy install directory).

这个问题并不是我一个人遇到的,实际上网上我看到有不少人都遇到了。但解决方法几乎都不靠谱。因为基本上碰到这个问题的人都没有搞清楚到底为什么会产生这个错误。一直到最后我找到了这篇日志

https://www.obodizhu.com/online/v2ray-fix-500-internal-privoxy-error.html

感觉上说的挺靠谱的,问题出自V2RAY对服务器和客户端时间匹配要求较高,所以一旦出现使用端和服务器的本地时间发生较大差异时会报这个错误。依照这个理论解决方法其实不难,也就是同步客户端和服务器的时间同步网络时间即可。本地的时间同步我就不写了,很简单。我接下来遇到的问题是我的服务器装的ubuntu系统,那么咋个同步网络时间呢。首先,安装ntp,注意不同linux的安装方式不一样,ubuntu的方式是

apt-get install ntp

在安装的过程中仔细看一下就会发现,ubuntu本身自带这个,所谓安装不过是给ntp升了个级。OK,因为我是这方面小白,所以还是解释一个ntp是个啥,我直接引用了。

网络时间协议,英文名称:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议

升级后ntp后开始同步时间,同步对象是ntp时间服务器

ntpdate pool.ntp.org

可惜报错

the NTP socket is in use, exiting

网上查了一下,大部分都说是因为ntp的默认socket号是123,而ntp本身正在占用这个socket号,所以无法同步。解决方法就是暂时停用ntp服务

service ntpd stop

但神奇的是我这里又报错了

Failed to stop ntpd.service: Unit ntpd.service not loaded.

其实到最后我才发现,我这里要停止的服务应该是ntp,可为什么网上都写着ntpd呢?那当我输入停止ntpd的命令时肯定是报错啊。不过当时我并没有太在意这点,而是找了其他方法来关闭ntp,就是kill PID。利用下面这个命令查看默认端口123的占用者是谁。

lsof -i:123

会得到这个结果

COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
ntpd    20150  ntp   16u  IPv4 48022499      0t0  UDP localhost.localdomain:ntp 
ntpd    20150  ntp   17u  IPv4 48022501      0t0  UDP 172.19.0.10:ntp 
ntpd    20150  ntp   18u  IPv6 48022503      0t0  UDP ip6-localhost:ntp 
ntpd    20150  ntp   19u  IPv6 48022507      0t0  UDP [fe80::5054:ff:fea5:7d38]:ntp

诶?名称是叫ntpd啊?!不管了,这个名称不对。kill对应的PID即可。然后重新nptdate校准时间。

kill -9 20150

最后为了验证这货到底叫啥,我试验了一下

service ntp stop

成功!所以不管别的系统里什么情况,至少在ubuntu里,ntp就叫ntp。

左半红印发表于2020.05.4th

在CSS3中,有个新属性是animation,当然了如果你了解的话,transition也是一样的道理。这两个CSS3中的新属性可以让元素在页面中完成你想要的一些动画效果。但是,background-image不支持这两个属性。说实话这很扯淡,background-image也是CSS3中新增的属性,自己不支持自己还行?!

https://www.w3.org/TR/css-backgrounds-3/#the-background-image

W3有明确的显示Animatable:no,但就是不说为啥。

Name:	background-image
Value:	<bg-image>#
Initial:	none
Applies to:	all elements
Inherited:	no
Percentages:	N/A
Media:	visual
Computed value:	as specified, but with URIs made absolute
Animatable:	no

这个问题网上有个很麻烦的方法,简单说就是用backgrond-position属性,把整个动画过程切成N帧,然后把这N帧拼接成一张图,再利用CSS3定位这张图中不同位置的帧来造成动画的效果。超级麻烦好吗,先不说这个方法还要利用插件或者第三方工具来拼图,录制动画成N帧就没法弄。算了,自己来。

这里我用自己的实际情况来说明,本站的文章标题就是这个效果的完成品,鼠标移进移出的特效。红色渐变效果是用background-image中的渐变(background-image: linear-gradien)效果实现的。我无非需要它淡入淡出而已,所以很自然的可以想到利用jquery或者jqueryui,后者更方便,一个toggle方法既可以满足。

而需要调整的其实是html和css。首先是HTML,文章标题是一个简单的a链接,a后面接一个div作为背景。CSS如下:

#title a {
    z-index: 10;
    position: relative;
}

.title_background{
    background-image: linear-gradient(to right, rgba(88, 199, 238, 0), rgba(255, 0, 0, 0.5), rgba(88, 199, 238, 0));
    height: 40px;
    z-index: 0;
    position: relative;
    top: -40px;
    display: none;
}

需要注意的是div的position要设置成relative,这个属性的意义在于依据父元素定位。所以通过设置top或者left为一个负值,就可以使这两个元素重叠。我们发现a链接的属性也有position:relative,这个目的在于使z-index生效。我们希望a链接能够显示在div的上层。请注意,z-index是在position设置除了static以外的属性下才能生效的,而position的默认属性就是static,所以必须给position一个其他的设定值,这里卡了我很久。

还有一点需要说明,我们能不能将背景div放在a链接前面呢?看起来没啥区别,只是调整位置的变成了a链接而已,但是在下面的jquery动画中会出现问题,toggle方法的本质其实是将动画层的display属性最终设置为none或者block,但是背景div的display属性会影响到a链接的position定位,所以这导致在执行jquery动画后a链接的位置发生偏移,这不是我想要的。

然后是js代码,这里不多讲了,懂得自然懂。

function title_hover() {
	let title_button = document.querySelectorAll(".title_content");
	for(let i =0; i < title_button.length; i++){
		$(title_button[i]).mouseenter(function () {
			let title_b = this.querySelector('.title_background');
			$(title_b).toggle("fade",500);
		})
		$(title_button[i]).mouseleave(function () {
			let title_b = this.querySelector('.title_background');
			$(title_b).toggle("fade",500);
		})
	}
}

其中的title_content是用于包裹a链接和背景div的div,主要用于判断鼠标进出的边界。

左半红印发表于2020.04.19th