从‘相信前端能做一切’到‘连这个都做不了么’

帮助阅读

此篇文章主要是为了实现仪表盘功能,前后过了4种方案,每篇方案从逻辑、代码、效果、问题四个方面出发。最后个人总结。同时非常非常希望有大佬能够提供一个方案,个人实在想不到实现方案了

需求

h5页面中,做一个环形仪表盘(如下图),需要一个从0%到实际百分比的增长过渡动效

前提

使用前端原生Html、css、js语言实现, 不打算借助第三方插件。

最初Scheme

将UI图片作为背景,上面放一个白色div作为遮罩,再利用css3将白色div旋转,从而达到过渡效果。

代码如下:

xml 复制代码
<style>
		.light-strip {
			width: 500px;
			height:500px;
			border: 1px solid #efefef;
			background-image: url('Frame 29@3x.png');
			float: right;
			background-size: 100% 100%;
		}
		.light-strip-top {
			margin-top: 0%;
			width: 500px;
			height: 250px;
			background: #fff;
			transform-origin: bottom center;
			/* transform: rotate 5s ; */
			rotate: 0deg;
			transition: all 2s ease-in-out;
		}
	</style>
	<body onload="load()">
		<div class="light-strip">
			<div class="light-strip-top">
				
			</div>
		</div>
	</body>
	<script>
		function load() {
			setTimeout(() => {
				document.querySelectorAll('.light-strip-top')[0].setAttribute('style', "rotate: 180deg")
			}, 1000)
		}
	</script>

效果如下:

出现问题:

由于仪表盘整体大于180度,所以白色div,在最开始遮挡全部仪表盘,那么旋转一定角度后一定会覆盖UI图。

进化Scheme

根据上面出现的问题,想到与UI沟通将仪表盘改成180度效果(解决不了问题,就把问题解决掉),该方案由于改变了原型之后会导致UI过于丑,就没有进行深度测试。

超进化Scheme

根据上面两个方案的结合,想到将方案1中的白色div换成一张指针图片,利用css3旋转追针,达到过渡效果,但此方案也是改了UI效果。

代码如下:

xml 复制代码
	<style>
		.light-strip {
			width: 500px;
			height:500px;
			border: 1px solid #efefef;
			background-image: url('Frame 29@3x.png');
			/* background-color: #fff; */
			float: right;
			background-size: 100% 100%;
		}
		.light-strip-top {
			margin-top: 50%;
			width: 49%;
			height: 4px;
			background: red;
			transform-origin: center right;
			/* transform: rotate 5s ; */
			rotate: -35deg;
			transition: all 2s ease-in-out;
		}
		
	</style>
	<body onload="load()">
		<div class="light-strip">
			<div class="light-strip-top">
				
			</div>
		</div>
	</body>
	<script>
		function load() {
			setTimeout(() => {
				document.querySelectorAll('.light-strip-top')[0].setAttribute('style', "rotate: 90deg")
			}, 1000)
		}
	</script>

效果如下:

Now:

此时大脑宕机了,在我的前端知识基础上,想不到能够完美实现UI效果的方案了。于是和同事探讨了一下,了解到element-plus中的进度条有类似的效果,于是打算看一下源码,了解到它是svg实现的。发现新大陆又开始尝试svg实现。

究极进化Scheme

利用svg,做一个带白色的背景圆环A,再做一个带有渐变背景色的进度圆环B, 利用进度圆环的偏移值、显示长度、断口长度配合css3过渡实现过渡效果。

代码如下:

xml 复制代码
 <style>
    body {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      background-color: #f5f5f5;
    }

    .dashboard {
      position: relative;
      width: 200px;
      height: 200px;
	  background-size: 100% 100%;
    }

    .circle-background {
      fill: none;           /* 不填充 */
      stroke: #fff;          /* 圆环的颜色 */
      stroke-width: 10;      /* 圆环的宽度 */
	  stroke-dasharray: 200, 52; /* 圆环断开部分的长度,总长度为周长 */
	  stroke-dashoffset: 163;
	  stroke-linecap: round;
	  border-radius: 10;
	  transition: all 1s; /* 过渡效果时间 */
    }

    .circle-progress {
      fill: none;           /* 不填充 */
      stroke: url(#gradient);       /* 圆环的颜色 */
      stroke-width: 10;      /* 圆环的宽度 */
      stroke-dasharray: 252, 0; /* 圆环断开部分的长度,总长度为周长 */
      stroke-dashoffset: 163;
      stroke-linecap: round; /* 圆滑断点 */
      transition: all 1s; /* 过渡效果时间 */
    }

    .percentage {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 24px;
      color: #3498db;
    }
  </style>
</head>
<body>

<svg class="dashboard" viewBox="0 0 100 100">
	<!-- 定义渐变色 -->
	  <defs>
	   <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="50" y1="0" x2="50" y2="100%">
	          <stop offset="0%" style="stop-color: rgba(111, 232, 191, 1)" />
	          <stop offset="33%" style="stop-color: rgba(255, 175, 19, 1)" />
	          <stop offset="70%" style="stop-color: rgba(222, 19, 80, 1)" />
	          <stop offset="100%" style="stop-color: rgba(133, 14, 205, 1)" />
	        </linearGradient>
	  </defs>
	
  <!-- 背景圆环 -->
  <circle class="circle-background" cx="50" cy="50" r="40"></circle>
  
  <!-- 进度圆环 -->
  <circle class="circle-progress" cx="50" cy="50" r="40"></circle>

</svg>

<!-- 进度百分比显示 -->
<div class="percentage" id="percentage">0%</div>

<script>
  function setProgress(percentage) {
    const circleProgress = document.querySelector('.circle-progress');
	const circleBackground = document.querySelector('.circle-background');
    const percentageText = document.getElementById('percentage');

    const circumference = 2 * Math.PI * 40; // 圆的周长
	const circumNewLength = (percentage / 100) * (circumference - 52);
    const dashOffset = 163 - circumNewLength;

	
    // 设置进度圆环的样式
    circleBackground.style.strokeDashoffset = dashOffset;
	circleBackground.style.strokeDasharray = `${200 - circumNewLength}, ${ 52 + circumNewLength }`
	circleProgress.style.strokeDasharray = `${circumNewLength}, ${ circumference - circumNewLength }`
    
    // 更新百分比文本
    percentageText.textContent = `${percentage}%`;
  }

  // 设置初始进度为0%
  setProgress(0);

  // 模拟过渡效果,从0%到50%
  setTimeout(() => {
    setProgress(50);
  }, 1000); // 过渡时间为1秒,你可以根据需要调整这个值
</script>

效果如下:

问题:

基本实现,但是还有一个问题是,渐变色是两点之间的线性渐变,无法做到圆环的顺时针渐变。

总结

  • 单纯前端不是万能的😂😂😂😂
  • 个人认为这个需求还是能够实现的
  • 希望有da lao能出个方案
  • 加油,继续搞
相关推荐
慧一居士2 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead4 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_7 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说7 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js