wu-icon.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <template>
  2. <view class="wu-icon" @tap="clickHandler" :class="['wu-icon--' + labelPos]">
  3. <!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
  4. <text v-if="label !== '' && (labelPos == 'left' || labelPos == 'top')" class="wu-icon__label" :style="labelStyle">{{ label }}</text>
  5. <image class="wu-icon__img" v-if="isImg" :src="name" :mode="imgMode"
  6. :style="[imgStyle, $w.addStyle(customStyle)]"></image>
  7. <text v-else class="wu-icon__icon" :class="uClasses" :style="[iconStyle, $w.addStyle(customStyle)]"
  8. :hover-class="hoverClass">{{icon}}</text>
  9. <!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
  10. <text v-if="label !== '' && (labelPos == 'right' || labelPos == 'bottom')" class="wu-icon__label" :style="labelStyle">{{ label }}</text>
  11. </view>
  12. </template>
  13. <script>
  14. import mpMixin from '@/uni_modules/wu-ui-tools/libs/mixin/mpMixin.js'
  15. import mixin from '@/uni_modules/wu-ui-tools/libs/mixin/mixin.js'
  16. // #ifdef APP-NVUE
  17. // nvue通过weex的dom模块引入字体,相关文档地址如下:
  18. // https://weex.apache.org/zh/docs/modules/dom.html#addrule
  19. import iconUrl from './wuicons.ttf';
  20. const domModule = weex.requireModule('dom');
  21. domModule.addRule('fontFace', {
  22. 'fontFamily': "wuicon-iconfont",
  23. 'src': "url('" + iconUrl + "')"
  24. })
  25. // #endif
  26. // 引入图标名称,已经对应的unicode
  27. import icons from './icons';
  28. import props from './props.js';
  29. /**
  30. * icon 图标
  31. * @description 基于字体的图标集,包含了大多数常见场景的图标。
  32. * @tutorial https://wuui.cn/zh-CN/components/icon.html
  33. * @property {String} name 图标名称,若带有 `/` 或遵循 `base64` 图片格式,会被认为是图片图标,则文字图标相关属性会失效。
  34. * @property {String} color 图标颜色,可接受主题色 (默认 color: #606266 )
  35. * @property {String | Number} size 图标字体大小,单位px/rpx (默认 '16px' )
  36. * @property {Boolean} bold 是否显示粗体 (默认 false )
  37. * @property {String | Number} index 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
  38. * @property {String} hoverClass 图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
  39. * @property {String} customPrefix 自定义扩展前缀,方便用户扩展自己的图标库 (默认 'wuicon' )
  40. * @property {String | Number} label 图标右侧的label文字
  41. * @property {String} labelPos label相对于图标的位置(默认 'right' )
  42. * @value top 上方
  43. * @value bottom 下方
  44. * @value left 左侧
  45. * @value right 右侧
  46. * @property {String | Number} labelSize label字体大小,单位px (默认 '15px' )
  47. * @property {String} labelColor 图标右侧的label文字颜色 ( 默认 color['wu-content-color'] )
  48. * @property {String | Number} space label与图标的距离,单位px (默认 '3px' )
  49. * @property {String} imgMode image组件的mode,详见:[image](https://uniapp.dcloud.net.cn/component/image.html#image)
  50. * @property {String | Number} width 显示图片小图标时的宽度
  51. * @property {String | Number} height 显示图片小图标时的高度
  52. * @property {String | Number} top 图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途 (默认 0 )
  53. * @property {Boolean} stop 是否阻止事件传播 (默认 false )
  54. * @property {Object} customStyle icon的样式,对象形式
  55. * @event {Function} click 点击图标时触发
  56. * @event {Function} touchstart 事件触摸时触发
  57. * @example <wu-icon name="photo" color="#2979ff" size="28"></wu-icon>
  58. */
  59. export default {
  60. name: 'wu-icon',
  61. emits: ['click'],
  62. mixins: [mpMixin, mixin, props],
  63. data() {
  64. return {
  65. colorType: [
  66. 'primary',
  67. 'success',
  68. 'info',
  69. 'error',
  70. 'warning'
  71. ]
  72. }
  73. },
  74. computed: {
  75. uClasses() {
  76. let classes = []
  77. classes.push(this.customPrefix)
  78. classes.push(this.customPrefix + '-' + this.name)
  79. // 主题色,通过类配置
  80. if (this.color && this.colorType.includes(this.color)) classes.push('wu-icon__icon--' + this.color)
  81. // 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
  82. // 故需将其拆成一个字符串的形式,通过空格隔开各个类名
  83. //#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
  84. classes = classes.join(' ')
  85. //#endif
  86. return classes
  87. },
  88. iconStyle() {
  89. let style = {}
  90. style = {
  91. fontSize: this.$w.addUnit(this.size),
  92. lineHeight: this.$w.addUnit(this.size),
  93. fontWeight: this.bold ? 'bold' : 'normal',
  94. // 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
  95. top: this.$w.addUnit(this.top)
  96. }
  97. // 非主题色值时,才当作颜色值
  98. if (this.color && !this.colorType.includes(this.color)) style.color = this.color
  99. return style
  100. },
  101. // 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
  102. isImg() {
  103. const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
  104. return this.name.indexOf('/') !== -1 || isBase64;
  105. },
  106. imgStyle() {
  107. let style = {}
  108. // 如果设置width和height属性,则优先使用,否则使用size属性
  109. style.width = this.width ? this.$w.addUnit(this.width) : this.$w.addUnit(this.size)
  110. style.height = this.height ? this.$w.addUnit(this.height) : this.$w.addUnit(this.size)
  111. return style
  112. },
  113. // 通过图标名,查找对应的图标
  114. icon() {
  115. // 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
  116. const code = icons['wuicon-' + this.name];
  117. if (['wuicon'].indexOf(this.customPrefix) > -1) {
  118. return code ? unescape(`%u${code}`) : this.name;
  119. } else {
  120. // #ifndef APP-NVUE
  121. return ''
  122. // #endif
  123. // #ifdef APP-NVUE
  124. return unescape(`%u${this.name}`)
  125. // #endif
  126. }
  127. },
  128. // label样式
  129. labelStyle() {
  130. let style = {
  131. color: this.labelColor,
  132. fontSize: this.$w.addUnit(this.labelSize),
  133. marginLeft: this.labelPos == 'right' ? this.$w.addUnit(this.space) : 0,
  134. marginTop: this.labelPos == 'bottom' ? this.$w.addUnit(this.space) : 0,
  135. marginRight: this.labelPos == 'left' ? this.$w.addUnit(this.space) : 0,
  136. marginBottom: this.labelPos == 'top' ? this.$w.addUnit(this.space) : 0
  137. };
  138. return style
  139. }
  140. },
  141. methods: {
  142. clickHandler(e) {
  143. this.$emit('click', this.index)
  144. // 是否阻止事件冒泡
  145. this.stop && this.preventEvent(e)
  146. }
  147. }
  148. }
  149. </script>
  150. <style lang="scss" scoped>
  151. @import '@/uni_modules/wu-ui-tools/libs/css/components.scss';
  152. @import '@/uni_modules/wu-ui-tools/libs/css/color.scss';
  153. // 变量定义
  154. $wu-icon-primary: $wu-primary !default;
  155. $wu-icon-success: $wu-success !default;
  156. $wu-icon-info: $wu-info !default;
  157. $wu-icon-warning: $wu-warning !default;
  158. $wu-icon-error: $wu-error !default;
  159. $wu-icon-label-line-height: 1 !default;
  160. /* #ifndef APP-NVUE */
  161. // 非nvue下加载字体
  162. @font-face {
  163. font-family: 'wuicon-iconfont';
  164. src: url('./wuicons.ttf') format('truetype');
  165. }
  166. /* #endif */
  167. .wu-icon {
  168. /* #ifndef APP-NVUE */
  169. display: flex;
  170. /* #endif */
  171. align-items: center;
  172. &--left, &--right {
  173. flex-direction: row;
  174. }
  175. &--top, &--bottom {
  176. flex-direction: column;
  177. }
  178. &__icon {
  179. font-family: wuicon-iconfont;
  180. position: relative;
  181. @include flex;
  182. align-items: center;
  183. &--primary {
  184. color: $wu-icon-primary;
  185. }
  186. &--success {
  187. color: $wu-icon-success;
  188. }
  189. &--error {
  190. color: $wu-icon-error;
  191. }
  192. &--warning {
  193. color: $wu-icon-warning;
  194. }
  195. &--info {
  196. color: $wu-icon-info;
  197. }
  198. }
  199. &__img {
  200. /* #ifndef APP-NVUE */
  201. height: auto;
  202. will-change: transform;
  203. /* #endif */
  204. }
  205. &__label {
  206. /* #ifndef APP-NVUE */
  207. line-height: $wu-icon-label-line-height;
  208. /* #endif */
  209. }
  210. }
  211. </style>