mysNavBar.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2. <view class="nav">
  3. <view class="nv_padding" v-if="!!mysNavConfig.navPadding" :style="{
  4. height: navBarHeight,
  5. }"></view>
  6. <view class="bg_box" style="background-color: #FFFFFF;" :style="{
  7. backgroundColor: mysNavConfig.bgColor,
  8. backgroundImage: mysNavConfig.bgImage,
  9. paddingTop: navBarTop,
  10. height: navBarHeight,
  11. opacity: opacity,
  12. }" :class="{ fixed: mysNavConfig.navFixed }"></view>
  13. <view class="mys_navBar" :style="{
  14. paddingTop: navBarTop,
  15. height: navBarHeight,
  16. paddingRight: navBarRight,
  17. }" :class="{ fixed: mysNavConfig.navFixed }">
  18. <view class="my_left_box" :style="{ height: btnHeight }">
  19. <!-- 左侧单图标 + text -->
  20. <view class="my_left_icon" @tap="onLeftHome" :style="{ height: btnHeight, paddingLeft: navBarLeft }"
  21. v-if="isHome">
  22. <image class="nv_icon" :src="mysNavConfig.homeIconPath || homeIconPath" />
  23. </view>
  24. <view class="my_left_icon" @tap="onLeftClick" v-if="mysNavConfig.btnType !== 'type2' && !isHome"
  25. :style="{ height: btnHeight, paddingLeft: navBarLeft }">
  26. <image class="nv_icon" :src="mysNavConfig.leftIconPath || backIconPath" />
  27. <view class="leftText" :style="{ height: btnHeight }"
  28. v-if="!!mysNavConfig.leftText && mysNavConfig.btnType !== 'type2'">
  29. <text :style="{
  30. color: mysNavConfig.leftText.color,
  31. fontSize: mysNavConfig.leftText.fontSize,
  32. fontWeight: mysNavConfig.leftText.fontWeight,
  33. }">{{ mysNavConfig.leftText.text }}</text>
  34. </view>
  35. </view>
  36. </view>
  37. <!-- 左slot -->
  38. <view class="my_left_custom" :style="{ height: btnHeight }">
  39. <slot name="left"></slot>
  40. </view>
  41. <view class="btn_type" :style="{ height: btnHeight }">
  42. <view class="btn_box nav_btn_t1" :style="{
  43. width: btnWidth,
  44. height: btnHeight,
  45. marginLeft: navBarLeft,
  46. borderRadius: mysNavConfig.type2Config.radius,
  47. }" v-if="mysNavConfig.btnType == 'type2' && !isHome">
  48. <view class="btn_back" @tap="onLeftClick" >
  49. <image class="nv_icon" :src="mysNavConfig.type2Config.leftPath"
  50. :style="{ height: btnHeight, width: iconW }" mode="aspectFit" />
  51. </view>
  52. <view class="line"></view>
  53. <view class="btn_home" @tap="onLeftHome">
  54. <image class="nv_icon" :src="mysNavConfig.type2Config.rightPath"
  55. :style="{ height: btnHeight, width: iconW }" mode="aspectFit" />
  56. </view>
  57. </view>
  58. <!-- 中间slot -->
  59. <view class="my_custom_box" :style="{ height: btnHeight }">
  60. <!-- 搜索框 -->
  61. <view class="nv_search_box" v-if="!!mysNavConfig.searchConfig" :style="{
  62. height: inputHeight,
  63. backgroundColor: mysNavConfig.searchConfig.bgColor,
  64. marginRight: mysNavConfig.searchConfig.marginRight,
  65. marginLeft: mysNavConfig.searchConfig.marginLeft,
  66. }">
  67. <image class="nv_icon" :src="`/static/searchB.png`" mode="aspectFit" />
  68. <input type="text" :value="mysNavConfig.searchConfig.value"
  69. :placeholder="mysNavConfig.searchConfig.placeholder"
  70. :disabled="mysNavConfig.searchConfig.disabled" @tap="clickInput" @input="changeInput"
  71. @confirm="submitInput" @confirm-type="mysNavConfig.searchConfig.ctype || 'search'"
  72. :placeholder-style="mysNavConfig.searchConfig.placeholderStyle || ''" class="nv_input" />
  73. <view class="close" @tap="clearInput" :style="{ height: inputHeight }">
  74. <image v-if="mysNavConfig.searchConfig.value !== ''" class="nv_icon"
  75. :src="`/static/colse_fill.png`" mode="aspectFit" />
  76. </view>
  77. </view>
  78. <slot name="center1"></slot>
  79. </view>
  80. </view>
  81. <!-- 标题 -->
  82. <view class="title_container" v-if="!mysNavConfig.searchConfig"
  83. :style="{ top: navBarTop, height: btnHeight }">
  84. <text class="title_text" v-if="!!mysNavConfig.navTitle" :style="{
  85. color: mysNavConfig.navTitle.color,
  86. fontSize: mysNavConfig.navTitle.fontSize,
  87. fontWeight: mysNavConfig.navTitle.fontWeight,
  88. }">{{ mysNavConfig.navTitle.text }}</text>
  89. <slot name="center2"></slot>
  90. </view>
  91. <!-- 右边slot -->
  92. <view class="my_right_icon" :style="{ height: btnHeight }">
  93. <image v-if="mysNavConfig.rightIconPath" @tap="onRightClick" class="nv_icon"
  94. :src="mysNavConfig.rightIconPath" />
  95. <slot name="right"></slot>
  96. </view>
  97. </view>
  98. </view>
  99. </template>
  100. <script>
  101. /* 默认首页路径 */
  102. const homePath = "/pages/pupu/pupudao";
  103. /* 默认首页图标路径 */
  104. const homeIconPath = "";
  105. /* 默认返回图标路径 */
  106. const backIconPath = "/static/img/png2.png";
  107. export default {
  108. props: {
  109. mysNavConfig: {
  110. type: Object,
  111. default () {
  112. return {
  113. /* 固定导航 */
  114. navFixed: true,
  115. /* 开启单页显示首页图标 */
  116. isHome: true,
  117. /* 占位开启 */
  118. navPadding: true,
  119. /* 背景 */
  120. bgColor: "#f8f8f8",
  121. /* 渐变色 */
  122. opacity: 1,
  123. /* 渐变开启 */
  124. isOpacity: false,
  125. /* 渐变延时效果 */
  126. opacityTime: 100,
  127. /* 左侧按钮样式 可选 type1 type2 (type2根据小程序胶囊位置调整) */
  128. btnType: "type1",
  129. /* type1 左侧文字配置 */
  130. leftText: {
  131. text: "",
  132. color: "",
  133. fontSize: "", // px upx rpx
  134. fontWeight: "", // blod
  135. },
  136. /* 标题 */
  137. navTitle: {
  138. text: "",
  139. color: "",
  140. fontSize: "32rpx", // px upx rpx
  141. fontWeight: "", // blod
  142. },
  143. /* type2 按钮 */
  144. type2Config: {
  145. // 左图标
  146. leftPath: "/static/back_w.png",
  147. // 右图标
  148. rightPath: "/static/home.png",
  149. // 圆角
  150. radius: "40rpx",
  151. },
  152. /* 搜索框配置 */
  153. // searchConfig: {
  154. // value: "",
  155. // confirmType: "search",
  156. // placeholder: "",
  157. // disabled: true,
  158. // placeholderStyle: "",
  159. // // marginRight: "",
  160. // // marginLeft: "",
  161. // },
  162. /* 自定义事件开启 */
  163. // isCustomFn: false,
  164. /* 定义左侧图标 (大小是固定的16px ,想改变大小通过 slot 或 css ) */
  165. // leftIconPath: "/static/back_b.png",
  166. /* 定义右侧图标 */
  167. // rightIconPath: "/static/home.png",
  168. /* home图标 */
  169. // homeIconPath: "/static/home.png",
  170. };
  171. },
  172. },
  173. scrollTop: {
  174. type: Number,
  175. default: function() {
  176. return 0;
  177. },
  178. },
  179. },
  180. data() {
  181. return {
  182. iconW: undefined,
  183. iconH: undefined,
  184. btnWidth: undefined,
  185. btnHeight: undefined,
  186. navBarTop: undefined,
  187. navBarHeight: undefined,
  188. navBarLeft: undefined,
  189. navBarRight: undefined,
  190. inputHeight: undefined,
  191. opacity: 0,
  192. isHome: false,
  193. homeIconPath: homeIconPath,
  194. backIconPath: backIconPath,
  195. };
  196. },
  197. computed: {
  198. isSharePage() {},
  199. },
  200. watch: {
  201. scrollTop(val) {
  202. if (!this.mysNavConfig.isOpacity) {
  203. return;
  204. }
  205. this.setOpacity(val, this.mysNavConfig.opacityTime);
  206. },
  207. },
  208. methods: {
  209. init() {
  210. if (this.mysNavConfig.isHome) {
  211. let pages = getCurrentPages().length;
  212. /* 单页显示home图标 */
  213. pages == 1 ? (this.isHome = true) : (this.isHome = false);
  214. }
  215. // 开启渐变 强制fixed
  216. this.navBarTop = uni.getSystemInfoSync().statusBarHeight + "px";
  217. if (!this.mysNavConfig.opacity) {
  218. this.opacity = 1;
  219. !this.mysNavConfig.isOpacity ? (this.opacity = 1) : ((this.mysNavConfig.navFixed = true), (this
  220. .opacity = 0));
  221. } else {
  222. this.opacity = this.mysNavConfig.opacity;
  223. !this.mysNavConfig.isOpacity ? "" : ((this.mysNavConfig.navFixed = true), (this.opacity = 0));
  224. }
  225. // #ifdef MP
  226. this.initMP();
  227. // #endif
  228. // #ifdef APP-PLUS-NVUE
  229. this.navBarHeight = 44 + uni.getSystemInfoSync().statusBarHeight + "px";
  230. // #endif
  231. },
  232. /* 小程序初始化位置 */
  233. initMP() {
  234. let gS = uni.getSystemInfoSync();
  235. let rect = uni.getMenuButtonBoundingClientRect();
  236. let rectHeight = rect.height;
  237. this.btnWidth = rect.width + "px";
  238. this.iconW = Math.floor(rect.width / 4 - 5) + "px";
  239. this.iconH = rectHeight / 2 + "px";
  240. this.btnHeight = rectHeight + "px";
  241. this.inputHeight = rectHeight - 3 + "px";
  242. this.navBarTop = rect.top + "px";
  243. this.navBarLeft = gS.screenWidth - rect.right + "px";
  244. this.navBarRight = gS.screenWidth - rect.right + rect.width + "px";
  245. this.navBarHeight = gS.statusBarHeight + rectHeight + (rect.top - gS.statusBarHeight) * 2 + "px";
  246. },
  247. /* 点击左侧 */
  248. onLeftClick() {
  249. if (this.mysNavConfig.isCustomFn) {
  250. this.$emit("onLeftClick");
  251. } else {
  252. console.log("back");
  253. uni.navigateBack();
  254. }
  255. },
  256. /* type2 返回首页 */
  257. onLeftHome() {
  258. uni.switchTab({
  259. url: homePath,
  260. });
  261. },
  262. /* 点击右侧 */
  263. onRightClick() {
  264. console.log("onRightClick");
  265. uni.showToast({
  266. title: "onRightClick",
  267. duration: 1000,
  268. });
  269. this.$emit("onRightClick");
  270. },
  271. /**
  272. * @param scrollTop 页面顶部距离
  273. * @param down 滑动显示效果延时
  274. */
  275. setOpacity(scrollTop, down = 60) {
  276. if (scrollTop > 0) {
  277. if (scrollTop < down) {
  278. this.opacity = scrollTop / down;
  279. }
  280. if (scrollTop > down) {
  281. this.opacity = 1;
  282. }
  283. } else {
  284. this.opacity = 0;
  285. }
  286. },
  287. /* 搜索框改变值 */
  288. changeInput(e) {
  289. this.$emit("changeInput", e);
  290. },
  291. /* 搜索框提交 */
  292. submitInput(e) {
  293. this.$emit("submitInput", e);
  294. },
  295. /* 清空搜索 */
  296. clearInput() {
  297. this.$emit("clearInput");
  298. },
  299. /* 禁用状态下点击搜索框 */
  300. clickInput() {
  301. this.$emit("clickInput");
  302. },
  303. },
  304. created() {
  305. this.init();
  306. },
  307. onReady() {
  308. // setTimeout(() => {
  309. // // 改变手机状态栏颜色
  310. // uni.setNavigationBarColor({
  311. // frontColor: "#000000",
  312. // backgroundColor: "#FF4258",
  313. // });
  314. // }, 10);
  315. },
  316. };
  317. </script>
  318. <style lang="scss" scoped>
  319. .nav {
  320. position: relative;
  321. }
  322. .nv_padding {
  323. height: 88upx;
  324. background-color: transparent;
  325. }
  326. /* 图标默认大小 */
  327. .nv_icon {
  328. width: 16px;
  329. height: 16px;
  330. }
  331. .bg_box {
  332. position: absolute;
  333. width: 750upx;
  334. height: 88upx;
  335. z-index: 10;
  336. top: 0;
  337. background-color: transparent;
  338. /* #ifdef MP */
  339. box-sizing: border-box;
  340. /* #endif */
  341. /* #ifndef APP-PLUS-NVUE */
  342. background-size: cover;
  343. background-repeat: no-repeat;
  344. background-position: center center;
  345. /* #endif */
  346. }
  347. .mys_navBar {
  348. /* #ifndef APP-PLUS-NVUE */
  349. display: flex;
  350. height: 88upx;
  351. /* #endif */
  352. // #ifdef MP
  353. box-sizing: border-box;
  354. // #endif
  355. width: 750upx;
  356. flex-direction: row;
  357. background-color: transparent;
  358. position: absolute;
  359. z-index: 10;
  360. top: 0;
  361. }
  362. .fixed {
  363. position: fixed;
  364. }
  365. /*
  366. left 按钮
  367. */
  368. .btn_type {
  369. /* #ifndef APP-PLUS-NVUE */
  370. display: flex;
  371. /* #endif */
  372. /* #ifdef APP-PLUS-NVUE */
  373. margin-left: 16upx;
  374. /* #endif */
  375. // #ifndef MP
  376. align-items: center;
  377. // #endif
  378. flex: 1;
  379. // background-color: #fff;
  380. flex-direction: row;
  381. }
  382. .btn_box {
  383. /* #ifndef APP-PLUS-NVUE */
  384. display: flex;
  385. margin-left: 16upx;
  386. /* #endif */
  387. flex-direction: row;
  388. // #ifndef MP
  389. align-items: center;
  390. // #endif
  391. }
  392. .btn_back,
  393. .btn_home {
  394. /* #ifndef APP-PLUS-NVUE */
  395. display: flex;
  396. /* #endif */
  397. /* #ifndef APP-PLUS-NVUE */
  398. height: 100%;
  399. /* #endif */
  400. /* #ifdef APP-PLUS-NVUE */
  401. width: 76upx;
  402. height: 62upx;
  403. /* #endif */
  404. flex-direction: row;
  405. align-items: center;
  406. justify-content: center;
  407. flex: 1;
  408. }
  409. /* 按钮类型1 */
  410. .nav_btn_t1 {
  411. /* #ifndef APP-PLUS-NVUE */
  412. display: flex;
  413. /* #endif */
  414. // #ifdef MP
  415. box-sizing: border-box;
  416. // #endif
  417. flex-direction: row;
  418. align-items: center;
  419. border-style: solid;
  420. border-width: 1px;
  421. border-color: #C0C0C0;
  422. // background-color: rgba(0, 0, 0, 0.2);
  423. background-color: #FFFFFF;
  424. width: 150upx;
  425. height: 45upx;
  426. }
  427. .line {
  428. width: 1upx;
  429. height: 60%;
  430. /* #ifdef APP-PLUS-NVUE */
  431. height: 30upx;
  432. /* #endif */
  433. background-color: #C0C0C0;
  434. }
  435. /*
  436. 标题
  437. */
  438. .title_container {
  439. /* #ifndef APP-PLUS-NVUE */
  440. display: flex;
  441. /* #endif */
  442. position: absolute;
  443. left: 375upx;
  444. bottom: 0;
  445. transform: translateX(-50%);
  446. flex-direction: row;
  447. justify-content: center;
  448. align-items: center;
  449. }
  450. .title_text {
  451. // flex: 1;
  452. text-overflow: ellipsis;
  453. /* #ifndef APP-PLUS-NVUE */
  454. white-space: nowrap;
  455. overflow: hidden;
  456. font-weight:550;
  457. /* #endif */
  458. /* #ifdef APP-PLUS-NVUE */
  459. lines: 1;
  460. /* #endif */
  461. }
  462. /*
  463. 左边自定义
  464. */
  465. .my_left_box {
  466. /* #ifndef APP-PLUS-NVUE */
  467. display: flex;
  468. /* #endif */
  469. flex-direction: row;
  470. align-items: center;
  471. }
  472. .my_left_icon {
  473. /* #ifndef APP-PLUS-NVUE */
  474. display: flex;
  475. /* #endif */
  476. flex-direction: row;
  477. align-items: center;
  478. justify-content: center;
  479. /* #ifndef MP */
  480. margin-left: 18upx;
  481. /* #endif */
  482. }
  483. .my_left_custom {
  484. /* #ifndef APP-PLUS-NVUE */
  485. display: flex;
  486. /* #endif */
  487. flex-direction: row;
  488. align-items: center;
  489. // justify-content: center;
  490. }
  491. /* 文字 */
  492. .leftText {
  493. /* #ifndef APP-PLUS-NVUE */
  494. display: flex;
  495. /* #endif */
  496. flex-direction: row;
  497. align-items: center;
  498. justify-content: center;
  499. padding-left: 4upx;
  500. font-size: 15px;
  501. }
  502. /*
  503. 中间
  504. */
  505. .my_custom_box {
  506. /* #ifndef APP-PLUS-NVUE */
  507. display: flex;
  508. /* #endif */
  509. flex-direction: row;
  510. align-items: center;
  511. justify-content: center;
  512. flex: 1;
  513. }
  514. /*
  515. 搜索框
  516. */
  517. .nv_search_box {
  518. /* #ifndef APP-PLUS-NVUE */
  519. display: flex;
  520. /* #endif */
  521. flex-direction: row;
  522. align-items: center;
  523. flex: 1;
  524. /* #ifndef MP */
  525. height: 60upx;
  526. /* #endif */
  527. background-color: #f8f8f8;
  528. padding-right: 20upx;
  529. padding-left: 20upx;
  530. border-radius: 60upx;
  531. margin-right: 15upx;
  532. margin-left: 15upx;
  533. }
  534. .nv_input {
  535. flex: 1;
  536. padding-left: 16upx;
  537. font-size: 13px;
  538. }
  539. .close {
  540. width: 50upx;
  541. /* #ifndef APP-PLUS-NVUE */
  542. display: flex;
  543. /* #endif */
  544. flex-direction: row;
  545. align-items: center;
  546. justify-content: center;
  547. /* #ifndef MP */
  548. height: 62upx;
  549. /* #endif */
  550. }
  551. /*
  552. 右边 自定义
  553. */
  554. .my_right_icon {
  555. /* #ifndef APP-PLUS-NVUE */
  556. display: flex;
  557. /* #endif */
  558. flex-direction: row;
  559. align-items: center;
  560. justify-content: center;
  561. /* #ifndef MP */
  562. // min-width: 70upx;
  563. /* #endif */
  564. padding-left: 6px;
  565. padding-right: 10px;
  566. }
  567. </style>