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

帮助阅读

此篇文章主要是为了实现仪表盘功能,前后过了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能出个方案
  • 加油,继续搞
相关推荐
lpfasd12338 分钟前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4563 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai3 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记4 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁4 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu4 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!5 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格5 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人5 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid5 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet