首页 > 其他分享 >Vue【原创】数据可视化,复合数字形式展示

Vue【原创】数据可视化,复合数字形式展示

时间:2023-08-24 15:13:42浏览次数:35  
标签:blue Vue return color percent 复合 可视化 dataProvider unit

做数据可视化的时候,经常碰到需要很灵活的数字形式展示。

先上个效果图:

 如图包括名称,数量,别名,单位,上升下降,环比等等的复合数据展示,并且需要支持样式灵活配置。

此组件包括2个模块,父容器组件box-group,其中每一项的子组件box。

 

父组件 box-group

 1 <template>
 2     <div class="box-group">
 3         <div class="box-wrapper" v-for="(item, index) in dataProvider" :key="index" v-if="index < dataProvider.length && index % col == 0">
 4             <box
 5                 class="item"
 6                 :theme="theme"
 7                 :style="{ marginBottom: lineGap }"
 8                 v-for="(bb, idx) in colArray"
 9                 :dataProvider="dataProvider[index + idx]"
10                 :key="idx"
11                 :openType="openType"
12                 @selected="selected"
13             ></box>
14         </div>
15     </div>
16 </template>
17 
18 <script>
19 import Box from './components/box.vue';
20 
21 export default {
22     name: 'LiloBoxGroup',
23     props: {
24         col: {
25             type: Number,
26             default: 2
27         },
28         theme: {
29             type: String,
30             default: 'blue'
31         },
32         lineGap: {
33             type: String,
34             default: '10px'
35         },
36         dataProvider: {
37             type: Array,
38             default() {
39                 return [
40                     // { label: '总人口数', value: '123213', unit: '人', color: '#ff0000' },
41                     // { label: '总户数', value: '123213', unit: '户', color: '#123312' },
42                     // { label: '总人口数', value: '123213', unit: '人', color: '#235234' },
43                     // { label: '总户数', value: '123213', unit: '户', color: '#444444' }
44                 ];
45             }
46         },
47         openType: {
48             type: String,
49             default: 'popup'
50         }
51     },
52     data() {
53         return {};
54     },
55     components: {
56         Box
57     },
58     mounted() {},
59     computed: {
60         colArray() {
61             let result = [];
62             for (let i = 0; i < this.col; i++) {
63                 result.push(i);
64             }
65             return result;
66         }
67     },
68     methods: {
69         selected(data) {
70             this.$emit('selected', data);
71         }
72     }
73 };
74 </script>
75 
76 <style lang="scss" scoped>
77 .box-group {
78     .box-wrapper {
79         display: flex;
80         margin-top: 5px;
81         .item {
82             flex: 1;
83         }
84     }
85 }
86 </style>

 

