摘要:先上效果图这种图形大家应该都见过,俗称仪表盘,当然,上图只是个最基本的仪表盘架子,可能在实际场景中还会其他很多花里胡哨的点缀,那些暂且不管,不是关键,这东西经常见到,但还没亲自上手在代码层面实现过,最近做的一个需求恰好有这个场景,这里归
先上效果图:
这种图形大家应该都见过,俗称仪表盘,当然,上图只是个最基本的仪表盘架子,可能在实际场景中还会其他很多花里胡哨的点缀,那些暂且不管,不是关键,这东西经常见到,但还没亲自上手在代码层面实现过,最近做的一个需求恰好有这个场景,这里归纳一下
canvas实现大部分情况下,对于这种偏可视化的元素,一般都选择使用 canvas来进行绘制,现在已经 9120年了,线上使用 canvas完全没问题
仪表盘整体是一个复杂图形,而复杂图形是由简单图形组合而成,只要把所有组成这个仪表盘的简单图形绘制出来,再进行组合,整个仪表盘自然也就绘制出来了
所以,首先对仪表盘进行分解,分解成 canvas能绘制出的基本图形,其主体其实就两个圆弧,一个是底部蓝色的半圆轨道,一个是代表进度的红色圆弧,其实都是圆弧,canvas刚好有绘制圆弧的能力,即:
ctx.arc
至于动态绘制,只需要配合 requestAnimationFrame即可
const trackW = 6
const rx = 500
const ry = 500
const radius = 400
const innerLineW = 20
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
function draw (toAngle, currentAngle = Math.PI) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 半圆轨道
ctx.beginPath()
ctx.strokeStyle = "#ad80fc"
ctx.lineWidth = trackW
ctx.arc(rx, ry, radius, Math.PI, 0, false)
ctx.stroke()
// 圆弧
ctx.beginPath()
ctx.lineCap = "round"
ctx.strokeStyle = "#fe4d55"
ctx.lineWidth = innerLineW
ctx.arc(rx, ry, radius, Math.PI, currentAngle, false)
ctx.stroke()
if (currentAngle < toAngle) {
currentAngle += 0.02
if (currentAngle > toAngle) currentAngle = toAngle
requestAnimationFrame(() => {
draw(toAngle, currentAngle)
})
}
}
draw(1.5 * Math.PI)
加上变量定义,花括号等几十行代码即可完成,由此可见,canvas绘图还是很方便的,所以在可视化领域,例如一些库或者UI组件基本上都是以canvas进行构建
css绘制canvas实质上就是借助 js操纵浏览器 API进行渲染,然而 UI渲染这种事情本应该交给 CSS来做才是,感觉用 js直接画多影响性能啊(实际上并不),哪有 css来的流畅,实际上,css完全可以做到
从 css的角度对仪表盘进行分解,同样还是两个圆弧,通过设置 border-radius属性即可让元素呈现整圆效果,然后再用一个矩形元素进行遮罩,决定展现出来的部分,即为圆弧,通过控制遮罩的面积来呈现动态绘制的效果
<div class="arc-wrapper">
<p class="track-arc">p>
<div class="round-box">
<p class="round">p>
div>
div>
:root {
--arcRadius: 200px;
--rectWidth: calc(var(--arcRadius) * 2);
--trackWidth: 4px;
--roundWidth: 10px;
}
.arc-wrapper {
position: relative;
margin: 0 auto;
width: var(--rectWidth);
height: var(--arcRadius);
overflow: hidden;
background-color: pink;
}
.track-arc {
width: 100%;
height: var(--rectWidth);
box-sizing: border-box;
border-radius: 50%;
border: var(--trackWidth) solid #ad80fc;
}
.round-box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
transform-origin: 50% 100%;
transform: rotate(-45deg);
z-index: 20;
}
.round {
width: 100%;
height: var(--rectWidth);
box-sizing: border-box;
border-radius: 50%;
border: var(--roundWidth) solid #fe4d55;
}
其实没多少代码,也没什么难以理解的,只不过效果似乎微调:
由于圆弧的线是存在宽度的,并不是数学意义上的可以忽略,canvas绘制圆弧,是根据圆心坐标和半径进行绘制的,绘制出来的圆弧会自动根据圆弧 line的宽度进行调整,即圆弧的半径是圆弧线的中心位置与圆心坐标距离
而通过 css绘制的圆弧,此圆弧的半径则是圆弧最外层边线与圆心的坐标距离:
知道了问题其实就好解决了,只要缩减轨道半圆的半径,并对其进行一定的偏移即可:
.track-arc {
--trackArcSize: calc(var(--rectWidth) - var(--roundWidth) + var(--trackWidth));
/* 尺寸改变 */
width: var(--trackArcSize);
height: var(--trackArcSize);
box-sizing: border-box;
border-radius: 50%;
border: var(--trackWidth) solid #ad80fc;
/* 位置偏移 */
transform: translate(calc(var(--roundWidth) / 2 - var(--trackWidth) / 2), calc(var(--roundWidth) / 2 - var(--trackWidth) / 2));
}
然后就顺眼多了:
然而,还有个问题,一般为了呈现更加圆润的效果,设计稿上圆弧的断点处一般都是圆头:
而上述呈现出来的效果是直接截断的:
一般人之所以不使用 css来绘制仪表盘,基本都是因为这个原因,canvas简简单单通过设置一个 ctx.lineCap = "round"就能解决的问题。似乎 css无解了
乍一看好像确实没什么好办法,但稍微思考下,这不就是一个圆角吗,完全在css能力范围内啊,只不过实现的方式不太那么直接罢了
方法很简单,就是使用一个圆角矩形覆盖在圆弧的顶端,将圆弧本身的矩形顶端覆盖住,圆角矩形当做是圆弧的顶端,这样视觉上看起来不就是圆头了吗
<div class="round-box">
<p class="round">p>
<p class="dot-r-box">
<span class="dot-r">span>
p>
div>
.dot-r-box {
position: absolute;
right: 0;
bottom: 0;
width: var(--roundWidth);
height: var(--dotHeight);
background-color: var(--backColor);
}
.dot-r {
display: inline-block;
width: 100%;
height: 100%;
/* 这里的100px只是为了呈现出最大限度的圆角 */
border-bottom-left-radius: 100px;
border-bottom-right-radius: 100px;
background-color: var(--roundColor);
}
效果如下:
圆角顶端 get
同样的,圆弧左边的顶端也可以这么做
不过左边这个顶端有个稍微需要注意的地方,因为其存在的目的是为了当做圆弧的左断点,但是当进度为 0的时候,圆弧应该是完全不展现的,或者当进度很小的时候,圆弧应该展现的长度还没有 dot-l的高度大,这样就露馅了:
不过呢转而又一想,一般实际场景中,就算进度为 0,我们其实为了看起来更符合常识直觉,也会让圆弧展现一点点出来,只要 dot-l的高度不是太大,或者说只要圆弧的宽度不要太宽,其实预留的这点圆弧完全就可以 cover住了,不至于露馅
小结css的新特性 var 和 calc还挺好用的嘛
本文示例的 Live Demo已经上传,感兴趣的可以亲自试下
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/7023.html
摘要:先上效果图这种图形大家应该都见过,俗称仪表盘,当然,上图只是个最基本的仪表盘架子,可能在实际场景中还会其他很多花里胡哨的点缀,那些暂且不管,不是关键,这东西经常见到,但还没亲自上手在代码层面实现过,最近做的一个需求恰好有这个场景,这里归先上效果图: showImg(https://user-gold-cdn.xitu.io/2019/5/23/16ae28a94cb51d3e); 这种图形大...
小编写这篇文章的主要目的,主要还是去进行讲解一些关于Python pyecharts绘制仪表盘的一些讲解,具体怎么去进行操作呢?下面就给大家详细解答下。 仪表盘 仪表盘的效果我只能说炫酷而已,如果想要运用在实际的场景中,我其实也不清楚那个场景比较适合,但是pyecharts毕竟是炫酷可视化的利器,炫酷自然也就有它了。 小汽车仪表盘是长这样的,下面我们来看看pyecharts的仪表盘是怎么...
在vue项目中canvas实现截图功能是常用的,下面是具体代码: 实现效果: 在vue项目中做的一个截图功能(只能够截取图片),只用鼠标就可以在画面中进行框选截取。 实现:做一个弹窗,打开弹窗的时候传入要截的图,接下来在这个窗口里面,点击截图按钮,开始截图;点击取消按钮,取消截图。 窗口里面的html主要是三个部分,一个是可截图区域,一个是截取图片的回显,一个是操作按钮(截图按钮和取消...
访问时间超过3S对于用户就十分痛苦,为考虑到用户访问效果。为此我,首屏加载时间一顿操作,基本都在2s左右,这样的首屏加载时间,对于用户来说,算是可以接受的。 那我都哪些操作?下面就为大家展示 打包分析 在 package.json 中添加命令 "report":"vue-cli-servicebuild--report" 然后命令行执行npm ...
上传视频要提供视频封面(视频封面必填),这是在开发中实际问题。封面可以用户自己制作并上传,但这样脱离网站,体验不好,常见的处理方案就是用户未选择或上传封面时,自动截取视频第一帧作为封面,但这样并不友好。因此考虑视频上传后,在播放中由人员自行截取画面作为视频封面。 简单效果如图: 前端代码如下: <template> <div> <videosrc=&...
阅读 1041·2021-11-23 10:05
阅读 1747·2021-11-12 10:36
阅读 1810·2019-08-30 15:56
阅读 1660·2019-08-29 12:32
阅读 3010·2019-08-28 18:04
阅读 3393·2019-08-26 12:17
阅读 2479·2019-08-26 11:35
阅读 1158·2019-08-23 15:11