Chrome69 新特性介绍
chenxiaochun opened this issue · 0 comments
Chrome69 刚刚发布,翻了一下它的官方文档。所以,这篇文章就是向大家介绍一下它新支持的一些有趣功能特性。
写这篇文章的目的也仅仅是对新技术的一种了解和探索,各位也不要看完之后,就急着应用到自己的项目中去;或者看完之后,就开始纠结各种浏览器的兼容性问题。我个人认为,在项目中使用技术要保守一点,尽量选择那些比较熟悉的技术方案,但是,学习新技术还是应该尽量激进。
CSS Scroll Snap
CSS Scroll Snap 用来创建平滑的滚动体验,并且还可以控制元素每次滚动操作之后的停止位置。这个新特性非常合适用在图片轮播和滚动分页的操作效果。
拿图片轮播举例,我需要给滚动的容器添加scroll-snap-type: x mandatory;
,mandatory
的意思就是“强制的”,也就是强制里面的元素以水平方向滚动。然后给里面滚动的每一张图片添加scroll-snap-align: center;
。然后当用户滚动轮播的时候,每一张图片就能恰好顺滑的滚动到完美的位置上。
#gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
#gallery img {
scroll-snap-align: center;
}
即使每一张图片的尺寸都不一样或者超出了滚动容器的大小,这个功能依然能工作的很好。
查看示例:https://codepen.io/sjzcxc/pen/PdKrzv?editors=1100
查看 google 官方提供的示例:https://snap.glitch.me/carousel.html
源代码:https://glitch.com/edit/#!/snap?path=carousel.html:186:0
手机“刘海儿”区域显示
现在越来越多的手机都有那个“刘海儿”。于是浏览器添加了一些额外的外边距以处理这个区域。
默认显示效果:
viewport-fit=cover
告诉浏览器展开预留的那个“刘海儿”区域。但是你会发现有些内容会被遮挡,并且下面的导航条也会变得非常难用。
<meta name='viewport' content='initial-scale=1, viewport-fit=cover'>
那怎么才能在加上上面的元标签之后,也能防止内容不被遮挡呢?
为了实现这个效果,需要使用 css 函数:env()
,以及四个内置的环境变量:
safe-area-inset-left
safe-area-inset-right
safe-area-inset-top
safe-area-inset-bottom
.post {
padding: 12px;
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
web locks api
可以用这个 api 以异步的方式获得一个锁,然后直到你的任务完成之后,再去释放它。当其它任务占用这把锁的时候,获得这把锁的其它任务,只能是等待上一个任务释放这把锁之后,再能继续执行。这个特性非常适合用于管理公共资源的使用。
注意:这个 api 只能在 https 协议中才能获取到。
例如,当一个应用在多个 tab 页运行的时候,可以用来确保当前只有一个 tab 页在获取数据.
navigator.locks.request("network_sync_lock", async lock=>{
await new Promise(resolve => {
setTimeout(() =>{
console.log('我正在获取一个数据!')
resolve();
}, 3000);
})
})
navigator.locks.request('network_sync_lock', async lock => {
await new Promise(resolve => {
setTimeout(() => {
console.log('等第一个任务完成之后,我才能继续!');
resolve();
}, 3000)
})
});
第一个 tab 页获得一把锁之后,开始异步的请求数据。如果另一个 tab 页也想获得相同的锁,它就必须排队。当第一个任务把锁释放之后,后面排队的任务才会被授权使用锁,并被执行。查看示例:https://codepen.io/sjzcxc/pen/GXMJzX?editors=1010
可以给request
传递一个对象参数,用来控制锁的执行状态。
model
:默认值是exclusive
,也就是独有的,排外的;shared
,可以共享自己的状态。查看在线实例:https://codepen.io/sjzcxc/pen/PdJXGZ
navigator.locks.request("network_sync_lock",{mode: 'shared'}, async lock=>{
await new Promise(resolve => {
setTimeout(() =>{
console.log('我正在获取一个数据!')
resolve();
}, 3000);
})
})
navigator.locks.request('network_sync_lock',{mode: 'exclusive'}, async lock => {
await new Promise(resolve => {
setTimeout(() => {
console.log('等第一个任务完成之后,我才能继续!');
resolve();
}, 3000)
})
});
实验发现,只要第一个任务把锁置为shared
的状态,那么第二个任务是否需要等待上一个任务释放锁,完全是由自己决定的。
signal
:它是一个AbortSignal
对象,可以用来在适当的时机中止当前任务锁,查看示例:https://codepen.io/sjzcxc/pen/EewMZm?editors=1010#
var controller = new AbortController();
var signal = controller.signal;
navigator.locks.request("network_sync_lock",{signal: signal}, async lock=>{
await new Promise(resolve => {
setTimeout(() =>{
console.log('执行第一个任务!')
resolve();
}, 3000);
})
})
navigator.locks.request('network_sync_lock', async lock => {
await new Promise(resolve => {
setTimeout(() => {
console.log('执行第二个任务!');
resolve();
}, 3000)
})
});
signal.onabort = () => {
if(signal.aborted){
console.log('任务被中止!');
}
}
controller.abort();
ifAvailable
:默认为false
,指定为true
表示当前任务如果不能立即得到执行,就无需等待其它任务释放资源锁,按照自己的逻辑直接执行即可。
如下示例所示,我们给第二个任务设置了ifAvailable: true
,经过 3 秒钟之后,会同时看到两条 log 信息。
navigator.locks.request("network_sync_lock", async lock => {
await new Promise(resolve => {
setTimeout(() => {
console.log('执行第一个任务!')
resolve();
}, 3000);
})
})
navigator.locks.request('network_sync_lock', { ifAvailable: true }, async lock => {
await new Promise(resolve => {
setTimeout(() => {
console.log('执行第二个任务!');
resolve();
}, 3000)
})
});
圆锥渐变
查看示例:conic-gradient。另外,之前写过一篇关于线性渐变和放射性渐变的文章,可以点击链接查看。
属性开关切换
<input value="text">
<button>toggleAttribute</button>
var button = document.querySelector("button");
var input = document.querySelector("input");
button.addEventListener("click", function(){
input.toggleAttribute("readonly");
});
toggleAttribute
的第二个参数是一个布尔值。设置为true
时表示给当前元素添加属性,为false
时表示删除属性。
新增两个 array 方法
flat()
const array = [1, [2, [3]]];
array.flat();
// → [1, 2, [3]]
flatMap()
[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]
OffscreenCanvas
以前在 worker 中是无法使用 canvas 的,因为无法在 worker 中操作 DOM 元素。现在OffscreenCanvas
的出现,就是为了实现无需依赖于 DOM 操作的在 worker 中绘制 canvas。
大家都知道,浏览器的执行时是单线程的,如果一个任务耗时过长,就会使页面出现卡顿,影响用户体验。因此将那些复杂的 canvas 绘制工作从主线程移到一个 worker 里面,不影响主线程的程序运行,可以极大提高执行效率和用户体验。
worker.js:
function getGradientColor(percent) {
const canvas = new OffscreenCanvas(100, 1);
const ctx = canvas.getContext("2d");
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, ctx.canvas.width, 1);
const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}
postMessage(getGradientColor(40));
主文件:
<body>
<script>
var worker = new Worker('worker.js');
worker.onmessage = event => {
console.log(event.data);
}
</script>
</body>
关闭地址栏默认隐藏 www 字符
你在地址栏中输入www.a.www.b.com
回车之后,它显示的是a.b.com
。这明显是有问题的,例如钓鱼网站就可能利用这个漏洞欺骗用户。今天测试发现Chrome 已经默认修复了这个问题,所以,大家只要知道有这么个开关就可以了。
chrome://flags#omnibox-ui-hide-steady-state-url-scheme-and-subdomains