”本系列教程为实战教程,是本人移动端重构经验及思想的一次总结,也是对 sandal 及 sheral UI 的一次全方位剖析,首发在imweb和 w3cplus 两大站点及“前端Talk”微信公众号,其余所有标注或没有标注来源的均为转载。“
——imweb 结一
具体demo效果可见: sheral progress
这里主要分析下圆环的实现,蓝色的进度条圆环由左右两边构成,这里以右半边的为例,html结构为 .circle-right > .right-inner
(为了视觉效果,把蓝色放在里面了,而非覆盖在灰色上),如下图:
半圆环由两层结构构成, .cicle-right
的大小为50px 100px,超过隐藏,而 .right-inner
的实际大小为100px 100px,因为父容器宽度为50px且超过隐藏所以只会显示右边一半,如果只是这样的话我们旋转 .right-inner
的话右边一直会有蓝色的半环。所以我们对 .right-inner
再做个裁剪处理 clip: rect(0, 50px, 100px, 0);
,这样导致整个 .right-inner
圆环只有左半边可见,然后加上我们父元素是在右半边且多余隐藏,所以默认看不到我们的蓝色圆环,如要看到蓝色圆环部分只有将 .right-inner
左边部分旋转到右边父元素的范围内,核心代码如下图:
.circle-right{ width: 50px; height: 100px; position: absolute; top: -4px; right: -4px; overflow: hidden; } .right-inner{ width: 100px; height: 100px; position: absolute; right: 0; top: 0; border-radius: 50%; border: 4px solid #007aff; box-sizing: border-box; clip: rect(0, 50px, 100px, 0); // 设置左半边可见 transition: transform 0.5s linear; }
同理即可实现左半边,不过如果某些安卓机比较卡的话,在大于50%的时候,左边半圆在衔接的时候会有一个卡顿不连贯,所以可以考虑增加再增加一个底部的半圆环,让其在右边半圆环运动到一半的时候开始运动,然后设置一个比较短的完成时间,这样就可以衔接起来。
当然其实使用svg更方便,这里推荐一个库 progress bar.js
PS:关于svg path的弧形绘制可参考 MDN svg 路径 的最后弧形部分
要实现的效果如下图,具体demo可见 sheral tool
这里主要涉及到两点:
如果按总的90deg角计算,index表示item的索引(从1开始),n表示item总数,则每个item的旋转角度计算公式为:
每个item的旋转角度 = ( index -1) / (n - 1) * 90deg
而图标就要相应的旋转对应的负角度回来,于是每个icon的旋转角度计算公式为:
每个图标的旋转角度 = -( index -1) / (n - 1) * 90deg
默认样式:
.tool-item{ width: $quickToolSize; height: $quickToolSize; position: absolute; background: $quickToolBg; border-radius: 50%; opacity: 0; transition: opacity .3s linear, transform .3s $timingFunction; @include center-flex(both); }
active样式
.tool-item{ opacity: 1; @for $i from 1 through $quickToolNum{ &:nth-of-type(#{$i}) { // item旋转 加 偏移 transform: rotate(($i - 1) * 90deg / ($quickToolNum - 1)) translateX(-80px); // transition-delay: ($i - 1) * 0.03s; .item-icon{ // icon旋转 transform: rotate(-($i - 1) * 90deg / ($quickToolNum - 1)); } } } }
转盘背景图如下图,我们要把奖品填写到相应的区域。
大体思想跟上面的差不多,大概如下:
1、先绝对定位在圆中间,然后先计算每个item的旋转角度,再设置偏移值
.item{ position: absolute; left: 50%; top: 50%; } @for $i from 1 through 8 { .item:nth-child(#{$i}){ transform: translate(-50%, -50%) rotate(($i - 1)*45deg + 22.5deg) translate(90px, 0); } }
2、调整奖品文字的旋转
.item-inner{ transform: rotate(90deg); }