Browse Source

feat: fixednav

richard1015 5 years ago
parent
commit
416aa0d7c1

+ 1 - 0
package.json

@@ -49,6 +49,7 @@
     "@commitlint/cli": "^8.0.0",
     "@commitlint/config-conventional": "^8.0.0",
     "@nutui/cli": "^0.2.3",
+    "autoprefixer": "^9.8.4",
     "babel-plugin-istanbul": "^6.0.0",
     "gsap": "^3.2.6",
     "husky": "^3.0.0",

+ 9 - 0
src/config.json

@@ -651,6 +651,15 @@
       "sort": "0",
       "showDemo": true,
       "author": "yumingming"
+    },
+    {
+      "name": "FixedNav",
+      "type": "component",
+      "chnName": "悬浮导航",
+      "desc": "拖拽导航",
+      "sort": "3",
+      "showDemo": true,
+      "author": "richard1015"
     }
   ]
 }

+ 17 - 14
src/nutui.js

@@ -128,6 +128,8 @@ import Notify from "./packages/notify/index.js";
 import "./packages/notify/notify.scss";
 import CountUp from "./packages/countup/index.js";
 import "./packages/countup/countup.scss";
+import FixedNav from "./packages/fixednav/index.js";
+import "./packages/fixednav/fixednav.scss";
 
 const packages = {
   Cell,
@@ -178,20 +180,21 @@ const packages = {
   Elevator,
   Popup,
   LeftSlip,
-  TabSelect: TabSelect,
-  LuckDraw: LuckDraw,
-  Video: Video,
-  Signature: Signature,
-  CircleProgress: CircleProgress,
-  TimeLine: TimeLine,
-  TimeLineItem: TimeLineItem,
-  SideNavBar: SideNavBar,
-  SubSideNavBar: SubSideNavBar,
-  SideNavBarItem: SideNavBarItem,
-  Drag: Drag,
-  Address: Address,
-  Notify: Notify,
-  CountUp: CountUp
+  TabSelect,
+  LuckDraw,
+  Video,
+  Signature,
+  CircleProgress,
+  TimeLine,
+  TimeLineItem,
+  SideNavBar,
+  SubSideNavBar,
+  SideNavBarItem,
+  Drag,
+  Address,
+  Notify,
+  CountUp,
+  FixedNav
 };
 
 const components = {};

+ 90 - 0
src/packages/fixednav/demo.vue

@@ -0,0 +1,90 @@
+<template>
+  <div class="demo-list">
+    <nut-noticebar :closeMode="true" v-if="!isMobile">此 Demo 仅能在移动端浏览器体验,建议在 Android 或 iOS 设备上体验。 </nut-noticebar>
+    <!-- 基本用法 -->
+    <nut-drag direction="y" :style="{right:'0px',top:'50px'}">
+      <nut-fixednav active-text="右侧收起" un-active-text="右侧展开" :nav-list="navList" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <nut-drag direction="y" :style="{left:'0px',top:'100px'}">
+      <nut-fixednav active-text="左侧收起" un-active-text="左侧展开" type="left" :nav-list="navList" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <nut-drag direction="y" :style="{right:'0px',top:'150px'}">
+      <nut-fixednav :nav-list="navList" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <nut-drag direction="y" :style="{left:'0px',top:'200px'}">
+      <nut-fixednav :nav-list="navList" type="left" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <nut-drag direction="y" :style="{right:'0px',top:'250px'}">
+      <nut-fixednav :nav-list="navList" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <nut-drag direction="y" :style="{left:'0px',top:'300px'}">
+      <nut-fixednav :nav-list="navList" type="left" @selected="selected">
+      </nut-fixednav>
+    </nut-drag>
+    <!-- 自定义用法 -->
+    <nut-drag direction="y" :style="{left:'0px',top:'300px'}">
+      <nut-fixednav :active.sync="myActive" type="left" @selected="selected">
+        <ul slot="list" class="fixed-list">
+          <li>1</li>
+          <li>2</li>
+          <li>3</li>
+          <li>4</li>
+          <li>5</li>
+        </ul>
+        <template slot="btn" @click="myActive=!myActive">
+          <img style="width:20px;height:20px"
+            src="https://img10.360buyimg.com/imagetools/jfs/t1/143466/8/1743/6993/5ef9fb50E10f30d87/993e4e681fc50cac.png" />
+          <span>{{myActive?'自定义开':'自定义关'}}</span>
+        </template>
+      </nut-fixednav>
+    </nut-drag>
+
+    <!-- 无拖拽效果 -->
+    <nut-fixednav active-text="收起" un-active-text="无法拖拽" :style="{position:'fixed',bottom:'10px',right:'0px'}"
+      :nav-list="navList" @selected="selected">
+    </nut-fixednav>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      myActive: false,
+      navList: [
+        {
+          id: 1,
+          text: '首页',
+          icon: 'https://img11.360buyimg.com/imagetools/jfs/t1/117646/2/11112/1297/5ef83e95E81d77f05/daf8e3b1c81e3c98.png'
+        },
+        {
+          id: 2,
+          text: '分类',
+          icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/119490/8/9568/1798/5ef83e95E968c69a6/dd029326f7d5042e.png'
+        },
+        {
+          id: 3,
+          text: '购物车',
+          num: 2,
+          icon: 'https://img14.360buyimg.com/imagetools/jfs/t1/130725/4/3157/1704/5ef83e95Eb976644f/b36c6cfc1cc1a99d.png'
+        },
+        {
+          id: 4,
+          text: '我的',
+          icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/147573/29/1603/1721/5ef83e94E1393a678/5ddf1695ec989373.png'
+        }
+      ]
+    };
+  },
+  methods: {
+    selected($event) {
+      console.log($event);
+    }
+  }
+};
+</script>

