首页
Search
1
解决visual studio code (vscode)安装时没有选择安装路径问题
138 阅读
2
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
131 阅读
3
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
107 阅读
4
如何在 Clash for Windows 上配置服务
77 阅读
5
Uniapp如何引入自定义样式文件
75 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,061
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
624
篇与
的结果
2024-08-24
闲读源码:ScrollingElement Polyfill
今天看了这篇文章,讲到 WebKit document.body.scrollTop 的问题。还有这里 Dev.Opera Blog : Fixing the scrollTop bug。scrollTop, scrollLeft, scrollWidth, scrollHeight 都是跟滚动相关的属性。设置 scrollTop 和 scrollLeft 还可以产生滚动。当这些属于用在根元素的时候,滚动是发生在 viewport 的。但是 WebKit/Blink 不走寻常路,它会一直让 body 来代替 viewport 滚动。所以根元素会一直返回 0,对它设值也不会有反应。文章里面提到了几种处理方式,其中一种方式就是利用一个比较新的属性 document.scrollingElement,它会返回合适的滚动元素,就不用纠结是哪个。document.scrollingElement polyfill 是它的一个 fallback,看起来很有趣,就细读了一遍。规范要理解源码必须先看它要干什么,CSSOM View specification 提到:The scrollingElement attribute, on getting, must run these steps: If the Document is in quirks mode, follow these substeps: If the HTML body element exists, and it is not potentially scrollable, return the HTML body element and abort these steps. Return null and abort these steps. If there is a root element, return the root element and abort these steps. Return null. Note: For non-conforming user agents that always use the quirks mode behavior for scrollTop and scrollLeft, the scrollingElement attribute is expected to also always return the HTML body element (or null if it does not exist). This API exists so that Web developers can use it to get the right element to use for scrolling APIs, without making assumptions about a particular user agent’s behavior or having to invoke a scroll to see which element scrolls the viewport.这个 polyfill 干的事情就是在 Standards Mode 情况下如果正确实现规范的话就返回根元素,其它情况下返回 body(不一定是 document 的哦,后面会提到)。入口整体来看,没有实现 scrollingElement 的才会调用 polyfill:if (!('scrollingElement' in document)) (function() { // ... }());然后从这里开始:if (Object.defineProperty) { // Support modern browsers that lack a native implementation. Object.defineProperty(document, 'scrollingElement', { 'get': scrollingElement }); } else if (document.__defineGetter__) { // Support Firefox ≤ 3.6.9, Safari ≤ 4.1.3. document.__defineGetter__('scrollingElement', scrollingElement); } else { // IE ≤ 4 lacks `attachEvent`, so it only gets this one assignment. IE ≤ 7 // gets it too, but the value is updated later (see `propertychange`). document.scrollingElement = scrollingElement(); document.attachEvent && document.attachEvent('onpropertychange', function() { // This is for IE ≤ 7 only. // A `propertychange` event fires when `` is parsed because // `document.activeElement` then changes. if (window.event.propertyName == 'activeElement') { document.scrollingElement = scrollingElement(); } }); }规范里 scrollingElement 是一个变量。通过 defineProperty 就可以让一个变量在获取的时候(也就是 get 的时候)调用函数,动态计算值。这里就是主入口:var scrollingElement = function() { if (isCompliant()) { return document.documentElement; } var body = document.body; // Note: `document.body` could be a `frameset` element, or `null`. // `tagName` is uppercase in HTML, but lowercase in XML. var isFrameset = body && !/body/i.test(body.tagName); body = isFrameset ? getNextBodyElement(body) : body; // If `body` is itself scrollable, it is not the `scrollingElement`. return body && isScrollable(body) ? null : body; };正确实现规范的话就是返回根元素 document.documentElement,比如 HTML 里的 ,否则返回 body。isCompliant这里就是先判断浏览器有没有正确实现了规范。看看怎么判断的:// Note: standards mode / quirks mode can be toggled at runtime via // `document.write`. var isCompliantCached; var isCompliant = function() { var isStandardsMode = /^CSS1/.test(document.compatMode); if (!isStandardsMode) { // In quirks mode, the result is equivalent to the non-compliant // standards mode behavior. return false; } if (isCompliantCached === void 0) { // When called for the first time, check whether the browser is // standard-compliant, and cache the result. var iframe = document.createElement('iframe'); iframe.style.height = '1px'; (document.body || document.documentElement || document).appendChild(iframe); var doc = iframe.contentWindow.document; doc.write('x'); doc.close(); isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight; iframe.parentNode.removeChild(iframe); } return isCompliantCached; };:whitecheckmark: document.compatMode 是用来判断浏览器是 Standards Mode 还是 Quirks Mode,分别取值为 CSS1Compat 和 BackCompat。作者也说了 document.write 可以在运行时修改模式,所以每次都要判断一遍。然后就用一个 iframe 来测试了,哇蛮重的。好处只能说是通用了。Standards Mode 下根元素的 scrollHeight 比 body 高就可以说明正确的实现了规范。因为这么重所以测试了一遍之后就把结果存起来了,以后就直接用。:whitecheckmark: 从这里也对 document.body 有了新的认识:Returns the or node of the current document, or null if no such element exists. 这种过时的东西没什么兴趣深入了解,直接看看怎么获取 body 的:Bodyfunction isBodyElement(element) { // The `instanceof` check gives the correct result for e.g. `body` in a // non-HTML namespace. if (window.HTMLBodyElement) { return element instanceof HTMLBodyElement; } // Fall back to a `tagName` check for old browsers. return /body/i.test(element.tagName); } function getNextBodyElement(frameset) { // We use this function to be correct per spec in case `document.body` is // a `frameset` but there exists a later `body`. Since `document.body` is // a `frameset`, we know the root is an `html`, and there was no `body` // before the `frameset`, so we just need to look at siblings after the // `frameset`. var current = frameset; while (current = current.nextSibling) { if (current.nodeType == 1 && isBodyElement(current)) { return current; } } // No `body` found. return null; }通过 nextSibling 循环排查跳过一个个 frameset。nodeType == 1 表示 Node.ELEMENT_NODE,这个节点是个元素。:whitecheckmark: 通过 element instanceof window.HTMLBodyElement 可以正确判断 body 元素。isScrollable找到了 body 接下来就看 isScrollable 干了什么:function isScrollable(body) { // A `body` element is scrollable if `body` and `html` both have // non-`visible` overflow and are both being rendered. var bodyStyle = computeStyle(body); var htmlStyle = computeStyle(document.documentElement); return bodyStyle.overflow != 'visible' && htmlStyle.overflow != 'visible' && isRendered(bodyStyle) && isRendered(htmlStyle); }基本就是看看它的 CSS 属性,如果 overflow 不是 visible 且这个元素被渲染了的话,就属于可滚动的。这里就有了一个疑问,overflow 是 hidden 也算可滚动的吗?看了一下 MDN,发现这么一段话:Note: When programmatically setting scrollTop on the relevant HTML element, even when overflow has the hidden value an element may still need to scroll.:whitecheckmark: 所以 overflow 是 hidden 也是可滚动的。window.getComputedStyle然后就是这个 computeStyle:function computeStyle(element) { if (window.getComputedStyle) { // Support Firefox < 4 which throws on a single parameter. return getComputedStyle(element, null); } // Support Internet Explorer < 9. return element.currentStyle; }:whitecheckmark: window.getComputedStyle() 与 HTMLElement.style 不一样在于前者可以动态得到元素所有的 CSS 属性,包括默认的值,而后者只能得到 inline CSS 属性。但前者是只读的,后者可以设值。isRendered然后再看 isRendered 怎么判断:function isRendered(style) { return style.display != 'none' && !(style.visibility == 'collapse' && /^table-(.+-group|row|column)$/.test(style.display)); }看来这位作者不太用严格等号和不等号。display这个好理解,none的元素不会被渲染出来。后面的就有点绕,要理解这个判断需要明白 visibility 的三个取值: visible Default value, the box is visible. hidden The box is invisible (fully transparent, nothing is drawn), but still affects layout. Descendants of the element will be visible if they have visibility:visible (this doesn't work in IE up to version 7). collapse For table rows, columns, column groups, and row groups the row(s) or column(s) are hidden and the space they would have occupied is removed (as if display: none were applied to the column/row of the table). However, the size of other rows and columns is still calculated as though the cells in the collapsed row(s) or column(s) are present. This was designed for fast removal of a row/column from a table without having to recalculate widths and heights for every portion of the table. For XUL elements, the computed size of the element is always zero, regardless of other styles that would normally affect the size, although margins still take effect. For other elements, collapse is treated the same as hidden. 前两个比较常见,hidden 依然是占位置的所以属于渲染。:whitecheckmark: collapse 是专门为表格行列元素快速隐藏做优化的,对它们来说效果等同于 display: none,所以会影响滚动高度。于是后半段代码相当于找出下面几种元素,然后看是不是 collapse 的:display: table-column; display: table-column-group; display: table-footer-group; display: table-header-group; display: table-row; display: table-row-group;总结可以看到这个 polyfill 代码虽然不算太长,但也干了很多事情,算是比较重的。但考虑到还在用老浏览器的人,能用就很给面子了是吧哈哈。从中也学了许多新知识,都打钩了注意到了吗 :smile: 。
2024年08月24日
19 阅读
0 评论
0 点赞
2024-08-24
Sublime Text Title Case 快捷键
Preferences -> Key Bindings 添加:[ { "keys": ["ctrl+k", "ctrl+t"], "command": "title_case" } // ..... ]然后就可以用 Ctrl+k 再按下 Ctrl+t 使用 Title Case。Package Control 上有个很老的 Package,Smart Title Case。能识别更复杂的情况,但是有 bug,核心代码已经修复 https://github.com/ppannuto/python-titlecase,但 Package 的作者早已不再维护,下载量也不大。
2024年08月24日
7 阅读
0 评论
0 点赞
2024-08-24
自适应背景图片
很多时候我们希望背景图片能够在元素不同大小的情况下都能够显示出主体。居中是最常见的方式,但如果主体不在中间这个效果就大打折扣了。这个对我来说一开始仅仅是一个念头,也没太注意。直到一次在 podcast 上听到有位嘉宾做了一个 jQuery 插件 https://github.com/wentin/ResponsifyJS,主要就是为了实现这种效果。感兴趣地去看了一下,感觉还是太重了。但我有个缺点就是一旦开始了就不容易停下来,就继续找了一下资料。发现其实浏览器本身就有很好的实现。Background Positon!background-position 支持百分比属性。当使用百分比属性的时候,就是将背景图片与元素在百分比指定的位置重合。比如说 20% 40%,在横向上背景图片的 20% 与元素的 20% 对齐,竖向上背景图片的 40% 与元素的 40% 对齐。这就相当于指定了一个焦点。把焦点放到主体上,那么无论元素怎么变化,主体都会有较好的显示效果。而且这些计算都是浏览器来干的!现在唯一麻烦的地方就是要指定焦点。我继续找了一些资料,JavaScript 上也有人实现一些 Content Aware 的算法,比如这个 Smartcrop.js。但是由于我没有批量的图片需要调整,就没有折腾去研究这个,而是研究怎么方便手动选择。后来就做了这个所见即所得工具,http://www.crimx.com/portrait-crop/,除了标记焦点以外还可以进行竖向的裁剪,节省空间。移动焦点的时候右边会实时计算 background-position,包括了横向和竖向的结果。不需要裁剪的话只用横向的就行。右下还提供了 json 格式。我的博客就是为所有封面保存了一个 json 文件,在 hexo 中设钩子去读再作为 inline css 写入。每次添加的时候复制粘贴就可以。裁剪框是基于 cropperjs 实现的,添加了个焦点。实现的时候还顺便修了 bug 提交了个 pr 给原作者哈哈。2016年12月31日按:他今天才 merge …… :sweat_smile: 都忘记有提过这个 pr 了
2024年08月24日
8 阅读
0 评论
0 点赞
2024-08-24
Photoshop Pen Tool
https://design.tutsplus.com/tutorials/photoshops-pen-tool-the-comprehensive-guide--psd-718这篇文章非常好的总结了 PS 钢笔工具的用法,其中的练习 PSD 特别好用,照着画一遍基本就懂得怎么操作锚点。
2024年08月24日
12 阅读
0 评论
0 点赞
2024-08-24
CSS 过渡未知高度
有时候往 dom 里插入一些元素,会希望 dom 慢慢腾开空间,再把插入的元素呈现出来。但对于过渡 height 未知的元素,暂时没有完美的方法,浏览器还不支持 height 过渡到 auto。而且这种方式也会造成这个元素后面的所有元素一并重绘,蛮耗资源的。以下是利用 max-height 来过渡,适合已知元素高度的范围。但也不是完美方法,max-height 固定了,那么同样的时间,元素高度越小过渡就会显得越快。所以只好尽量选最接近的 max-height。写的时候犯了一个小错误,折腾了一会才发现时间 0 忘了加单位。CSS 时间里0是非法的值。
2024年08月24日
6 阅读
0 评论
0 点赞
1
...
58
59
60
...
125