子组件 box

  1 <template>
  2     <div class="box">
  3         <div class="icon-wrapper"><div class="icon" :style="iconStyle" v-if="dataProvider"></div></div>
  4         <div class="box-wrapper" v-if="dataProvider">
  5             <div class="label" :style="labelStyle">{{ dataProvider.label }}</div>
  6             <div @click="goTo">
  7                 <span class="value" :style="valueStyle" v-if="valueShow">{{ dataProvider.value | toThousandFilter }}</span>
  8                 <span class="alias" :style="aliasStyle">{{ dataProvider.alias }}</span>
  9             </div>
 10             <div class="unit" :style="unitStyle" v-if="valueShow">
 11                 {{ dataProvider.unit }}
 12                 <span v-if="dataProvider.hasOwnProperty('percent') && dataProvider.percent" 
 13                     class="percent" :style="percentStyle" v-html="percentFormatter"></span>
 14                 <span v-if="dataProvider.hasOwnProperty('trend') && dataProvider.trend" 
 15                     class="trend" :style="trendStyle" v-html="trendFormatter"></span>
 16             </div>
 17         </div>
 18         <!-- <component ref="component" :is="openType" /> -->
 19     </div>
 20 </template>
 21 
 22 <script>
 23 import variables from '../../../../src/styles/variables.scss';
 24 // import Popup from './popup.vue';
 25 // import Drawer from './Drawer.vue';
 26 export default {
 27     name: 'LiloBox',
 28     // components: {
 29     //     Popup,
 30     //     Drawer
 31     // },
 32     props: {
 33         dataProvider: {
 34             type: Object,
 35             default() {
 36                 return null;
 37             }
 38         },
 39         theme: {
 40             type: String,
 41             default: 'blue'
 42         },
 43         openType: {
 44             type: String,
 45             default: 'popup'
 46         }
 47     },
 48     computed: {
 49         themeObject() {
 50             return {
 51                 icon: variables[this.theme],
 52                 label: variables[this.theme],
 53                 value: variables[this.theme],
 54                 alias: variables[this.theme],
 55                 unit: variables[this.theme]
 56             };
 57         },
 58         valueShow() {
 59             if (this.dataProvider.hasOwnProperty('show')) {
 60                 return this.dataProvider.show;
 61             } else {
 62                 return true;
 63             }
 64         },
 65         iconStyle() {
 66             return {
 67                 'background-color': this.dataProvider.iconColor || this.dataProvider.color || this.themeObject.icon
 68             };
 69         },
 70         labelStyle() {
 71             return {
 72                 color: this.dataProvider.labelColor || this.dataProvider.color || this.themeObject.label,
 73                 fontSize: (this.dataProvider.labelSize || 1) + 'rem'
 74             };
 75         },
 76         valueStyle() {
 77             return {
 78                 color: this.dataProvider.valueColor || this.dataProvider.color || this.themeObject.value,
 79                 fontSize: (this.dataProvider.valueSize || 1.5) + 'rem'
 80             };
 81         },
 82         aliasStyle() {
 83             return {
 84                 color: this.dataProvider.aliasColor || this.dataProvider.color || this.themeObject.alias,
 85                 fontSize: (this.dataProvider.aliasSize || 1) + 'rem'
 86             };
 87         },
 88         unitStyle() {
 89             return {
 90                 color: this.dataProvider.unitColor || this.dataProvider.color || this.themeObject.unit,
 91                 fontSize: (this.dataProvider.unitSize || 1) + 'rem'
 92             };
 93         },
 94         percentStyle() {
 95             return {
 96                 color: this.dataProvider.percent > 0 ? variables.red : variables.deepGreen
 97             };
 98         },
 99         trendStyle() {
100             return {
101                 color: this.dataProvider.trend > 0 ? variables.red : variables.deepGreen
102             };
103         },
104         percentFormatter() {
105             const _percent = this.dataProvider.percent;
106             if (!_percent || _percent === 0) {
107                 return '';
108             }
109             if (_percent > 0) {
110                 return '<i class="el-icon-caret-top" style="margin-right:3px;"></i>' + Math.abs(_percent) + '%';
111                 // return "⬆" + Math.abs(_percent) + "%"
112             } else {
113                 return '<i class="el-icon-caret-bottom" style="margin-right:3px;"></i>' + Math.abs(_percent) + '%';
114                 // return "⬇" + Math.abs(_percent) + "%"
115             }
116         },
117         trendFormatter() {
118             const _trend = this.dataProvider.trend;
119             if (!_trend || _trend === 0) {
120                 return '';
121             }
122             if (_trend > 0) {
123                 return '<i class="el-icon-caret-top" style="margin-right:3px;"></i>' + Math.abs(_trend);
124                 // return "⬆" + Math.abs(_trend) + "%"
125             } else {
126                 return '<i class="el-icon-caret-bottom" style="margin-right:3px;"></i>' + Math.abs(_trend);
127                 // return "⬇" + Math.abs(_trend) + "%"
128             }
129         }
130     },
131     methods: {
132         goTo() {
133             // if (this.dataProvider.href) {
134             // this.$refs.component.show(this.dataProvider);
135             // }
136             this.$emit('selected', this.dataProvider);
137         }
138     }
139 };
140 </script>
141 
142 <style lang="scss" scoped>
143 $blue: #0058a5;
144 $grey : #585858;
145 
146 .box {
147     display: flex;
148     .icon-wrapper {
149         flex: 0 0 20px;
150         display: flex;
151         align-items: center;
152         justify-content: center;
153         .icon {
154             width: 5px;
155             height: 50%;
156             background-color: $blue;
157         }
158     }
159     .box-wrapper {
160         flex: 1;
161         display: flex;
162         flex-direction: column;
163     }
164     .label {
165         color: $grey;
166         // font-size: 1rem;
167     }
168     .value {
169         color: $blue;
170         // font-size: 1.5rem;
171         font-weight: 550;
172         cursor: pointer;
173     }
174     .alias {
175         color: $blue;
176         // font-size: 1rem;
177         font-weight: 550;
178         cursor: pointer;
179         margin-left: 5px;
180     }
181     .percent {
182         color: $blue;
183         // font-size: 1rem;
184         font-weight: 550;
185         cursor: pointer;
186     }
187     .trend {
188         color: $blue;
189         // font-size: 1rem;
190         font-weight: 550;
191         cursor: pointer;
192     }
193     .unit {
194         color: $blue;
195         // font-size: 1rem;
196     }
197 }
198 </style>

 

