echarts 实现环形渐变

前言

最近产品在ecahrts官网上找到一个 饼图 想要实现这种从头到尾的渐变交互效果,一开始以为非常简单,echarts应该是提供了类似的配置项,知道做起来才发现,这其中没那么简单。

官网案例分析

官网例子中的渐变并不是echarts提供的配置项实现的,而是通过一张 图片 作为背景实现的渐变,所以一开始想着是先来实现一个渐变的饼图,然后通过多个饼图进行拼接来实现类似指针一样的效果,这样就能够实现自定义这个渐变的颜色,并且也很快就写出来一个demo

认识 Echarts 渐变色

在 echarts 的渐变色中,提供了三种类型,包括线性渐变(linear gradient)、径向渐变(radial gradient)和纹理填充(pattern)。

主要了解了一下 线性渐变 以及 径向渐变 的实现效果,在这之后,也意识到了一个严重的问题:通过echarts提供的颜色填充,貌似没办法实现案例里面这种从头到尾的渐变效果,通过线性渐变能够实现下面这种效果

这种固定方向的渐变,但是并不符合我们的要求,

并且我也上网找了一些饼图渐变的案例,发现都是通过这种线性渐变来实现的,只不过会去计算这个渐变的角度,来实现类似从头到尾的渐变,但是一旦进度的幅度较大,就马上露馅了。

  • 例子

可以看到一旦我调大某一个区域的比例,就会发现最后的实现原理还是线性渐变,只不过动态的计算了角度,这种适合多个比例差不多的饼图,但是一旦有某个块比例过大,就还是会出现样式不够美观

奇思妙想

突然意识到,我们最终的目的是自定义这个圆环的起点和终点的颜色,这并不是非得用echarts提供的渐变功能,图片本身并没有问题,图片最大的限制就在于颜色是定好的,但是我们是不是可以让图片的颜色变成动态生成的?

当然可以!

与似乎,就有了下面的方案,通过 canvas 动态生成渐变背景,在讲这张背景图作为圆环的背景图,这样我们就能够实现自定义圆环的起点颜色和终点颜色了

canvas 生成渐变背景

canvas生成背景这个并不是什么难事,百度一下就能够找到类似的案例,然后丢给ai进行美化一下,修改参数变成自己想要的一个函数,我定义的是能够通过传入起点角度,起点颜色,终点颜色 图片大小 四个参数生成一张 base64 的图片

ts 复制代码
/**
 * 创建圆形渐变图片
 * @param startAngle 起始角度
 * @param startColor 起始颜色
 * @param endColor 结束颜色
 * @param size 大小
 * @returns
 */
export function createCircularGradientImage(startAngle = 0, startColor = '#fff', endColor = 'blue', size = 200) {
  // 创建一个canvas元素
  const canvas = document.createElement('canvas')
  // 设置canvas的宽度
  canvas.width = size
  // 设置canvas的高度
  canvas.height = size
  // 获取2D绘图上下文
  const ctx = canvas.getContext('2d')
  // 检查是否成功获取上下文
  if (!ctx) {
    throw new Error('ctx is null')
  }
  // 创建圆锥渐变
  // 参数:起始角度,圆心x坐标,圆心y坐标
  const gradient = ctx.createConicGradient(startAngle, size / 2, size / 2)
  // 添加渐变的起始颜色
  gradient.addColorStop(0, startColor)
  // 添加渐变的结束颜色
  gradient.addColorStop(1, endColor)
  // 设置填充样式并绘制矩形
  ctx.fillStyle = gradient
  ctx.fillRect(0, 0, size, size)
  // 将canvas转换为base64格式的图片数据
  const res = canvas.toDataURL('image/png')
  // 从DOM中移除canvas元素
  canvas.remove()
  // 返回生成的图片数据
  return res
}

最终我们能够得到一张类似这样的图片

结果

接下来的步骤就简单了,参考官网的案例,我们只不过是替换了图片的来源,这样就能够通过传参获得一个自定义颜色的结果。

js 复制代码
const _panelImageURL = createCircularGradientImage(0, '#E5E5FF', 'red')

最后的效果:

至于文字颜色和阴影颜色,这些都有着很明显的配置项,这里就不做过多的赘述了,本文主要是分享一下通过canvas构造图片来实现渐变的这种思路

如果有大佬有更好的实现渐变的思路欢迎评论区留言!

相关推荐
SoaringHeart8 小时前
Flutter最佳实践:键盘辅助视图输入框天添加图片附件
前端·flutter
kyriewen8 小时前
我看完这篇安全论文——AI推荐的npm包,92%是编出来的
前端·javascript·ai编程
小心我捶你啊10 小时前
数据采集和Web解锁不是一回事,从用途到规则区分
前端·爬虫·网络协议
hunterandroid10 小时前
[鸿蒙从零到一] ArkUI 基础组件实战:Text、Image、Button 与 TextInput
前端
fsssb10 小时前
Chromium 源码学习笔记(五):一次点击,在进入 JS 之前先经历了什么?
前端
hunterandroid10 小时前
WorkManager 可靠性实战:唯一任务、重试与幂等设计
android·前端
鹿目10 小时前
使用 Vant CLI 搭建 UI 组件库:从 H5 到小程序跨平台
前端·javascript
默_笙10 小时前
😭 我花了两小时找了一个数据结构 bug,才把"迷你 Cursor"跑起来,绝望(bushi)
前端·javascript
竹林81810 小时前
wagmi v2 监听合约事件踩坑记:从 `useContractEvent` 到 `watchContractEvent`,我重构了三版才搞定实时数据流
前端·javascript