css实现
canvas实现
css实现
效果图
代码
<template>
<!-- 间隔柱状图 -->
<div :id="barId" class="bar-wrap">
<div class="bar-bg">
<div class="bar" v-for="(item, index) in 27" :key="index"></div>
</div>
<div class="bar-contian" :style="`width: ${percent || 0}%`">
<div
class="bar"
:style="`background: ${color}`"
v-for="(color, index) in colorArr"
:key="index"
></div>
</div>
</div>
</template>
<script>
export default {
name: "intervalBarCharts",
props: {
percent: {
required: true,
type: Number,
},
},
data() {
return {
barId: "",
colorArr: [],
};
},
watch: {
percent: {
handler(val) {
if (!this.barId) {
this.barId = `intervalBar${this.guid()}`;
}
this.$nextTick(() => {
this.drawBar();
});
},
immediate: true,
deep: true,
},
},
methods: {
guid() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0;
const v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
},
drawBar() {
if (this.percent) {
const step = this.percent * 0.27;
this.colorArr = this.gradientColor([0, 118, 255], [0,227,255], step);
}
},
gradientColor(startRGB, endRGB, step) {
let startR = startRGB[0];
let startG = startRGB[1];
let startB = startRGB[2];
let endR = endRGB[0];
let endG = endRGB[1];
let endB = endRGB[2];
let sR = (endR - startR) / step; // 总差值
let sG = (endG - startG) / step;
let sB = (endB - startB) / step;
let colorArr = [];
for (let i = 0; i < step; i++) {
let color = `rgb(${sR * i + startR},${sG * i + startG},${sB * i + startB})`;
colorArr.push(color);
}
return colorArr;
},
},
};
</script>
<style lang="less" scoped>
.bar-wrap {
width: 100%;
height: 100%;
position: relative;
.bar-bg {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.bar {
height: 100%;
width: 8px;
flex-shrink: 0;
margin-right: 4px;
border-radius: 4px;
background: #043147;
&:last-child {
margin-right: 0;
}
}
}
.bar-contian {
position: absolute;
left: 0;
top: 0;
height: 45px;
overflow: hidden;
display: flex;
align-items: center;
.bar {
height: 100%;
width: 8px;
flex-shrink: 0;
margin-right: 4px;
border-radius: 4px;
&:last-child {
margin-right: 0;
}
}
}
}
</style>
canvas实现
效果图
代码
<template>
<div class="g-emergency-level">
<div class="content">
<div v-for="(item, index) in data" :key="index" class="item">
<div class="chart-bg">
<div class="ratio">{{ item.ratio }}</div>
<div class="bar-contain" :style="{ width: width + 'px', height: height + 'px'}">
<canvas :id="`level-ratio-${item.name}`"></canvas>
</div>
</div>
<div class="tag">{{ item.name }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'GEmergencyLevel',
props: {
data: {
required: true,
type: Array,
default: [
{
ratio: '95%',
name: '完好率',
start: 'rgba(22,255,216,0.25)',
end: 'rgba(22,255,243,0.10)',
line: '#00FFD5'
}
],
},
width: {
required: false,
type: Number,
default: 77,
},
height: {
required: false,
type: Number,
default: 114,
}
},
data() {
return {}
},
watch: {
data: {
handler(val) {
this.$nextTick(() => {
this.drawChart()
})
},
immediate: true,
deep: true,
}
},
methods: {
drawChart() {
this.data.map(item => {
let height = parseFloat(item.ratio) * this.height / 100
let context = document.getElementById(`level-ratio-${item.name}`)
let ctx = context.getContext('2d')
let my_gradient = ctx.createLinearGradient(0, this.height - height, 0, height)
my_gradient.addColorStop(0.02, item.start)
my_gradient.addColorStop(1, item.end)
// 画渐变区域
ctx.lineWidth = this.width * 2
ctx.setLineDash([2])
ctx.strokeStyle = my_gradient
ctx.beginPath()
ctx.moveTo(0, this.height)
ctx.lineTo(0, this.height - height)
ctx.stroke()
// 画头顶线
ctx.beginPath()
ctx.setLineDash([0])
ctx.lineWidth = 2
ctx.strokeStyle = item.line
ctx.moveTo(0, this.height - height)
ctx.lineTo(this.width, this.height - height)
ctx.stroke()
ctx.closePath()
})
},
},
}
</script>
<style lang="less" scoped>
.g-emergency-level {
height: 230px;
width: 100%;
display: flex;
align-items: center;
.content {
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
.item {
width: 98px;
height: 150px;
.chart-bg {
width: 100%;
height: 100%;
background: url('./images/bg_zhanbi.png') center/100% 100% no-repeat;
.ratio {
font-family: DINAlternate-Bold;
font-size: 20px;
color: #ffffff;
text-align: center;
font-weight: 700;
position: relative;
top: -10px;
}
.bar-contain {
width: 100%;
height: 100%;
margin: 0 auto 2px;
}
}
.tag {
font-family: MicrosoftYaHeiUI;
font-size: 14px;
color: #FFFFFF;
letter-spacing: 0;
text-align: center;
font-weight: 400;
}
}
}
}
</style>