调用案例:

<lilo-box-group :dataProvider="boxData" theme="blue" :col="6" lineGap="10px" @selected="boxGroupSelected"></lilo-box-group>
 1 boxData: [
 2                 {
 3                     label: '初等教育',
 4                     value: 12447,
 5                     unit: '人',
 6                     alias: '1.5%',
 7                     // percent: 0.3,
 8                     trend: -120,
 9                     valueSize: 0.9,
10                     aliasSize: 0.7
11                 },
12                 {
13                     label: '中等教育',
14                     value: 579160,
15                     unit: '人',
16                     alias: '69.6%',
17                     percent: 5.8,
18                     valueSize: 0.9,
19                     aliasSize: 0.7
20                 },
21                 {
22                     label: '高等教育',
23                     value: 66622,
24                     unit: '人',
25                     alias: '8%',
26                     // percent: -8.6,
27                     trend: -86,
28                     valueSize: 0.9,
29                     aliasSize: 0.7
30                 },
31                 {
32                     label: '研究生教育',
33                     value: 3734,
34                     unit: '人',
35                     alias: '0.4%',
36                     // percent: -0.2,
37                     trend: 189,
38                     valueSize: 0.9,
39                     aliasSize: 0.7
40                 },
41                 {
42                     label: '有房',
43                     value: 459386,
44                     unit: '人',
45                     alias: '55.2%',
46                     percent: -5,
47                     valueSize: 1.2,
48                     aliasSize: 0.9
49                 },
50                 {
51                     label: '有车',
52                     value: 63210,
53                     unit: '人',
54                     alias: '7.6%',
55                     percent: -6.3,
56                     valueSize: 1.2,
57                     aliasSize: 0.9
58                 }
59             ]

 1 boxGroupSelected(val) { 2 console.log(val); 3 } 

 

附录:variables.css

// base color

// $blue: #324157;
// $menuBg: #304156;
// $menuHover: #263445;
// $subMenuBg: #1f2d3d;
// $subMenuHover: #001528;

$color-background-s: rgba(0, 0, 0, 0.9);

$blue: #00417a;
$commonBlue: #0000ff;
// $menuBg: #00417a;
$menuBg: #ffffff;
// $menuHover: #00355e;
$menuHover: #f4f4f4;
// $subMenuBg: #003462;
$subMenuBg: #ffffff;
// $subMenuHover: #002546;
$subMenuHover: #e7e7e7;
$menuBorderRight: 1px solid #c5c1c1;

$light-blue: #1890ff;
$red: #f56c6c;
$deep-red: #ff0000;
$blood-red: #d50000;
$pink: #dc67ce;
$green: #0bbd87;
$tiffany: #4ab7bd;
$yellow: #e6a23c;
$deep-yellow: #d69737;
$panGreen: #30b08f;
$purple: #6771dc;
$grey: #585858;
$light-grey: #f0f0f0;
$orange: #ff8037;
$deep-green: #07885f;
$light-green: #0bbd8722;
$light-purple: #6771dc22;
// sidebar
// $menuText: #bfcbd9;
$menuText: #002546;
// $menuActiveText: #409eff;
$menuActiveText: #08ac76;
// $subMenuActiveText: #f4f4f5;
$subMenuActiveText: #00417a;

$sideBarWidth: 230px;
$headerHeight: 54px;

// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
    blue: $blue;
    commonBlue: $commonBlue;
    lightBlue: $light-blue;
    red: $red;
    deepRed: $deep-red;
    bloodRed: $blood-red;
    pink: $pink;
    green: $green;
    deepGreen: $deep-green;
    lightGreen: $light-green;
    lightPurple: $light-purple;
    tiffany: $tiffany;
    yellow: $yellow;
    deepYellow: $deep-yellow;
    orange: $orange;
    panGreen: $panGreen;
    purple: $purple;
    grey: $grey;
    lightGrey: $light-grey;
    menuText: $menuText;
    menuActiveText: $menuActiveText;
    subMenuActiveText: $subMenuActiveText;
    menuBg: $menuBg;
    menuHover: $menuHover;
    subMenuBg: $subMenuBg;
    subMenuHover: $subMenuHover;
    sideBarWidth: $sideBarWidth;
}
View Code

 

 

参数解释:

col:每行的列数

theme:主题,这个是我的整个插件有个variables.css,里面有很多主题色

lineGap:行间距

dataProvider:

[{

label: '初等教育', //标题
value: 12447, //主数值
unit: '人', //单位
alias: '1.5%', //别名
percent: 0.3, //百分比
trend: -120, //趋势值 labelSize: 1, //标题字体大小 rem
valueSize: 0.9, //主数值字体大小 rem
aliasSize: 0.7, //别名字体大小 rem unitSize: 1, //单位字体大小 rem color: '#000000', //所有文字颜色,颜色优先级为 具体子项颜色(下面的颜色参数)> color > theme iconColor: '#000000', //左边边框颜色 labelColor: '#000000', //标题文字颜色 valueColor: '#000000', //主数值文字颜色 aliasColor: '#000000', //别名文字颜色 unitColor: '#000000', //单位文字颜色

}]

 

详细源码请移步 https://gitee.com/binyylovesino/lilo-ui

欢迎各路大佬指导、提问~

标签:blue,Vue,return,color,percent,复合,可视化,dataProvider,unit
From: https://www.cnblogs.com/loveFlex/p/17654170.html

相关文章

  • vue3 报错:husky - pre-commit hook exited with code 1 (error)
    问题:git提交不上去解决方法:   "format":"prettier--write\"./**/*.{html,vue,ts,js,json,md}\"",......
  • 找不到模块“../view/Home.vue”或其相应的类型声明。
    环境:vue3+ts解决办法:在src目录里面添加env.d.ts文件,在文件里贴上declaremodule'*.vue'{importtype{DefineComponent}from'vue'constcomponent:ComponentOptions|ComponentOptions['setup']exportdefaultcomponent} ......
  • VUE input允许数字 且两位小数
    页面:<[email protected]="onlyNumber()"placeholder="请输入(整数或者小数)金额"v-model="form.ysje"></el-input>方法:onlyNumber(){this.form.ysje=this.onlyNumOnePoint(this.form.ysje);},onlyNumOnePoint(number_on......
  • Vue【原创】下划线动态效果按钮,一般按钮模式,开关切换模式。
     1.lilo-icon-button一般按钮模式:1<template>2<divclass="icon-button":style="{color:font.color}"@click="onclick">3<i:class="[icon.type]":style="{color:icon.color,font......
  • vuedraggable和vue-fragment冲突导致连续多次拖拽报错问题
    项目中使用了vuedraggable实现拖拽功能。同时为了不产生多余标签,引入了vue-fragment。在连续多次拖动之后,总是报错。 解决办法:卸载vue-fragment。如果不想引入多余的标签,可以直接使用<template>,而且<template>标签是标准的HTML标签,更具可移植性。......
  • RIdeogram染色体可视化
    Circos玩多了难免会视觉疲劳,今天换一个新工具可视化,回到直条的染色体形式。https://www.jianshu.com/p/07ae1fe18071https://cran.r-project.org/web/packages/RIdeogram/vignettes/RIdeogram.html#install.packages('RIdeogram')library(RIdeogram)library(plyr)library(dp......
  • Vue3 中 keepAlive 如何搭配 VueRouter 来更自由的控制页面的状态缓存?
    在vue中,默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。但是vue提供了keep-alive组件,它可以将一个动态组件包装起来从而实现组件切换时候保留其状态。本篇文章要介绍的......
  • Vue【原创】千位符输入框(不仅只是过滤器哦)
    最近和一个做金融的朋友讨论到千位符输入的问题,后来一想貌似自己项目中也会经常碰到金额数字这种输入框,要么自己做一个吧。首先肯定要有一个正则表达式,也就是过滤器的方案里面常用的正则:1filters:{2_toThousandFilter(str,that){3returnthat._toN......
  • 视频云存储平台EasyCVR视频汇聚平台关于机电设别可视化管理平台可实施设计方案
    随着工业化进程的不断发展,机电设备在各行各业中扮演着重要的角色。然而,由于机电设备种类繁多、数量庞大,包括生产机械、建筑器械、矿用器械、制药器械、食品机械等,传统的手动管理方式已经无法满足对设备进行精细化管理的需求。因此,设备生产厂家、设备维保商和设备使用单位正在寻求......
  • 创建web应用程序,React和Vue怎么选?
    React和Vue都是创建web应用程序的绝佳选择。React得到了科技巨头和庞大的开源社区的支持,代码库可以很大程度地扩展,允许你创建企业级web应用程序。React拥有大量合格甚至优秀的开发人员粉丝,可以解决你在开发阶段可能遇到的任何问题。毫无疑问,React是创建跨平台解决方案的最佳框架......