+ 116 - 0
src/packages/fixednav/doc.md

@@ -0,0 +1,116 @@
+# FixedNav 悬浮导航
+
+可拖拽的悬浮导航
+
+## 基本用法
+
+```html
+<!-- 基本用法 -->
+<nut-drag direction="y" :style="{right:'0px',top:'50px'}">
+    <nut-fixednav active-text="右侧收起" un-active-text="右侧展开" :nav-list="navList" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<nut-drag direction="y" :style="{left:'0px',top:'100px'}">
+    <nut-fixednav active-text="左侧收起" un-active-text="左侧展开" type="left" :nav-list="navList" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<nut-drag direction="y" :style="{right:'0px',top:'150px'}">
+    <nut-fixednav :nav-list="navList" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<nut-drag direction="y" :style="{left:'0px',top:'200px'}">
+    <nut-fixednav :nav-list="navList" type="left" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<nut-drag direction="y" :style="{right:'0px',top:'250px'}">
+    <nut-fixednav :nav-list="navList" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<nut-drag direction="y" :style="{left:'0px',top:'300px'}">
+    <nut-fixednav :nav-list="navList" type="left" @selected="selected">
+    </nut-fixednav>
+</nut-drag>
+<!-- 自定义用法 -->
+<nut-drag direction="y" :style="{left:'0px',top:'300px'}">
+    <nut-fixednav :active.sync="myActive" type="left" @selected="selected">
+    <ul slot="list" class="fixed-list">
+        <li>1</li>
+        <li>2</li>
+        <li>3</li>
+        <li>4</li>
+        <li>5</li>
+    </ul>
+    <template slot="btn" @click="myActive=!myActive">
+        <img style="width:20px;height:20px"
+        src="https://img10.360buyimg.com/imagetools/jfs/t1/143466/8/1743/6993/5ef9fb50E10f30d87/993e4e681fc50cac.png" />
+        <span>{{myActive?'自定义开':'自定义关'}}</span>
+    </template>
+    </nut-fixednav>
+</nut-drag>
+
+<!-- 无拖拽效果 -->
+<nut-fixednav active-text="收起" un-active-text="无法拖拽" :style="{position:'fixed',bottom:'10px',right:'0px'}"
+    :nav-list="navList" @selected="selected">
+</nut-fixednav>
+```
+
+``` javascript
+export default {
+  data() {
+    return {
+      myActive: false,
+      navList: [
+        {
+          id: 1,
+          text: '首页',
+          icon: 'https://img11.360buyimg.com/imagetools/jfs/t1/117646/2/11112/1297/5ef83e95E81d77f05/daf8e3b1c81e3c98.png'
+        },
+        {
+          id: 2,
+          text: '分类',
+          icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/119490/8/9568/1798/5ef83e95E968c69a6/dd029326f7d5042e.png'
+        },
+        {
+          id: 3,
+          text: '购物车',
+          num: 2,
+          icon: 'https://img14.360buyimg.com/imagetools/jfs/t1/130725/4/3157/1704/5ef83e95Eb976644f/b36c6cfc1cc1a99d.png'
+        },
+        {
+          id: 4,
+          text: '我的',
+          icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/147573/29/1603/1721/5ef83e94E1393a678/5ddf1695ec989373.png'
+        }
+      ]
+    };
+  },
+  methods: {
+    selected($event) {
+      console.log($event);
+    }
+  }
+};
+```
+
+## Prop
+| 字段           | 说明                       | 类型    | 默认值     |
+|:---------------|:---------------------------|:--------|:-----------|
+| active         | 是否打开                   | Boolean | false      |
+| navList        | 悬浮列表内容数据           | Array   | []         |
+| active-text    | 收起列表按钮文案           | String  | '收起导航' |
+| un-active-text | 展开列表按钮文案           | String  | '快速导航' |
+| type           | 导航方向,可选值 left right | String  | 'right'     |
+
+
+## Slot
+
+| 名称 | 说明               |
+|------|--------------------|
+| btn  | 自定义按钮         |
+| list | 自定义展开列表内容 |
+
+## Event
+
+| 字段     | 说明         | 回调参数                 |
+|----------|--------------|--------------------------|
+| selected | 选择之后触发 | {item:item,$event:Event} |

