小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
在前端应用中, 不管是PC端, 还是移动端. 总有很多时候需要对用户进行引导.
一般, 我们会在我们的应用页面之上覆盖一层黑色蒙层, 然后进行引导.
引导的内容有如何操作页面功能呢, 引导用户如何操作.
而进行引导的这个时候, 我们页面上其他功能是不可以使用的.
这样子的场景相信开发移动端的同学们是最熟悉的, PC端的应用场景就相对较少了.
而我发现, 很多同学会直接把连带黑色蒙层的背景一起切成一张图, 直接甩在页面上, 或者把主要的图切出来.
这样子, 固然可以得到一样的效果.
然而却不是最优方案, 同时大张的图片也会增加性能消耗、网络延迟.
本文就带大家来学会如何在前端页面优雅的打洞.
我们先来看几张我做的镂空效果.
简单图形使用css镂空
第一种方法, 使用CSS进行镂空.
那么在css中如何镂空页面呢?
有同学会想了, 使用4个黑色透明的div拼合, 中间就可以得到一个矩形的镂空.
那么问题来了, 我要镂空圆形, 椭圆, 圆角矩形呢?又该如何去实现呢?
在css中有两个属性:
- border
- box-shadow
border是给节点盒子添加边框, box-shadow是为节点盒子添加阴影.
那么, 这两个属性就促使我们有了实现镂空的基础.
当边框或者阴影较大的时候, 就可以达到镂空的效果了
<div class="cricle"></div>
/* 镂空一个圆 */
.cricle{
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 100px;
height: 100px;
border-radius: 50%;
border: 1000px solid rgba(0,0,0,0.8);
/* box-shadow: 0 0 0 1000px rgba(0,0,0,0.8); */
}
这样子, 我们的页面就有了一个镂空的圆.
注意
使用border-radius来控制div形状.
问题又来了, 这样子我们只是镂空了一个, 如果我们需要页面上镂空多个呢?
这个时候我们就需要变通一下, 在每一个镂空节点之上在套一个div盒子, 然后把每个盒子拼合在页面上.
<!-- 镂空两个 -->
<div class="mask-con-1">
<div class="round-rect"></div>
</div>
<div class="mask-con-2">
<div class="cricle"></div>
</div>
.mask-con-1{
position: absolute;
left: 0;
width: 50%;
height: 100%;
overflow: hidden;
}
.round-rect{
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-56.8%) translateY(-56.8%);
width: 120px;
height: 180px;
border: 1000px solid rgba(0,0,0,0.8);
border-radius: 1020px;
}
.mask-con-2{
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 100%;
overflow: hidden;
}
.mask-con-2 .cricle{
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-51%);
width: 400px;
height: 400px;
border-radius: 50%;
border: 1000px solid rgba(0,0,0,0.8);
}
这样子我们就得到了下图中的镂空效果:
是不是很有意思, 这样子我们就不需要每次遇到引导就去切图覆盖了.
然而我们需要注意一下的点:
box-shadow具有一定兼容性, 建议使用border.
同时设置border和border-radius时, 圆角会被覆盖, 所以我们设置的时候border-radius在border的基础上加上圆角范围.
我们可以来看下border和border-radius的相爱相杀.
可以看到, 随着border的增大, 内层的圆角慢慢就消失了.
所以我们要设置内层镂空圆角, 就需要在border的基础值上增加.
css镂空也有很多局限, 比如镂空不规则图形就相形见绌
我们还有canvas的方法来镂空.
复杂不规则图形使用canvas镂空
canvas绘制形状的方法, 也可以用来做镂空.
具体如何去做呢?
顺时针画背景, 逆时针画需要镂空的形状
这个就是canvas做镂空的核心所在了.
<canvas id="canvas"></canvas>
在canvas上绘制.
const canvas = document.getElementById("canvas");
canvas.width = 960;
canvas.height = 540;
const ctx = canvas.getContext("2d");
我们先来画一个镂空的矩形试下:
顺时针画一个大背景, 逆时针画一个矩形
ctx.beginPath();
ctx.fillStyle = 'rgba(0,0,0,0.8)';
//顺时针话方
ctx.moveTo(0, 0);
ctx.lineTo(960, 0);
ctx.lineTo(960, 540);
ctx.lineTo(0, 540);
//逆时针镂空
//方块
ctx.moveTo(40, 30);
ctx.lineTo(40, 100);
ctx.lineTo(150, 100);
ctx.lineTo(150, 30);
ctx.fill();
这样子, 我们就得到了镂空的一个矩形框了.
同样的, 我们再来画一个圆:
// 圆
ctx.moveTo(700, 200);
ctx.arc(700, 200, 150, 0, Math.PI * 2, true);
接着, 我们更换笔触, 画出一些不规则形状:
// 三角
ctx.moveTo(200, 30);
ctx.lineTo(200, 80);
ctx.lineTo(240, 60);
//类椭圆
ctx.moveTo(140, 267);
ctx.quadraticCurveTo(117, 252, 64, 336);
ctx.quadraticCurveTo(12, 423, 40, 438);
ctx.quadraticCurveTo(63, 453, 114, 367);
ctx.quadraticCurveTo(166, 280, 140, 267);
//不规则
ctx.moveTo(197,320);
ctx.lineTo(210, 342);
ctx.lineTo(215, 370);
ctx.lineTo(268, 360);
ctx.lineTo(226, 535);
ctx.lineTo(251, 539);
ctx.lineTo(300, 323);
ctx.lineTo(263, 326);
ctx.lineTo(235, 302);
ctx.lineTo(236, 303);
ctx.lineTo(213, 317);
ctx.fill();
就得到了下面的镂空效果.
难点应该是那个倾斜的椭圆了
我们用ps画出如下的效果图, 然后得到一系列的点, 将这些点写入二次贝赛尔曲线, 就可以一顺利画出来了.
这也是一个小技巧.
注意
镂空的图形一定要逆着背景去画.
当然, 镂空矩形还可以使用clearRect的方法
很多游戏引擎里面有个遮罩的概念
很多同学就会用遮罩去做镂空, 其实不可取哈, 遮罩性能较差.
但是不可否认, 遮罩是可以根据图片去镂空一块区域的. 功能还是非常香的.
编外使用svg镂空
最后再来介绍一下svg的镂空方法.
这个镂空不是很常见, svg兼容也不是很好.
看下我写的例子:
<!-- svg镂空 -->
<svg width="960" height="540">
<defs>
<mask id="mask">
<rect class="rect1" x="0" y="0" width="100%" height="100%"/>
<circle class="mask-to" cx="565" cy="67" r="50"/>
<circle class="mask-to" cx="434" cy="320" r="100"/>
<circle class="mask-to" cx="462" cy="209" r="40"/>
<ellipse cx="141" cy="135" rx="50" ry="100"/>
<rect class="mask-to" width="100" height="100" x='824' y="142"/>
</mask>
</defs>
<rect class="rect-bg" x="0" y="0" width="100%" height="100%"/>
</svg>
.svg {
position: absolute;
}
.rect1 {
stroke:none;
fill: #fff;
}
.rect2 {
stroke: none;
fill: #fff;
mask: url(#mask3);
}
.mask-to{
fill: #000
}
.rect-bg{
stroke: none; fill: rgba(0, 0, 0, 0.7); mask: url(#mask)
}
这样子也可以得到如下的镂空效果:
使用svg镂空可以画的图形也是不多.
同时需要注意的是, svg蒙层和背景需要形成对比.所以我这里选择的是黑白两色.
尾声
至此, 三种镂空的方法就介绍到这里了, 大家还有更好的办法吗?
我们需要注意:
如果页面镂空很单纯, 就使用css镂空.
如果涉及到不规则图形, 就使用canvas.
一般游戏中就使用canvas的方法好了.
尽量不去使用svg方法(不用管浏览器, 还是很强大的).
尽量少去请求图片资源, 优化性能是我们需要做的, 不能什么页面都靠图片堆砌.
如果你还有更好的方式, 可以留下你的评论, 感激不尽~
欢迎大家拍砖指正, 笔者功力尚浅, 如有不当之处请斧正.
文章粗浅, 望诸位不吝您的评论和点赞~
注: 本文系作者呕心沥血之作, 转载须声明