项目中要求金额输入框实现单位提示,在输入指定位数后,左上角分别提示百、千、万、十万、百万、千万、亿……,效果如下图所示,原来以为很容易就实现了,实际操作后,发现还有一丢丢门道需要注意。
大概分为以下几点的实现思路:
- 使用定位将单位提示放在上方,采用阴影样式实现凸起样式,box-shadow 还是 filter +drop-shadow
- 三角形使用 border 实现,使用伪元素添加三角,避免在 dom 中增加新的节点
box-shadow vs filter +drop-shadow
box-shadow
用法:
box-shadow: x-shadow y-shadow blur spread color inset || none; // 默认为null
值描述x-shadow必需。水平阴影的位置。允许负值y-shadow必需。垂直阴影的位置。允许负值blur可选。模糊半径。值越大,阴影越大越模糊。若未指定,默认为
0
,产生清晰、不模糊的边缘。不允许有负值。spread可选,阴影的扩展半径。取正值时,阴影扩大;取负值时,阴影收缩。默认为 0,此时阴影与元素同样大color可选。阴影的颜色inset可选。将外部阴影outset改为内部阴影
注意:默认是外阴影,但不可以写outset,否则导致 阴影无效;阴影不占用空间,不影响其他盒子;
drop-shadow
用法:
filter: drop-shadow(x-shadow y-shadow blur spread color);
值描述x-shadow必需。水平阴影的位置。允许负值y-shadow必需。垂直阴影的位置。允许负值blur可选。模糊半径。值越大,阴影越大越模糊。若未指定,默认为
0
,产生清晰、不模糊的边缘。不允许有负值。spread可选,阴影的扩展半径。取正值时,阴影扩大;取负值时,阴影收缩。默认为 0,此时阴影与元素同样大。大多数浏览器不支持这个参数;如果使用,效果将不会呈现。color可选。阴影的颜色
两者差异
1、兼容性不一样。CSS3
box-shadow
从IE9浏览器开始就支持了,
filter
中的
drop-shadow
IE13开始支持
2、同样的参数值,表现效果有差异,
box-shadow
的阴影距离更小,色值要更深
使用同样参数右下5像素偏移,10像素模糊的黑色阴影
5px 5px 10px black
, 两种实现效果差异如下:
<style>.box{margin: 50px;line-height: 120px;text-align: center;width: 120px;height: 120px;background-color: antiquewhite;}.box-shadow{box-shadow: 5px 10px 10px black;}.drop-shadow{filter:drop-shadow(5px 10px 10px black);}</style><body><divclass="box box-shadow">box-shadow</div><divclass="box drop-shadow">drop-shadow</div></body>
3、drop-shadow没有内阴影效果
4、drop-shadow 不能阴影叠加,而box-shadow可以多个阴影叠加,例如:
box-shadow: 2px 0 2px 2px #ccc, -2px 0 2px 2px #ccc; // 左右两边有阴影
5、box-shadow 是盒阴影,不能穿透,而 drop-shadow 是投影,可以穿透透明的区域。
阴影实现
上文写了 box-shadow 和 drop-shadow 的区别,盒阴影和投影。
而三角是使用
border
绘制的,没法
box-shadow
,但三角如果没有阴影,就会被同色系的 van-filed 完美隐藏,达不到开头示意图展示效果了。除非箭头处的颜色和底色背景选择不同色,如下图所示。
所以采用 filter + drop-shadow 实现
指示三角形
html 结构,使用
van-field
实现
<div class="money-container">
<van-field
v-model="money"
type="number"
label="金额"
/>
<div v-if="moneyUnit" class="money-unit">{{ moneyUnit }}</div>
使用伪元素实现三角形:
.money-container {
position: relative;
.money-unit {
padding: 0 14px;
height: 40px;
line-height: 40px;
border-radius: 6px;
text-align: center;
background-color: #fff;
position: absolute;
left: 7em;
top: -20px;
/* 下文介绍实现 */
transform: translateZ(0);
filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.1));
&::before {
content: '';
position: absolute;
left: 50%;
bottom: 0;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 10px;
border-top-color: #fff;
transform: translate(-50%, 100%);
}
}
}
最终实现效果
drop-shadow 在 ios 渲染问题
问题原因和解决
在 pc 端测试正常,在 iPhone 打开页面发现会出现以下情况,单位从有到无,或者单位框框宽度由大变小时,会出现阴影仍然存在的情况。
解决办法:加上 transform: translateZ(0); 添加到gpu复合层渲染就正常了。
复合图层介绍
CPU 和 GPU:CPU 即中央处理器,GPU 即图形处理器。
定义:
- 渲染图层:是页面的普通的文档流,我们虽然可以使用绝对定位相对定位来脱离文档流,但是它仍属于默认复合层,都公用同一个绘画上下文对象
- 复合图层:它会单独分配系统资源,每个复合图层都有一个独立的GraphicsContext(当然也会脱离文档流,这样一来,不管复合图层中如何变化,都不会影响默认图层内的重绘重排),硬件加速就用在了这里
如何创建复合图层:
可以
Chrome源码调试 -> More Tools -> Rendering -> Layer borders
中看到,黄色的就是复合图层信息。
translate3D
或者translateZ
opacity
属性/过渡动画(需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态)will-chang
属性(这个比较偏僻),一般配合opacity与translate使用。作用是提前告诉浏览器要变化,这样浏览器会开始做一些优化工作(这个最好用完后就释放)video/iframe/canvas/webgl
等元素
复合图层的优点
- 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
- 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
- 对于 transform 和 opacity 效果,不会触发 layout 和 paint
最大的优点:形成复合图层之后,和其他的复合图层是相对独立的,内部元素发生重排或者重绘的时候,不会影响其他复合层的元素
复合图层的注意点
- 创建复合图层是一个相对比较占资源的操作。所以在创建复合图层的时候,要考虑是否会得不偿失。
- 层爆炸现象。也就是页面中不可预期的产生了很多复合层,导致大量占用内存。产生这种情况的原因可能是在给某个元素添加复合图层的时候,这个元素的层级比较低,那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releative或absolute属性相同的), 会默认变为复合层渲染
所以在创建复合图层的时候,最好给元素加上一个z-index属性,提高元素的层级。避免创建多余的复合图层。
absolute和复合图层的区别
absolute虽然脱离了文档流,但是并不能创建一个单独的复合图层,也就是说还是在默认的复合图层中的。所以,就算absolute中信息改变时不会改变普通文档流中 render 树, 但是,浏览器最终绘制时,是整个复合层绘制的,所以absolute中信息的改变,仍然会影响整个复合层的绘制。
所以如果复合层中的节点很多的时候,绘制整个复合层也是相当耗费资源的,所以这时就要考虑给元素创建新的复合图层。
reference
CSS3 box-shadow盒阴影图形生成技术
IOS真机下动态修改filter:drop-shadow导致的渲染异常问题
复合图层,渲染图层及性能优化
谈谈复合图层
版权归原作者 攒一筐小丸子 所有, 如有侵权,请联系我们删除。