+ 135 - 0
src/packages/fixednav/fixednav.scss

@@ -0,0 +1,135 @@
+.nut-fixednav {
+    height: 50px;
+    display: flex;
+    align-items: center;
+    position: relative;
+    z-index: 0;
+    width: 300px;
+
+    &.active {
+        &.left {
+            .fixed-btn img {
+                transform: rotate(180deg);
+            }
+            .fixed-list {
+                left: 0;
+            }
+        }
+        .fixed-btn {
+            img {
+                transform: rotate(0deg);
+            }
+        }
+        .fixed-list {
+            right: 0;
+        }
+    }
+
+    .fixed-btn {
+        box-sizing: border-box;
+        position: absolute;
+        right: 0;
+        z-index: 2;
+        width: 50px;
+        padding-left: 5px;
+        height: 50px;
+        background: linear-gradient(
+            135deg,
+            rgba(242, 20, 12, 1) 0%,
+            rgba(242, 39, 12, 1) 70%,
+            rgba(242, 77, 12, 1) 100%
+        );
+        border-radius: 25px 0px 0px 25px;
+        box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        > img {
+            margin-right: 5px;
+            width: 4px;
+            height: 10px;
+            flex-shrink: 0;
+            transition: all 0.3s;
+            transform: rotate(180deg);
+        }
+        > span {
+            width: 24px;
+            line-height: 13px;
+            font-size: 10px;
+            color: $fixed-bg-color;
+            flex-shrink: 0;
+        }
+    }
+    ul.fixed-list {
+        position: absolute;
+        right: -100%;
+        transition: all 0.5s;
+        z-index: 1;
+        flex-shrink: 0;
+        height: 44px;
+        background: $fixed-bg-color;
+        display: flex;
+        justify-content: space-between;
+        border-radius: 25px 0px 0px 25px;
+        box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, 0.2);
+        padding: {
+            left: 20px;
+            right: 50px;
+        }
+        li {
+            position: relative;
+            flex: 1;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            min-width: 40px;
+            flex-shrink: 0;
+            > img {
+                width: 20px;
+                height: 20px;
+                margin-bottom: 2px;
+            }
+            span {
+                font-size: 10px;
+                color: $fixed-font-color;
+            }
+            b {
+                position: absolute;
+                right: 0;
+                top: 1px;
+                height: 14px;
+                line-height: 14px;
+                font-size: 10px;
+                padding: 0 3px;
+                color: $primary-color;
+                background: $fixed-bg-color;
+                border: 1px solid $primary-color;
+                border-radius: 7px;
+                text-align: center;
+                min-width: 12px;
+            }
+        }
+    }
+    &.left {
+        .fixed-btn {
+            flex-direction: row-reverse;
+            right: auto;
+            left: 0;
+            border-radius: 0 25px 25px 0;
+            > img {
+                transform: rotate(0deg);
+            }
+        }
+        ul.fixed-list {
+            left: -100%;
+            right: auto;
+            border-radius: 0px 25px 25px 0px;
+            padding: {
+                left: 50px;
+                right: 20px;
+            }
+        }
+    }
+}

