学习记录第3波,前两波可访问学习记录专栏了解。
第9周 2.26-3.3
1.浏览器音频上限
浏览器对可播放音频资源是有限制的,具体多少忘记了,700多个还是900多个的。这周在调试AI配音的时候,遇到了之前反馈过的,但是自己一直没能复现的没有声音的问题......突然灵光一闪,会不会是因为音频资源超出上限,所以之后的音频没声音?
于是,每次应用新的声音,我都将之前创建的播放实例全部卸载,一番修改下来,至少自己是没再复现,同事也没有再出现没有声音的问题,再观察观察,感觉......这个问题的解决八九不离十了。
2.音频倍速的问题
视频合成有个倍速合成选项,于是,其中的声音要需要0.5倍速,或者2倍速这种,一开始我以为这个需求很简单,跟视频帧一样,0.5倍速就两两重复,2倍速就间歇掉帧,结果却非如此,虽然这么处理之后的音频时长和速率符合了,但是音调也跟着变了。
众所周知,声音其实就是一种波,在数学上常常用三角函数表示。播放速率变快,也就意味着波形越陡峭,自然音调也就越高。下面这个GIF动图很好地示意了这一点:
而要解决此问题,需要特殊的算法,让波形变窄的同时音调也保持不变,这里还是很考验数学功底的,业界对于此问题已经有不少解决方案,大家有兴趣可以访问"不改变音调情况下Audio音频的倍速合成JS实现"一文。
第10周 3.4-3.10
- Dialog组件的更新
当初Dialog组件开发的时候,Safari浏览器还没支持原生的<dialog>
元素,所以实现的方法比较保守,黑色蒙层就是<dialog>
元素,而弹框内容使用div元素模拟。
然而,如今,<dialog>
元素所有现代浏览器都支持,显然,之前的策略就显得过时了。
这次项目的UI组件库改用LuLu UI,然后发现Dialog组件由于之前的设计,导致<dialog>
元素的DOM层级会发生变化。
在传统的Web项目中,这种用户用户是无感知的,并没有任何问题。
但是对于Vue/React这类数据驱动DOM渲染的项目,DOM层级随意变动是会影响之后的虚拟DOM渲染的。
于是,趁着这个机会,对Dialog组件进行了较大的改动,包括蒙层就是<dialog>
原生的蒙层,弹框的显示以showModal()方法为主,对于不支持<dialog>
的浏览器,蒙层使用outline模拟,采用优雅降级的策略。
很棒,组件的迭代离不开在实际项目中的应用。
- docker中视频合成的音频编码
浏览器版本的自动化合成在本地puppeteer中都是好的,可一旦打包到docker环境中,音频编码和解码就相继出现问题。
先说解码,此问题出现是一开始使用的docker镜像有问题,折腾了好久,换成puppeteer官方提供的镜像才解决,这个是吃了没有经验的亏。
编码失败,则是编码格式不对,一开始的格式是codec:"mp4a.40.2",后来换成codec:"opus"才好。
第11周 3.11-3.17
Chrome和Safari浏览器现在已经支持让屏幕唤醒锁定,也就是只要页面打开,就不会息屏或者出现屏保。
全名叫做Screen Wake Lock API,使用也比较简单,要想屏幕保持唤起状态,很简单,一行代码的事情:
navigator.wakeLock.request('screen');
结束了,就这么简单。
当然,还有很多释放与容错处理的细节,这里不展开,有兴趣可以参考我整理的这篇文章:"Web网页也能阻止息屏了"。
第12周 3.18-3.24
这周学习了一个新的CSS属性,名叫initial-letter,其作用是设置首字母的可以占据多少行文本的高度。
是这样的,在英文排版中,经常会有首字母放大的效果,在过去,都是通过::first-letter伪元素和font-size属性实现。
p::first-letter { font-size: 350%;}
但是这个实现有个问题,那就是首字母的排版很糟糕,由于只能占据一行内联元素的高度,因此,要么上面不对齐,要么下面空白间隙大,如下图所示:
而initial-letter属性可以很好地解决此排版问题,例如:
p::first-letter { initial-letter:3 }
详见我整理的这篇文章:"CSS initial-letter属性,嗯......也就这样吧"
第13周 3.25-3.31
年前有介绍CSS @scope规则,可以实现CSS的选择器内外嵌套,简化选择器的书写,最近发现,几乎同一时间,现代浏览器还支持了专门用来嵌套书写的CSS Nesting语法,借鉴自Sass/Less/Stylus等预编译语言,和@scope(nav)的语法极为相似,所实现的效果也是一样的
css
nav {
ul { list-style: none; padding:0; margin:0; }
li { display: inline-block; }
}
这就让我陷入了深深的沉思......为什么要弄两套规则如此相似的东西呢?
于是,我就好好对比来下CSS @scope和CSS Nesting,详见我整理的"CSS Nesting嵌套与@scope规则也太雷同了吧?"这篇文章。
第14周 4.1-4.7
难得的假期,放空自己,慎思而独省,自是学习。
第15周 4.8-4.14
本周的学习主要集中在SVG的滤镜元素的学习上。
a. <feBlend>
元素
<feBlend>
元素可以实现SVG中的混合模式效果,其支持的混合模式和CSS mix-blend-mode
混合模式支持的属性值是一样的。
具体如何使用,可以参见我整理的这篇文章:"SVG滤镜系列之搞懂feBlend元素"
b. feGaussianBlur和feDropShadow
<feGaussianBlur>
可以在SVG中实现高斯模糊效果,<feDropShadow>
元素可以实现投影效果,这算是SVG滤镜中学习难度最低的元素了,因为可以独立使用产生效果,从中可以看到CSS模糊和投影滤镜语法的影子。
具体可以参见我整理的这篇文章:"学习SVG滤镜feGaussianBlur和feDropShadow"
第16周 4.15-4.21
本周学习最大收获就是Node.js层面对视频缩略图的处理,之前这块并没有玩过。
好在,一番研究与学习下来,搞定了需求。
使用node-fluent-ffmpeg,核心执行代码如下所示:
其中:
-
fps()方法可以改变视频的帧率
-
size('128x?')表示改变原始视频的尺寸,宽度为128px像素,高度按照原始视频比例自动计算
-
thumb-%04d.jpg中的%04d表示图片序列安装0000.jpg、0001.jpg这种四位补全的方式命名(保证排序)
最后,获取的缩略图使用工具打包为ZIP格式,再上传到cos存储,这样前端就能使用了。
详见我整理的这篇文章:"node环境中使用fluent-ffmpeg每隔一秒视频截图"。
第17周 4.22-4.28
上周又温习了一遍SVG中的贝塞尔曲线指令,然后手搓了一个下图所示的箭头效果:
其实还挺简单的,就10个标准指令,外加1个非标准的,见下表:
然后在脑中脑补大致的坐标点的位置,和最终的曲线效果,然后出现效果后,再微调坐标就好了。
关键是要知道二次贝塞尔曲线和三次贝塞尔曲线坐标和最终效果的关系,这个设计师比较熟悉,我早年PS钢笔工具经常玩,所以,有了指令和坐标,脑中自然就有图形了,不知道别人是不是也是这样。
详见"深度掌握SVG路径贝塞尔曲线指令"一文。
还没完。
最终的SVG图形需要适用于多种尺寸场景下,而默认情况下,缩放SVG会让描边变细。此时,就轮到vector-effect属性出马了。
详见"CSS vector-effect与SVG stroke描边缩放"一文。
第18周 4.29-5.5
充分享受假期是为了接下来更高效的学习。😜
第19周 5.6-5.12
发现了一种适用于各种背景环境的文字变瘦方法,此方法居然无需用到任何与文字相关的CSS属性。
就是使用SVG feMorphology滤镜。
使用还是相当简单的,页面中嵌入一段SVG代码,然后就可以使用filter属性实现了。
详见我整理的这篇文章:"不使用font-weight等CSS实现文字变瘦或变胖效果"。
第20周 5.13-5.19
本周研究了下如何用比较简单的方法在Web上实现图片的马赛克效果。
一种是SVG滤镜方法,插入一段SVG代码就可以了,实现效果示意:
相关代码和效果可以访问这里进行了解。
还有一种方法是使用CSS的image-rendering:pixelated
声明,此声明可以让小图放大显示的时候,使用像素化算法,所呈现的效果就非常接近于马赛克效果。如下图所示:
相关代码和效果可以访问这里进行了解。
至于两种方法实现的原理和细节,大家有兴趣可以参见我整理的这篇文章:"如何用简单的Web方法实现图片的马赛克效果"。
第21周 5.20-5.26
上周的学习时间留给给新书写序言和录制CSS精讲视频第2期了。
新书关于HTML的,原名是《你并不精通HTML》,但......怎么讲呢,国有企业天然保守,我觉得非常好的名字,不断Battle之下,还是不行,真的没办法,也不提前确定好,要上架了,觉得书名不行。
现在暂定《HTML并不简单》,序言是免费对外的,有兴趣的,可以访问这里看看。
第22周 5.27-6.2
本周继续SVG滤镜的学习,这次的学习对应是<feMerge>
和<feMergeNode>
滤镜元素,这两个基本滤镜有个非常经典的应用,就是可以让原始输入图形double显示,另外复制的图像可以设置模糊、透明度等都是可以的。
例如下图所示的按钮投影效果,连按钮中的文字也一起复制了。
实现很简单,首先,在页面任意位置复制如下所示的SVG代码:
然后给按钮(假设有类名.filter)设置filter属性就好了。
.filter { filter: url(#offsetOpacity); }
更完整更深入的知识参见我整理的这篇文章:"记一次技术交流,feMerge滤镜复制任意DOM元素样式"。
第23周 6.3-6.9
HTML5 <dialog>
元素使用showModal()
显示的时候,自动层级最高,自动居中,自动有黑色蒙层,明显就比使用show()方法或者设置open属性显示弹框要好。于是,就在前段时间,对于LuLu UI Edge主题的弹框组件,我就进行了大刀阔斧的修改,让弹框的显示均采用showModal()方法(通过劫持open属性实现)。
修改完了自我感觉良好(见第10周的学习),但是真的实践之后,痛苦的事情来了,由于dialog元素顶层了,因此,自定义的验证提示,浮动定位,toast提示等,全都无法显示,因为这些组件的元素创建都是在body元素下的,由于弹框层级顶级,因此,这些组件样式被覆盖地死死的,用户根本就看不到。
目前靠谱的方法就是让toast元素,浮层元素全都append到<dialog>
元素中,这实在是太麻烦了。
于是,我开始另寻他法,决定以毒攻毒,也就是所有的提示元素,我也使用顶层特性实现,那就不用担心被覆盖的问题了。
所以,需要有让普通元素变成顶层元素的方法。
如何创建顶层元素?
目前来说,创建顶层元素有下面这几种方法:
-
元素全屏显示,可以通过调用
Element.requestFullscreen()
方法实现; -
上面提到的使用
showModal()
方法显示的<dialog>
元素 -
使用
HTMLElement.showPopover()
方法显示的弹出层元素。
其中,第三个,也就是借助popover属性和showPopover()方法是可行的,做了个简易的演示页面,果然可以。
不过popover属性Safari去年才开始支持,真正应用还需要再等1年左右。
期待后续的LuLu UI了。
更多关于顶层元素的知识,可以参见此文:"聊聊Top Layer顶层特性的隐患与实践"
第24周 6.10-6.16
本周学习了锚点定位,这是个非常强大的特性,可以让我们可以使用纯CSS实现绝对定位元素A相对于任意锚点元素B的定位效果了,过去那些使用JS实现的浮层效果均有了更好的实现方式。
举个简单的案例。
一个按钮,一张图片。在过去,希望点击按钮让图片在按钮的下边缘对齐显示,要么有DOM结构限制,要么借助JS。
现在,直接CSS就可以了,DOM结构可以非常随意。例如有如下HTML和CSS代码:
我们就可以预想的定位效果了,不仅如此,这种定位效果是实时的,也就是我们改变按钮的位置,下面的图片会自动跟随。
我专门做了个演示页面,您可以狠狠地点击这里:CSS锚点定位基本效果demo
本周继续学习其更加深入的 语法与应用。
第25周 6.17-6.23
本周继续锚点定位的学习。
锚点定位是没有center-center这种关系的定位的,但不影响居中定位效果的实现。
因为:
-
一来我们是可以使用transform偏移模拟;
-
二是有新的CSS特性专门实现锚点居中定位;
-
三则使用inset-area属性。
1. transform偏移模拟
例如有一个按钮和一张绝对定位图片,要想图片的水平中心和按钮的水平中心对齐,可以设置图片的left和锚点的center对齐,然后transform位移一半的图片宽度就可以了,CSS代码示意:
效果示意:
2. 全新的对齐属性值anchor-center
anchor-center是justify-self、align-self、justify-items和align-items等属性新支持的一个值,专门用在锚点定位中,可以让元素居中对齐显示,例如还是上面同样的HTML,则CSS这样就可以水平居中了。
3. inset-area属性实现
锚点定位的定位除了使用浮层元素的定位属性(left/bottom/left/right)实现外,还可以在目标元素上使用inset-area属性进行布局,这种新的布局机制有个新名称,叫做"边衬区布局"。
例如,本例,给按钮设置inset-area: bottom就可以。
CSS锚点定位还有其他若干属性和特性,本周继续学习。
第26周 6.24-6.30
继续CSS锚点API的学习
首先,anchor-size()
函数可以让浮层元素和锚点元素的尺寸产生关联。
例如,希望浮层元素的宽度永远和锚点元素保持一致,则可以设置:
less
width: anchor-size(width)
其次,我们可以使用@position-try
规则以及position-try-options
属性增加锚点定位的候补定位位置。
也可以直接使用position-try-options属性的关键字值实现一些简单的边界调整效果,例如:
最后,新设计了个position-visibility属性,可以控制锚点定位元素和滚动边界的显隐关系。下图是值no-overflow的表现效果:
更多更完整的内容,参见这篇大作:"告别JS浮层,全新的CSS Anchor Positioning锚点定位API���
transition-behavior和@starting-style规则的学习
这两个东西其实都是解决类似问题的,就是元素display none显隐的transition
动画效果的实现。
transition-behavior: allow-discrete
可以让元素display:none
隐藏的时候依然有淡出效果,@starting-style
规则则可以让display:none
元素显示的时候有淡入效果。
具体参见我整理的这篇文章:"CSS transition-behavior让display none也有动画效果"
第27周 7.1-7.7
最近做的中台项目因为用了不少新特性,而有些同事的Mac系统更新不及时,导致经常会反馈Safari有问题。
需要对Safari专门做兼容处理,所以,有必要收集下纯CSS识别Safari浏览器的技巧。
而网上对此资料甚少,那没办法,就自己出马整理了一大串鉴别Safari浏览器的方法。
例如:
less
@supports not (background: paint(xxx)) { /* Safari和Firefox */ }
@supports (background: -webkit-named-image(1)) { /* Safari only */ }
等诸多方法,详见此文:"如何使用纯CSS鉴别是不是Safari浏览器"
第28周 7.8-7.14
CSS calc()计算函数又新增了infinity,NaN,pi等关键字,不过实用性却一般般。
详见撰写的此文:"了解infinity、pi等CSS calc()计算关键字"。
(本篇完,年底待续)