一. clip-path 介绍

- 用上面的图做例子,假设这个九边形 div 被我设置了 cursor: pointr 属性,那么九边形之外的区域鼠标滑过不会显示手势,而九边形之内的区域可以
- 注意:clip-path 属性不支持 IE
二. clip-path 示例
2.1 平行四边形的 tab 按钮

- 通过叠加多个背景图片,实现两边固定,中间自适应增长的背景效果;
- 将 div 的 margin 值调整一下,实现减小 tab 按钮间距的效果;
-
这种方案存在的问题: - 关于背景 bug:仔细看按钮背景图会发现,中间是固定的,那个小光点高光效果,不可以被拉伸,自适应势必无法很好的展现设计图效果
- 关于点击 bug:即使背景改变成平行四边形的样子,给他们加点击事件就会暴露他是矩形的事实,修改间距会导致点击上图中的平行四边形角落,会触发别的平行四边形的事件,如下图所示,调整边距会导致 div 部分重合,进而导致点击事件混乱

-
综上所述,把 div 的 默认形状 改成 平行四边形,是最好的解决方案 - 我这用的是 Vue3 组件,按钮样式是传进去的,不要在意写法(…)
- 逻辑:通过 clip-path 调整 div 形状,通过 margin 调整 div 间距,背景就放正常的整张图片,而不是拼接多张背景图片
// 控制按钮大小、背景、位置的样式
const tabItemStyle = {
width: '1120px',
height: '250px',
// 这里 margin-left 负责调整按钮间距,如果按钮向右歪,就改成 margin-right
marginRight: '-380px',
// 这里是把按钮裁剪成平行四边形的形式,防止 div 重合影响点击事件
WebkitClipPath: 'polygon(0% 95%, 0% 0%, 96% 0%, 95% 92%)',
clipPath: 'polygon(0% 95%, 0% 0%, 96% 0%, 95% 92%)',
};
cStyle: {
// 按钮容器样式
tab: {
// 默认状态
default: {
...tabItemStyle,
// 正常传入整张背景图片,不要拼接多张
background: 'url(./assets/tab-right-default.png) no-repeat',
backgroundSize: '100% 100%',
},
// 激活状态
active: {
...tabItemStyle,
background: 'url(./assets/tab-right-light.png) no-repeat',
backgroundSize: '100% 100%',
},
},
},
2.2 不规则弹框边角效果

- 设计稿如上图,我最初构想的实现方案是:UI 直接切个背景(…)
- 先不说 图片啥的影响请求速度啥的了,公司 UI 比较忙,不敢没事找他【碎碎念】
-
认识了新属性 clip-path 之后,我可以更优雅的实现这个效果了 - 分析一下弹框边角本质:就是个八边形

- 其实写好了左上角之后,其他的边角直接 transform: rotate(); 即可
-
html 结构:外框 .dialog-outer,其内部包含了 弹框边角 及 内容区域
<div class="dialog-outer">
<div>内容</div>
<!-- 弹框的背景角落部分 -->
<i class="left-top-bg"></i>
<i class="left-bottom-bg"></i>
<i class="right-top-bg"></i>
<i class="right-bottom-bg"></i>
</div>
- 给 .dialog-outer 设置相对定位,一定要设置 border-radius: 40px; 防止边角盖不住
- 四个边角设置绝对定位,将左上角写好样式(宽高、渐变背景、形状)
- 依据左上的边角进行旋转 transform: rotateX(180deg) rotateY(180deg);
/* 弹窗外层容器 */
.dialog-outer {
/* 外框相对定位 */
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
width: 100%;
height: auto;
background: rgba(12, 28, 64, 0.8);
border-radius: 40px;
padding: 92px;
/* 解决 padding的负面效果 */
box-sizing: border-box;
}
/* 弹框背景 */
.left-top-bg,
.left-bottom-bg,
.right-top-bg,
.right-bottom-bg {
/* 边角绝对定位 */
position: absolute;
width: 90px;
height: 90px;
/* 实现边角渐变效果 */
background: linear-gradient(0deg, #D1A558, #F3DB86);
/* 切割边角八边形形状 */
clip-path: polygon(30% 0%, 70% 0%, 70% 6%, 32% 6%,
6% 33%, 6% 70%, 0% 70%, 0% 30%);
}
.left-top-bg {
top: -3px;
left: -2.5px;
}
.right-top-bg {
top: -3px;
right: -2.5px;
/* 根据左上角的边角效果进行旋转 */
transform: rotateY(180deg);
}
.left-bottom-bg {
bottom: -3px;
left: -2.5px;
transform: rotateX(180deg);
}
.right-bottom-bg {
bottom: -3px;
right: -2.5px;
transform: rotateX(180deg) rotateY(180deg);
}