+ 79 - 0
src/packages/fixednav/fixednav.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="nut-fixednav" :class="styled">
+    <div style="position:relative;z-index:1">
+      <nut-popup v-model="defaultActive"></nut-popup>
+    </div>
+    <slot name="list">
+      <ul class="fixed-list">
+        <li v-for="(item,index) in navList" @click="selected(item,$event)" :key="item.id||index">
+          <img :src="item.icon" />
+          <span>{{item.text}}</span>
+          <b v-if="item.num">{{item.num}}</b>
+        </li>
+      </ul>
+    </slot>
+
+    <div class="fixed-btn" @click="defaultActive=!defaultActive">
+      <slot name="btn">
+        <img
+          src="https://img14.360buyimg.com/imagetools/jfs/t1/149975/30/1615/368/5ef86176Eb75bae46/5f70ae80a2d567b4.png" />
+        <span>{{defaultActive?activeText:unActiveText}}</span>
+      </slot>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'nut-fixednav',
+  props: {
+    active: {
+      type: Boolean,
+      default: false
+    },
+    navList: {
+      default: () => [],
+      type: Array
+    },
+    activeText: {
+      default: '收起导航',
+      type: String
+    },
+    unActiveText: {
+      default: '快速导航',
+      type: String
+    },
+    type: {
+      default: 'right',
+      type: String
+    }
+  },
+  computed: {
+    styled() {
+      return {
+        active: this.defaultActive,
+        [this.defaultType]: true
+      };
+    }
+  },
+  watch: {
+    defaultActive(newV, oldV) {
+      this.$emit('update:active', newV);
+    }
+  },
+  data() {
+    return {
+      defaultActive: false,
+      defaultType: ''
+    };
+  },
+  mounted() {
+    this.defaultActive = this.active;
+    this.defaultType = this.type;
+  },
+  methods: {
+    selected(item, $event) {
+      this.$emit('selected', { item, $event });
+    }
+  }
+};
+</script>

+ 8 - 0
src/packages/fixednav/index.js

@@ -0,0 +1,8 @@
+import FixedNav from './fixednav.vue';
+import './fixednav.scss';
+
+FixedNav.install = function(Vue) {
+  Vue.component(FixedNav.name, FixedNav);
+};
+
+export default FixedNav

+ 13 - 3
src/styles/variable.scss

@@ -10,7 +10,8 @@ $dark-color: #dadada !default;
 // ---- base ----
 $body-background: #f6f6f6 !default;
 $mask-bg: rgba(0, 0, 0, 0.5) !default;
-$font-family: PingHei, 'Lucida Grande', 'Lucida Sans Unicode', STHeiti, Helvetica, Arial, Verdana, 'sans-serif', 'PingHei-light', SimHei, 'Droid Sans' !default;
+$font-family: PingHei, "Lucida Grande", "Lucida Sans Unicode", STHeiti, Helvetica, Arial, Verdana, "sans-serif",
+    "PingHei-light", SimHei, "Droid Sans" !default;
 $font-size-base: 14px !default;
 $font-size-small: 12px !default;
 $font-size-large: 16px !default;
@@ -60,7 +61,11 @@ $btn-gradient-color: #fff !default;
 $btn-gradient-start-color: #ff4f18;
 $btn-gradient-end-color: #f20000;
 $btn-gradient-bg: linear-gradient(315deg, $btn-gradient-start-color 0%, $btn-gradient-end-color 100%) !default;
-$btn-gradient-active-bg: linear-gradient(315deg, darken($btn-gradient-start-color, 10%) 0%, darken($btn-gradient-end-color, 10%) 100%) !default;
+$btn-gradient-active-bg: linear-gradient(
+    315deg,
+    darken($btn-gradient-start-color, 10%) 0%,
+    darken($btn-gradient-end-color, 10%) 100%
+) !default;
 $btn-default-color: $normal-color !default;
 $btn-default-bg: #fff !default;
 $btn-default-border: $border-color-dark !default;
@@ -78,7 +83,7 @@ $zindex-actionsheet: 10001 !default;
 $zindex-dialog: 10000 !default;
 $zindex-picker: 10050 !default;
 // ---- Assets path ----
-$assetsPath: '../../assets' !default;
+$assetsPath: "../../assets" !default;
 // ---- Stepper ----
 $stepper-color: #333 !default;
 $stepperbar-width: 11px !default;
@@ -93,3 +98,8 @@ $notify-primary-background-color: #1989fa;
 $notify-success-background-color: #07c160;
 $notify-danger-background-color: #ee0a24;
 $notify-warning-background-color: #ff976a;
+
+// Fixed
+
+$fixed-bg-color: #fff;
+$fixed-font-color: #333;

+ 1 - 1
types/nutui.d.ts

@@ -68,7 +68,6 @@ export declare class Elevator extends UIComponent { }
 export declare class LeftSlip extends UIComponent { }
 export declare class TabSelect extends UIComponent { }
 export declare class Popup extends UIComponent { }
-
 export declare class LuckDraw extends UIComponent { }
 export declare class Video extends UIComponent { }
 export declare class Signature extends UIComponent { }
@@ -83,3 +82,4 @@ export declare class Drag extends UIComponent { }
 export declare class Address extends UIComponent { }
 export declare class Notify extends UIComponent { }
 export declare class CountUp extends UIComponent { }
+export declare class FixedNav extends UIComponent { }