引子:ui设计出一个这样的效果,你打算怎么实现?
我是用canvas实现的,开发了一个组件,通过配置参数props可以设置宽高,颜色(自己根据ui设计改组件里的源码),缝隙宽度等属性。代码如下:
<template><div class="progressBarStyle"> <el-row> <el-col :span="24"> <div class="canvasStyle"> <canvas id="progressBarCanvas" width="610" height="70"> 此浏览器不支持canvas! </canvas> </div> </el-col> </el-row></div></template>
<script>export default { name: 'progressBar', props: { settingParams: { type: Object, default () { return {} } } }, data () { return { defaultParams: { // 此数值取7~92之间,不然图会变形。0和100单独处理 progressNum: 8, // 宽度 progressW: 600, // 高度 progressH: 48, // 中间缝隙宽度 gapW: 10 } } }, mounted () { // 合并参数 this.defaultParams = Object.assign({}, this.defaultParams, this.settingParams) // 初始化绘图 this.initProgressBar() }, watch: { defaultParams () { this.initProgressBar() } }, methods: { /** * 绘制左边 * leftLenBottom 左边图的底部宽度 * leftLenTop 左边图的顶部宽度 * */ renderLeft (leftLenBottom, leftLenTop) { let pCan = document.getElementById('progressBarCanvas') let pCo = pCan.getContext('2d') let gradient = pCo.createLinearGradient(32, 0, this.defaultParams.progressW, 0) gradient.addColorStop(0, '#FF8686') gradient.addColorStop(1, '#E98245')
let gradient1 = pCo.createLinearGradient(32, 0, this.defaultParams.progressW, 0) gradient1.addColorStop(0, 'rgba(221,151,20,0.47)') gradient1.addColorStop(1, 'rgba(206,110,77,1)') pCo.strokeStyle = gradient pCo.fillStyle = gradient1
pCo.beginPath() pCo.moveTo(32, 0) pCo.lineTo(32, this.defaultParams.progressH) pCo.lineTo(leftLenBottom, this.defaultParams.progressH) pCo.lineTo(leftLenTop, 0) pCo.closePath() pCo.stroke() pCo.fill() }, /** * 绘制右边 * rightLenBottom 右边图的底部宽度 * rightLenTop 右边图的顶部宽度 * */ renderRight (rightLenBottom, rightLenTop) { let pCan = document.getElementById('progressBarCanvas') let pCo = pCan.getContext('2d') let gradient2 = pCo.createLinearGradient(0, 0, this.defaultParams.progressW, 0) gradient2.addColorStop(0, '#6BE5FF') gradient2.addColorStop(1, '#3AEC96') let gradient3 = pCo.createLinearGradient(0, 0, this.defaultParams.progressW, 0) gradient3.addColorStop(0, 'rgba(121,246,211,0.49)') gradient3.addColorStop(1, 'rgba(58,120,236,0.53)') pCo.strokeStyle = gradient2 pCo.fillStyle = gradient3
pCo.beginPath() pCo.moveTo(rightLenTop + this.defaultParams.gapW, 0) pCo.lineTo(this.defaultParams.progressW, 0) pCo.lineTo(this.defaultParams.progressW, this.defaultParams.progressH) pCo.lineTo(rightLenBottom + this.defaultParams.gapW, this.defaultParams.progressH) pCo.closePath() pCo.stroke() pCo.fill() }, // 绘图 initProgressBar () { let pCan = document.getElementById('progressBarCanvas') let pCo = pCan.getContext('2d') pCo.clearRect(0, 0, this.defaultParams.progressW, this.defaultParams.progressH) let len = this.defaultParams.progressNum let leftLenBottom = 0 let leftLenTop = 0 // 输入的progressNum数字小于0按0处理 if (len <= 0) { leftLenBottom = 0 leftLenTop = 0 this.renderRight(leftLenBottom, leftLenTop) } else if (len >= 100) { // 输入的progressNum数字大于100按全长处理 leftLenBottom = this.defaultParams.progressW leftLenTop = this.defaultParams.progressW this.renderLeft(leftLenBottom, leftLenTop) } else { // 一般情况处理,当gapW变化时,这里可能还需要调整 len = len < 7 ? 7 : len len = len > 92 ? 92 : len
leftLenBottom = this.defaultParams.progressW * len / 100 + 36 leftLenTop = this.defaultParams.progressW * len / 100 - 10
this.renderLeft(leftLenBottom, leftLenTop) this.renderRight(leftLenBottom, leftLenTop) } } }}</script>
<style lang="scss" scoped>.progressBarStyle { width: 100%; height: 76px;}.canvasStyle { text-align: left;}</style>
使用的方法和一般的组件使用一样,
import progressBar from './progressBar'
在components
内注册一下:
<progressBar :settingParams="{progressNum: videoStorageData.used * 100, gapW: 16, progressH: 20, progressW: 400}" />
ok,这样就可以了。改进的地方就是对传进来的props参数是极端值时的处理。代码中已有一些写法,还有就是做到颜色可配置,多传几个参数即可。