blob: db1b0195314765ed12980d9331972626be210418 [file] [log] [blame]
guangchao.xu070005a2020-12-07 09:56:40 +08001<template>
2 <view :style="[customStyle]" class="u-icon" @tap="click" :class="['u-icon--' + labelPos]">
3 <image class="u-icon__img" v-if="isImg" :src="name" :mode="imgMode" :style="[imgStyle]"></image>
4 <text v-else class="u-icon__icon" :class="customClass" :style="[iconStyle]" :hover-class="hoverClass"
5 @touchstart="touchstart">
6 <text v-if="showDecimalIcon" :style="[decimalIconStyle]" :class="decimalIconClass" :hover-class="hoverClass"
7 class="u-icon__decimal">
8 </text>
9 </text>
10 <!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
11 <text v-if="label !== ''" class="u-icon__label" :style="{
12 color: labelColor,
13 fontSize: $u.addUnit(labelSize),
14 marginLeft: labelPos == 'right' ? $u.addUnit(marginLeft) : 0,
15 marginTop: labelPos == 'bottom' ? $u.addUnit(marginTop) : 0,
16 marginRight: labelPos == 'left' ? $u.addUnit(marginRight) : 0,
17 marginBottom: labelPos == 'top' ? $u.addUnit(marginBottom) : 0,
18 }">{{ label }}
19 </text>
20 </view>
21</template>
22
23<script>
24/**
25 * icon 图标
26 * @description 基于字体的图标集,包含了大多数常见场景的图标。
27 * @tutorial https://www.uviewui.com/components/icon.html
28 * @property {String} name 图标名称,见示例图标集
29 * @property {String} color 图标颜色(默认inherit)
30 * @property {String | Number} size 图标字体大小,单位rpx(默认32)
31 * @property {String | Number} label-size label字体大小,单位rpx(默认28)
32 * @property {String} label 图标右侧的label文字(默认28)
33 * @property {String} label-pos label文字相对于图标的位置,只能right或bottom(默认right)
34 * @property {String} label-color label字体颜色(默认#606266)
35 * @property {Object} custom-style icon的样式,对象形式
36 * @property {String} custom-prefix 自定义字体图标库时,需要写上此值
37 * @property {String | Number} margin-left label在右侧时与图标的距离,单位rpx(默认6)
38 * @property {String | Number} margin-top label在下方时与图标的距离,单位rpx(默认6)
39 * @property {String | Number} margin-bottom label在上方时与图标的距离,单位rpx(默认6)
40 * @property {String | Number} margin-right label在左侧时与图标的距离,单位rpx(默认6)
41 * @property {String} label-pos label相对于图标的位置,只能right或bottom(默认right)
42 * @property {String} index 一个用于区分多个图标的值,点击图标时通过click事件传出
43 * @property {String} hover-class 图标按下去的样式类,用法同uni的view组件的hover-class参数,详情见官网
44 * @property {String} width 显示图片小图标时的宽度
45 * @property {String} height 显示图片小图标时的高度
46 * @property {String} top 图标在垂直方向上的定位
47 * @property {String} top 图标在垂直方向上的定位
48 * @property {String} top 图标在垂直方向上的定位
49 * @property {Boolean} show-decimal-icon 是否为DecimalIcon
50 * @property {String} inactive-color 背景颜色,可接受主题色,仅Decimal时有效
51 * @property {String | Number} percent 显示的百分比,仅Decimal时有效
52 * @event {Function} click 点击图标时触发
53 * @example <u-icon name="photo" color="#2979ff" size="28"></u-icon>
54 */
55export default {
56 name: 'u-icon',
57 props: {
58 // 图标类名
59 name: {
60 type: String,
61 default: ''
62 },
63 // 图标颜色,可接受主题色
64 color: {
65 type: String,
66 default: ''
67 },
68 // 字体大小,单位rpx
69 size: {
70 type: [Number, String],
71 default: 'inherit'
72 },
73 // 是否显示粗体
74 bold: {
75 type: Boolean,
76 default: false
77 },
78 // 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
79 index: {
80 type: [Number, String],
81 default: ''
82 },
83 // 触摸图标时的类名
84 hoverClass: {
85 type: String,
86 default: ''
87 },
88 // 自定义扩展前缀,方便用户扩展自己的图标库
89 customPrefix: {
90 type: String,
91 default: 'uicon'
92 },
93 // 图标右边或者下面的文字
94 label: {
95 type: [String, Number],
96 default: ''
97 },
98 // label的位置,只能右边或者下边
99 labelPos: {
100 type: String,
101 default: 'right'
102 },
103 // label的大小
104 labelSize: {
105 type: [String, Number],
106 default: '28'
107 },
108 // label的颜色
109 labelColor: {
110 type: String,
111 default: '#606266'
112 },
113 // label与图标的距离(横向排列)
114 marginLeft: {
115 type: [String, Number],
116 default: '6'
117 },
118 // label与图标的距离(竖向排列)
119 marginTop: {
120 type: [String, Number],
121 default: '6'
122 },
123 // label与图标的距离(竖向排列)
124 marginRight: {
125 type: [String, Number],
126 default: '6'
127 },
128 // label与图标的距离(竖向排列)
129 marginBottom: {
130 type: [String, Number],
131 default: '6'
132 },
133 // 图片的mode
134 imgMode: {
135 type: String,
136 default: 'widthFix'
137 },
138 // 自定义样式
139 customStyle: {
140 type: Object,
141 default() {
142 return {}
143 }
144 },
145 // 用于显示图片小图标时,图片的宽度
146 width: {
147 type: [String, Number],
148 default: ''
149 },
150 // 用于显示图片小图标时,图片的高度
151 height: {
152 type: [String, Number],
153 default: ''
154 },
155 // 用于解决某些情况下,让图标垂直居中的用途
156 top: {
157 type: [String, Number],
158 default: 0
159 },
160 // 是否为DecimalIcon
161 showDecimalIcon: {
162 type: Boolean,
163 default: false
164 },
165 // 背景颜色,可接受主题色,仅Decimal时有效
166 inactiveColor: {
167 type: String,
168 default: '#ececec'
169 },
170 // 显示的百分比,仅Decimal时有效
171 percent: {
172 type: [Number, String],
173 default: '50'
174 }
175 },
176 computed: {
177 customClass() {
178 let classes = []
179 classes.push(this.customPrefix + '-' + this.name)
180 // uView的自定义图标类名为u-iconfont
181 if (this.customPrefix == 'uicon') {
182 classes.push('u-iconfont')
183 } else {
184 classes.push(this.customPrefix)
185 }
186 // 主题色,通过类配置
187 if (this.showDecimalIcon && this.inactiveColor && this.$u.config.type.includes(this.inactiveColor)) {
188 classes.push('u-icon__icon--' + this.inactiveColor)
189 } else if (this.color && this.$u.config.type.includes(this.color)) classes.push('u-icon__icon--' + this.color)
190 // 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
191 // 故需将其拆成一个字符串的形式,通过空格隔开各个类名
192 //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
193 classes = classes.join(' ')
194 //#endif
195 return classes
196 },
197 iconStyle() {
198 let style = {}
199 style = {
200 fontSize: this.size == 'inherit' ? 'inherit' : this.$u.addUnit(this.size),
201 fontWeight: this.bold ? 'bold' : 'normal',
202 // 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
203 top: this.$u.addUnit(this.top)
204 }
205 // 非主题色值时,才当作颜色值
206 if (this.showDecimalIcon && this.inactiveColor && !this.$u.config.type.includes(this.inactiveColor)) {
207 style.color = this.inactiveColor
208 } else if (this.color && !this.$u.config.type.includes(this.color)) style.color = this.color
209
210 return style
211 },
212 // 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
213 isImg() {
214 return this.name.indexOf('/') !== -1
215 },
216 imgStyle() {
217 let style = {}
218 // 如果设置width和height属性,则优先使用,否则使用size属性
219 style.width = this.width ? this.$u.addUnit(this.width) : this.$u.addUnit(this.size)
220 style.height = this.height ? this.$u.addUnit(this.height) : this.$u.addUnit(this.size)
221 return style
222 },
223 decimalIconStyle() {
224 let style = {}
225 style = {
226 fontSize: this.size == 'inherit' ? 'inherit' : this.$u.addUnit(this.size),
227 fontWeight: this.bold ? 'bold' : 'normal',
228 // 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
229 top: this.$u.addUnit(this.top),
230 width: this.percent + '%'
231 }
232 // 非主题色值时,才当作颜色值
233 if (this.color && !this.$u.config.type.includes(this.color)) style.color = this.color
234 return style
235 },
236 decimalIconClass() {
237 let classes = []
238 classes.push(this.customPrefix + '-' + this.name)
239 // uView的自定义图标类名为u-iconfont
240 if (this.customPrefix == 'uicon') {
241 classes.push('u-iconfont')
242 } else {
243 classes.push(this.customPrefix)
244 }
245 // 主题色,通过类配置
246 if (this.color && this.$u.config.type.includes(this.color)) classes.push('u-icon__icon--' + this.color)
247 else classes.push('u-icon__icon--primary')
248 // 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
249 // 故需将其拆成一个字符串的形式,通过空格隔开各个类名
250 //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
251 classes = classes.join(' ')
252 //#endif
253 return classes
254 }
255 },
256 methods: {
257 click() {
258 this.$emit('click', this.index)
259 },
260 touchstart() {
261 this.$emit('touchstart', this.index)
262 }
263 }
264}
265</script>
266
267<style scoped lang="scss">
268@import "../../libs/css/style.components.scss";
269@import '../../iconfont.css';
270
271.u-icon {
272 display: inline-flex;
273 align-items: center;
274
275 &--left {
276 flex-direction: row-reverse;
277 align-items: center;
278 }
279
280 &--right {
281 flex-direction: row;
282 align-items: center;
283 }
284
285 &--top {
286 flex-direction: column-reverse;
287 justify-content: center;
288 }
289
290 &--bottom {
291 flex-direction: column;
292 justify-content: center;
293 }
294
295 &__icon {
296 position: relative;
297
298 &--primary {
299 color: $u-type-primary;
300 }
301
302 &--success {
303 color: $u-type-success;
304 }
305
306 &--error {
307 color: $u-type-error;
308 }
309
310 &--warning {
311 color: $u-type-warning;
312 }
313
314 &--info {
315 color: $u-type-info;
316 }
317 }
318
319 &__decimal {
320 position: absolute;
321 top: 0;
322 left: 0;
323 display: inline-block;
324 overflow: hidden;
325 }
326
327 &__img {
328 height: auto;
329 will-change: transform;
330 }
331
332 &__label {
333 line-height: 1;
334 }
335}
336</style>