最近的小程序项目有个设计图要求作一个圆环,两种颜色分配,分别表明可用金额和冻结金额。要是就直接这么显示,感受好像挺没水平??因而我决定作个动态!css
在mdn把新特性gradients(渐变)、transitions(过渡)、 animations(动画)
都看了一遍,不由感叹css牛逼!这三个新特性加上canvas,仿佛一瞬间有了正面刚js的能耐。用js很难过渡得那么完美,并且浏览器的css渲染明显比用js性能好得多。
而后看了张鑫旭(传说中玩转css的那个男人)的一篇关于圆环的博文,拍案叫绝。连接=>3种纯CSS实现中间镂空的12色彩虹渐变圆环方法
只能说服气!除了灵活运用各类css特性以外,鑫大佬最让我佩服的是他的创造性思惟。会让你不由感叹:卧槽,还有这种操做?!想到了高中物理老师每次装完逼讲的一句话:思想有多远,就能走多远。html
虽然demo跟个人需求不太同样,问题仍是没有解决,但我认真看完以后仍是学会了不少,对我后面的代码帮助很大。鑫大佬这篇博文的重点仍是在渐变,而我须要动态平缓连续得实现颜色的分配,好比本来整个环是绿色,而后慢慢地60%被红色占了,并且整个过程要平滑。跟个人需求最接近的就是倒计时那个demo,linear-gradient线性渐变实现的多彩圆环demo,但不是连续的过程,而是经过剪裁,每次剪30度。css3
看了其余一些博客分享,好像也没有找到合适的,那没办法了...只能本身想一个!
由于再写这个demo的时候,发现小程序和H5在css表现上仍是有些差别(具体有哪些差别,在文末总结),因此仍是贴H5代码好了。web
很少说,直接上代码canvas
//html部分 <div class="circle"> <div class="circle-left"></div> <div class="circle-right"></div> <div class="circle-bottom-left"></div> <div class="circle-bottom-right"></div> </div> <div class="info">¥4500/¥5000</div>
//css部分 .circle { -webkit-mask: radial-gradient(transparent 150px, #000 150px); width: 400px; height: 400px; overflow: hidden; border-radius: 50%; position: relative; } .circle-left { width: 50%; height: 100%; background: #24B39B; transform-origin: 100% 50%; position: absolute; left: 0; z-index: 0; } .circle-right { width: 50%; height: 100%; background: #24B39B; transition: transform 1s linear; transform-origin: 0% 50%; position: absolute; right: 0; z-index: 2; } .circle-bottom-left { width: 50%; height: 100%; background: rgb(234, 67, 15); position: absolute; left: 0; z-index: -1; } .circle-bottom-right { width: 50%; height: 100%; background: rgb(234, 67, 15); position: absolute; right: 0; z-index: 1; } .info { width: 400px; height: 400px; line-height: 400px; text-align: center; margin-top: -400px; }
//js代码 window.onload = function () { var red = 4500, total = 5000 //红色区域表明的金额和总金额 var percent = red / total var right = document.getElementsByClassName('circle-right')[0] var left = document.getElementsByClassName('circle-left')[0] if (percent <= 0.5) { //红色区域不超过一半 right.style.transform = `rotate(${percent * 360}deg)` } else { //红色区域超过一半的状况,重点部分 right.style.transform = `rotate(180deg)` right.style.transition = `opacity 0s step-end 1s, transform 1s linear` //timing-function须要设为linear来达到视觉上的平缓过渡 right.style.opacity = 0 left.style.transition = `transform ${(percent - 0.5) / 0.5}s linear 1s` left.style.transform = `rotate(${percent * 360 - 180}deg)` } }
效果图小程序
st=>start: 开始 e=>end: 结束 con=>condition: degree<=180? op1=>operation: 右绿旋转 op2=>operation: 右绿旋转180度,opacity变为0,而后左绿旋转 st->con con(yes)->op1->e con(no)->op2->e
难点在于红色区域大于一半的状况,左右绿色半圆的衔接,过渡要天然,不能让人看出什么明显的破绽。
**这种状况个人作法是:4个半圆(红绿各两个)的z-index设为左红<左绿<右红<右绿
两个绿半圆的transform的time-function(时间函数)统一设为linear(线性)。右绿旋转180度(1秒)后opacity当即变成0(时间函数step-end),这样就不会挡住左红露出。而后左绿开始转(transform延迟1秒执行,由于要等待右绿转完),它转的时间要根据度数动态控制,好比总共要转270度,右绿转了180度,因此左绿只须要转90度。这就好办了,为了保持右绿的旋转速度,时间和度数要成比例,右绿转180度用1s,左绿转90度只能用0.5s浏览器
1. 不须要js代码动态实现动画(js只用来计算度数和触发transition) 2. 由于对js几乎没什么依赖,浏览器内核直接渲染,性能较好,过渡天然 3. 代码量不多
1. 由于是css3的属性,兼容不会太好 2. 时间函数只能用线性linear,用默认的ease(不匀速)会衔接不上 3. 只能两种颜色分布,再加一种的话行不通
有更好办法实现相同效果的大佬,欢迎留言!
微信
虽然效果图gif画质有点感人,但仍是能够发现一个问题:内环边缘明显很粗糙!这个要怎么解决呢?
中间这个透明遮罩的代码是`-webkit-mask: radial-gradient(transparent 150px, #000 150px);
个人作法就是把transparent 150px
改为transparent 148px
,就是说空出一两个像素点,让粗糙的部分虚化。
至于为何会出现粗糙,额。。。我以为是150px这一层上了太多颜色,加上原本画弧圈就没有防锯齿处理,色素点可能会拥挤,加重了锯齿状这种效果。具体是什么缘由,或者有更好的解决办法,欢迎大佬指教。微信开发
修改后的效果图
是否是明显好不少~wordpress
上文提到的小程序的css和h5的差别,通过再一次的实验,发现不是小程序内核渲染的问题,应该是微信开发者工具显示的问题。。。但愿尽快能获得改善,否则对开发人员影响挺大的
这个info的盒子margin-top负数在工具中显示翻不上去,但内容50000上去了.
过了几秒再点(啥都没干),这个info的盒子又跑到这里来
为了验证这个info的盒子到底有没有上去,我加了一个红色的盒子,发现并无被info盒子挤掉
取消info的margin-top属性,红色的盒子被挤掉,内容50000也下来了
终于!!!原来都是开发者工具摆的乌龙,其实info盒子一直在上面,只是调试不能正常显示他的位置。。。
话说回来,小程序不能获取DOM节点操做DOM,忽然以为只能数据驱动,不能操做DOM节点有时也挺麻烦的,transition那些须要动态改的样式只能写到style了。。。
最后,看好小程序,但愿各类问题能尽快完善,愈来愈好。