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

先上个效果图:

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

此组件包括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.scss

// 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;
}

参数解释:

col:每行的列数

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

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', //单位文字颜色

}]

数据可视化【原创】vue复合数字形式展示的更多相关文章

  1. 查询表格——建立动态表格,使用ajax输入查询条件将后台数据查询出来以表格的形式展示出来

    建立动态表格,使用ajax将前台查询条件传给后台,并将查询结果以表格的形式展示出来. 页面的展示效果如下图所示: 第一步:查询条件的部分: 代码如下: <div class="text ...

  2. Python实现汉诺塔问题的可视化(以动画的形式展示移动过程)

    学习Python已经有一段时间了,也学习了递归的方法,而能够实践该方法的当然就是汉诺塔问题了,但是这次我们不只是要完成对汉诺塔过程的计算,还要通过turtle库来体现汉诺塔中每一层移动的过程. 一.设 ...

  3. Matplotlib数据可视化(7):图片展示与保存

    In [1]: import os import matplotlib.image as mpimg from PIL import Image import matplotlib.pyplot as ...

  4. 数据可视化界面UI设计大屏展示

  5. Excel数据可视化图表设计需要注意的几个问题

    ​大数据发展迅速的时代,数据分析驱动商业决策.对于庞大.无序.复杂的数据要是没经过合适的处理,价值就无法体现. 可以想象一本没有图片的教科书.没有图表.图形或是带有箭头和标签的插图或流程图,那么这门学 ...

  6. 最棒的7种R语言数据可视化

    最棒的7种R语言数据可视化 随着数据量不断增加,抛开可视化技术讲故事是不可能的.数据可视化是一门将数字转化为有用知识的艺术. R语言编程提供一套建立可视化和展现数据的内置函数和库,让你学习这门艺术.在 ...

  7. EasyNVR摄像机网页无插件直播方案H5前端构建之:使用BootstrapPagination以分页形式展示数据信息

    背景介绍 EasyNVR核心在于摄像机的音视频流的获取.转换.转码与高性能分发,同时同步完成对实时直播流的录像存储,在客户端(PC浏览器.Android.iOS.微信)进行录像文件的检索.回放和下载. ...

  8. 基于echarts 24种数据可视化展示,填充数据就可用,动手能力强的还可以DIY(演示地址+下载地址)

    前言 我们先跟随百度百科了解一下什么是"数据可视化 [1]". 数据可视化,是关于数据视觉表现形式的科学技术研究. 其中,这种数据的视觉表现形式被定义为,一种以某种概要形式抽提出来 ...

  9. redis 一二事 - 设置过期时间,以文件夹形式展示key显示缓存数据

    在使用redis时,有时回存在大量数据的时候,而且分类相同,ID相同 可以使用hset来设置,这样有一个大类和一个小分类和一个value组成 但是hset不能设置过期时间 过期时间只能在set上设置 ...

  10. EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:使用BootstrapPagination以分页形式展示数据信息

    上一篇介绍通过接口来获取数据,本篇将介绍如何以分页形式展示出接口获取到的数据 获取到的数据往往会很多,为了追去页面的美观和方便用户的检索,需要进行分页的展示: EasyNVR可接如多通道,当我们的通道 ...

随机推荐

  1. Requested setting INSTALLED_APPS, but settings are not configured. You must either define the env...

    解决办法 在test.py文件的最头部加上以下代码,配置环境 import os,django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djb ...

  2. Mysql DDL执行方式-pt-osc介绍 | 京东云技术团队

    1 引言 大家好,接着上次和大家一起学习了<MySQL DDL执行方式-Online DDL介绍>,那么今天接着和大家一起学习另一种MySQL DDL执行方式之pt-soc. 在MySQL ...

  3. Abstract Factory Pattern 抽象工厂模式简介与 C# 示例【创建型】【设计模式来了】

    〇.简介 1.什么是抽象工厂模式? 一句话解释:   通过对抽象类和抽象工厂的一组实现,独立出一系列新的操作,客户端无需了解其逻辑直接访问. 抽象工厂模式(Abstract Factory Patte ...

  4. SpringBoot连接Redis失败报错:Unable to connect to Redis; (小白篇)

    学习redis一段时间了,现在开始使用springboot整合redis,实现Java与redis数据库的连接与一系列的使用. 但刚开始就给我来了个下马威,直接寄,连接不上redis,在swagger ...

  5. UpSetR:多数据集绘图可视化处理利器

    说到集合数据可视化,我们第一时间想到的就是韦恩图.在 NGS 相关的研究中,韦恩图用来直观表征不同的集合之间元素重叠关系,是经常在文献中出现的图. 在集合数少的时候韦恩图是很好用的,但是当集合数多比如 ...

  6. C#.NET Framework RSA 公钥加密 私钥解密 ver:20230609

    C#.NET Framework RSA 公钥加密 私钥解密 ver:20230609 环境说明: .NET Framework 4.6 的控制台程序 . .NET Framework 对于RSA的支 ...

  7. Rust中的变量的声明和定义

    变量的声明和定义 Rust中合法的标识符(包括变量名.函数名.triat名等)必须由数字.字母.下划线组成,而且不能以数字开头.这个和很多语言都是一样的.Rust将来也会允许其他Unicode字符作为 ...

  8. 从输入URI到浏览器渲染中间都经历了什么

    这篇文章总共分为两个部分,第一部分我会把从输入url到浏览器渲染的整个流程给大致说一下.第二部分我就会一一介绍各个部分的详细作用. 一.从输入url到浏览器渲染的整个流程   1.DNS域名解析 2. ...

  9. 从隐私保护到AI隐私保护:隐私隐私保护的跨隐私保护治理框架实践案例

    目录 标题:<从隐私保护到AI隐私保护:跨隐私保护治理框架实践案例> 背景介绍 随着人工智能技术的广泛应用,隐私保护问题也日益突出.数据隐私泄露.算法歧视等问题引发了公众的担忧和不满.为了 ...

  10. h2database BTree 设计实现与查询优化思考

    h2database 是使用Java 编写的开源数据库,兼容ANSI-SQL89. 即实现了常规基于 BTree 的存储引擎,又支持日志结构存储引擎.功能非常丰富(死锁检测机制.事务特性.MVCC.运 ...