繪圖需求:SVG 和 Canvas
基於SVG和Canvas,百度推出了Echarts圖形庫。
(更多api用法可查看官網文檔)
瀏覽器繪圖原理:
編寫的前端代碼最終都將經過瀏覽器渲染成一個頁面。瀏覽器繪圖通過HTML,還可以通過Canvas和SVG的方式來繪圖。實際上,HTML、CSS實際都是針對瀏覽器繪圖做出一些指令。
(關於SVG和Canvas的具體用法,可查看我的其他博文)
canvas繪圖:通過canvas創建的畫布內容允許自己去對內容繪製。
canvas只創建,內容需要我們填充:
canvas這些中的元素是無法被選中的,和dom不同。如果做canvas動畫就需要不停的刷新canvas畫布。
canvas在很多語言和編程方向中道理都是一致的,例如android中的canvas和flutter等:
SVG繪圖:表示矢量繪圖。
通過html標籤進行繪圖。canvas繪圖無法被選中。SVG繪製的可以被選中。
放大圖,canvas會有鋸齒失真,而SVG不會。
Canvas更適合做高性能的動畫渲染,Echarts支持canvas和svg。
爲了減少canvas失真,一般:
- 開啓抗鋸齒
- 對圖形的分辨率做的更大一些,然後對其進行縮放
Echarts:
可以解析爲canvas和svg版本。
1.簡單的案例體驗:
引入後編寫代碼:
Echarts+Webpack:
然後就可以使用webpack命令了:
現在報錯是因爲還沒創建webpack配置文件:
引入echarts:
然後
直接引用模塊化是錯誤的,需要使用webpack構建,引用構建後的源碼:
然後修改引入:
常見Echarts圖表:
可查看官網,相當豐富
實操:ECharts4實現數據報表組件(vue)
APP.vue:
<template>
<div id="app">
<sales-report></sales-report>
</div>
</template>
<script>
import SalesReport from '@/components/SalesReport'
export default {
name: 'App',
components: {
SalesReport,
}
}
</script>
<style>
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
background: #eee;
}
#app {
width: 100%;
height: 100%;
padding: 20px;
box-sizing: border-box;
}
</style>
index.vue:
<template>
<div class="language-report">
<div class="header">編程語言hot榜</div>
<div class="content">
<div class="content-title-wrapper">月增長率</div>
<div class="content-index-wrapper">
<span class="arrow-star">
<svg width="100" height="100" viewBox="0 0 190 180"
fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M95 0L117.227 68.4073H189.155L130.964 110.685L153.191 179.093L95 136.815L36.8093 179.093L59.0361 110.685L0.845406 68.4073H72.7731L95 0Z" fill="#f1c40f"/>
</svg>
</span>
<span class="percentage">98<span>%</span></span>
<span class="text">+99,999</span>
</div>
<div id="content-chart"/>
<div class="content-circle-wrapper">
<div
:class="['circle', selectedIndex === index ? 'selected' : '']"
@click="change(index)"
v-for="(item,index) in circle"
:key="index"/>
</div>
<div class="content-bottom-wrapper">編程語言流行趨勢</div>
</div>
<div class="footer">
<div class="footer-wrapper">
<div class="left">
<div class="footer-title">Go使用人數</div>
<div class="footer-sub-title">5月累計人數</div>
</div>
<div class="right">
<small>人</small> 300,254,00
</div>
</div>
<div class="progress-wrapper">
<div class="progress-bg">
<div class="progress-current" :style="{width:`${progress*100}%`}"></div>
</div>
</div>
<div class="footer-text">
<div>人數增長率</div>
<div>89%</div>
</div>
</div>
</div>
</template>
<script>
import ECharts from 'echarts';
export default {
data() {
return {
circle: new Array(3),
selectedIndex: 0,
progress: 0.75,
}
},
methods: {
change(index) {
this.selectedIndex = index;
this.genChart();
},
genChart() {
// 獲取數據源
const mockData = [];
for (let i=0;i<10;i++){
mockData.push(Math.floor( Math.random() * 100) + 200)
}
// 獲取chart對應的dom
const chartDom = document.getElementById('content-chart')
// 初始化echarts對象
const chart = ECharts.init(chartDom)
// 渲染參數
const options = {
xAxis: {
type: 'category',
show: false,
},
yAxis: {
show: false,
min: 0,
max: 400,
},
series: [{
data: mockData,
type: 'line',
smooth: true,
areaStyle: {
color: '#1abc9c'
},
lineStyle: {
width: 4,
color: '#2ecc71'
},
itemStyle: {
borderWidth: 8,
color: '#3498db'
}
}],
grid: {
top: 0,
bottom: 0,
right: -30,
left: -30,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
}
}
// 渲染圖表
chart.setOption(options)
},
},
mounted() {
this.genChart();
this.task = setInterval(() => {
let index = this.selectedIndex
index++
if(index > this.circle.length){
index = 0;
}
this.change(index)//
}, 3000);
},
destroyed() {
if(this.task){
clearInterval(this.task)
}
},
}
</script>
<style lang="scss">
.language-report {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background: #fff;
box-shadow: 0 2px 8px rgba(4,9,20,.3),0 2px 8px rgba(4,9,20,.3),0 2px 8px rgba(4,9,20,.3),0 2px 8px rgba(4,9,20,.3);
.header {
width: 100%;
height: 50px;
background: orange;
border-bottom: 2px solid #eee;
box-sizing: border-box;
color: rgba(13,27,62,.7);
padding-left: 20px;
display: flex;
align-items: center;
font-weight: bold;
color: #fff;
}
.content {
flex: 1;
width: 100%;
padding: 0 28px;
box-sizing: border-box;
display: flex;
flex-direction: column;
.content-title-wrapper {
padding-top: 28px;
color: #1abc9c;
font-size: 13px;
font-weight: bold;
}
.content-index-wrapper {
display: flex;
align-items: center;
.arrow-star {
svg {
width: 25px;
}
}
.percentage {
font-size: 35px;
font-weight: 700;
color: #333;
margin-left: 15px;
span {
font-size: 28px;
font-weight: 400;
color: #999;
margin-left: 2px;
}
}
.text {
margin-left: 15px;
color: #1abc9c;
font-weight:bold;
}
}
#content-chart {
flex: 1;
width: 100%;
}
.content-circle-wrapper {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
.circle {
width: 10px;
height: 10px;
background: #fff;
border: 3px solid #3498db;
border-radius: 50%;
margin: 0 5px;
&.selected {
background: #3498db;
}
}
}
.content-bottom-wrapper {
margin: 10px 0;
color: #999;
}
}
.footer {
display: flex;
flex-direction: column;
width: 100%;
height: 120px;
border-top: 2px solid #eee;
box-sizing: border-box;
.footer-wrapper{
display: flex;
padding: 14px 14px 0;
.left {
.footer-title {
font-size: 13px;
font-weight: 700;
color: #333;
}
.footer-sub-title {
font-size: 13px;
font-weight: 400;
color: #999;
}
}
.right {
flex: 1;
text-align: right;
color: #1abc9c;
font-size: 25px;
font-weight: 700;
small {
font-weight: 400;
}
}
}
.progress-wrapper {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 14px;
.progress-bg {
position: relative;
width: 100%;
height: 7px;
background: #95a5a6;
border-radius: 3px;
.progress-current {
position: absolute;
left: 0;
top: 0;
height: 7px;
background: #3498db;
border-radius: 3.5px;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
background: #fff;
opacity: 0;
animation: progress-active 2s ease infinite
}
@keyframes progress-active {
from {
width: 0;
opacity: 0;
}
to {
width: 100%;
opacity: .3;
}
}
}
}
}
.footer-text {
display: flex;
justify-content: space-between;
padding: 0 14px 14px;
font-size: 13px;
color: #999;
}
}
}
</style>