yangxiaolu3 3 年 前
コミット
4c64c57f4d

+ 28 - 24
src/packages/__VUE/popover/demo.vue

@@ -4,26 +4,14 @@
 
 
     <nut-row type="flex">
     <nut-row type="flex">
       <nut-col :span="8">
       <nut-col :span="8">
-        <nut-popover
-          v-model:visible="lightTheme"
-          :list="iconItemList"
-          location="bottom-end"
-          @choose="chooseItem"
-          overlay="true"
-        >
+        <nut-popover v-model:visible="lightTheme" :list="iconItemList" location="bottom-start" @choose="chooseItem">
           <template #reference>
           <template #reference>
             <nut-button type="primary" shape="square">{{ translate('light') }}</nut-button>
             <nut-button type="primary" shape="square">{{ translate('light') }}</nut-button>
           </template>
           </template>
         </nut-popover>
         </nut-popover>
       </nut-col>
       </nut-col>
       <nut-col :span="8">
       <nut-col :span="8">
-        <nut-popover
-          v-model:visible="darkTheme"
-          theme="dark"
-          location="bottom-start"
-          :list="iconItemList"
-          :offset="[0, 12]"
-        >
+        <nut-popover v-model:visible="darkTheme" theme="dark" location="bottom-start" :list="iconItemList">
           <template #reference>
           <template #reference>
             <nut-button type="primary" shape="square">{{ translate('dark') }}</nut-button>
             <nut-button type="primary" shape="square">{{ translate('dark') }}</nut-button>
           </template>
           </template>
@@ -81,17 +69,28 @@
       v-model:visible="customPositon"
       v-model:visible="customPositon"
       targetId="pickerTarget"
       targetId="pickerTarget"
       :location="curPostion"
       :location="curPostion"
-      bgColor="#f00"
       theme="dark"
       theme="dark"
       :list="positionList"
       :list="positionList"
     >
     >
     </nut-popover>
     </nut-popover>
 
 
-    <h2>自定义对象</h2>
-    <nut-button type="primary" shape="square" id="popid" @click="clickCustomHandle;">{{
-      translate('light')
-    }}</nut-button>
-    <nut-popover v-model:visible="customTarget" targetId="popid" :list="iconItemList" location="top-start">
+    <h2>{{ translate('contentTarget') }}</h2>
+    <nut-button type="primary" shape="square" id="popid" @click="clickCustomHandle">
+      {{ translate('contentTarget') }}
+    </nut-button>
+    <nut-popover
+      v-model:visible="customTarget"
+      targetId="popid"
+      :list="iconItemList"
+      location="top-start"
+    ></nut-popover>
+
+    <h2>{{ translate('contentColor') }}</h2>
+
+    <nut-popover v-model:visible="customColor" :list="iconItemList" location="right-start" bgColor="#f00" theme="dark">
+      <template #reference>
+        <nut-button type="primary" shape="square">{{ translate('contentColor') }}</nut-button>
+      </template>
     </nut-popover>
     </nut-popover>
   </div>
   </div>
 </template>
 </template>
@@ -112,7 +111,9 @@ const initTranslate = () =>
       dark: '暗黑风格',
       dark: '暗黑风格',
       showIcon: '展示图标',
       showIcon: '展示图标',
       disableAction: '禁用选项',
       disableAction: '禁用选项',
-      content: '自定义内容'
+      content: '自定义内容',
+      contentColor: '自定义颜色',
+      contentTarget: '自定义对象'
     },
     },
     'en-US': {
     'en-US': {
       title: 'Basic Usage',
       title: 'Basic Usage',
@@ -123,7 +124,9 @@ const initTranslate = () =>
       dark: 'dark',
       dark: 'dark',
       showIcon: 'show icon',
       showIcon: 'show icon',
       disableAction: 'disabled',
       disableAction: 'disabled',
-      content: 'custom content'
+      content: 'custom content',
+      contentColor: 'custom color',
+      contentTarget: 'custom target'
     }
     }
   });
   });
 export default createDemo({
 export default createDemo({
@@ -143,7 +146,8 @@ export default createDemo({
 
 
       showPicker: false,
       showPicker: false,
 
 
-      customTarget: false
+      customTarget: false,
+      customColor: false
     });
     });
     const curPostion = ref('top');
     const curPostion = ref('top');
 
 
@@ -257,9 +261,9 @@ export default createDemo({
     };
     };
 
 
     const clickCustomHandle = () => {
     const clickCustomHandle = () => {
-      console.log('点击', state.customTarget);
       state.customTarget = !state.customTarget;
       state.customTarget = !state.customTarget;
     };
     };
+
     return {
     return {
       iconItemList,
       iconItemList,
       itemList,
       itemList,

+ 44 - 11
src/packages/__VUE/popover/index.vue

@@ -1,5 +1,7 @@
 <template>
 <template>
-  <div class="nut-popover-wrapper" @click="openPopover" ref="popoverRef"><slot name="reference"></slot></div>
+  <div class="nut-popover-wrapper" @click="openPopover" ref="popoverRef" v-if="!targetId"
+    ><slot name="reference"></slot
+  ></div>
   <view :class="['nut-popover', `nut-popover--${theme}`, `${customClass}`]" :style="getRootPosition">
   <view :class="['nut-popover', `nut-popover--${theme}`, `${customClass}`]" :style="getRootPosition">
     <nut-popup
     <nut-popup
       :popClass="`nut-popover-content nut-popover-content--${location}`"
       :popClass="`nut-popover-content nut-popover-content--${location}`"
@@ -49,6 +51,7 @@ export default create({
     theme: { type: String as PropType<import('./type').PopoverTheme>, default: 'light' },
     theme: { type: String as PropType<import('./type').PopoverTheme>, default: 'light' },
     location: { type: String as PropType<import('./type').PopoverLocation>, default: 'bottom' },
     location: { type: String as PropType<import('./type').PopoverLocation>, default: 'bottom' },
     offset: { type: Array, default: [0, 12] },
     offset: { type: Array, default: [0, 12] },
+    arrowOffset: { type: Number, default: 0 },
     customClass: { type: String, default: '' },
     customClass: { type: String, default: '' },
     showArrow: { type: Boolean, default: true },
     showArrow: { type: Boolean, default: true },
     iconPrefix: { type: String, default: 'nut-icon' },
     iconPrefix: { type: String, default: 'nut-icon' },
@@ -84,11 +87,40 @@ export default create({
 
 
     const popoverArrowStyle = computed(() => {
     const popoverArrowStyle = computed(() => {
       const styles: CSSProperties = {};
       const styles: CSSProperties = {};
-      const direction = upperCaseFirst(props.location.split('-')[0]);
-      if (props.bgColor) {
-        styles[`border${direction}Color`] = props.bgColor;
+      const { bgColor, arrowOffset, location } = props;
+      const direction = location.split('-')[0];
+      const skew = location.split('-')[1];
+      const base = 16;
+
+      if (bgColor) {
+        styles[`border${upperCaseFirst(direction)}Color`] = bgColor;
       }
       }
 
 
+      if (props.arrowOffset != 0) {
+        if (['bottom', 'top'].includes(direction)) {
+          if (!skew) {
+            styles.left = `calc(50% + ${arrowOffset}px)`;
+          }
+          if (skew == 'start') {
+            styles.left = `${base + arrowOffset}px`;
+          }
+          if (skew == 'end') {
+            styles.right = `${base - arrowOffset}px`;
+          }
+        }
+
+        if (['left', 'right'].includes(direction)) {
+          if (!skew) {
+            styles.top = `calc(50% - ${arrowOffset}px)`;
+          }
+          if (skew == 'start') {
+            styles.top = `${base - arrowOffset}px`;
+          }
+          if (skew == 'end') {
+            styles.bottom = `${base + arrowOffset}px`;
+          }
+        }
+      }
       return styles;
       return styles;
     });
     });
 
 
@@ -111,36 +143,37 @@ export default create({
       const direction = location.split('-')[0];
       const direction = location.split('-')[0];
       const skew = location.split('-')[1];
       const skew = location.split('-')[1];
       let cross = 0;
       let cross = 0;
+      let parallel = 0;
       if (isArray(offset) && offset.length == 2) {
       if (isArray(offset) && offset.length == 2) {
         cross += +offset[1];
         cross += +offset[1];
+        parallel += +offset[0];
       }
       }
       if (width) {
       if (width) {
         if (['bottom', 'top'].includes(direction)) {
         if (['bottom', 'top'].includes(direction)) {
-          console.log('高度', conentHeight);
           const h = direction == 'bottom' ? height + cross : -(conentHeight + cross);
           const h = direction == 'bottom' ? height + cross : -(conentHeight + cross);
           styles.top = `${top + h}px`;
           styles.top = `${top + h}px`;
 
 
           if (!skew) {
           if (!skew) {
-            styles.left = `${-(conentWidth - width) / 2 + left}px`;
+            styles.left = `${-(conentWidth - width) / 2 + left + parallel}px`;
           }
           }
           if (skew == 'start') {
           if (skew == 'start') {
-            styles.left = `${left}px`;
+            styles.left = `${left + parallel}px`;
           }
           }
           if (skew == 'end') {
           if (skew == 'end') {
-            styles.left = `${rootRect.value.right}px`;
+            styles.left = `${rootRect.value.right + parallel}px`;
           }
           }
         }
         }
         if (['left', 'right'].includes(direction)) {
         if (['left', 'right'].includes(direction)) {
           const contentW = direction == 'left' ? -(conentWidth + cross) : width + cross;
           const contentW = direction == 'left' ? -(conentWidth + cross) : width + cross;
           styles.left = `${left + contentW}px`;
           styles.left = `${left + contentW}px`;
           if (!skew) {
           if (!skew) {
-            styles.top = `${top - conentHeight / 2 + height / 2 - 4}px`;
+            styles.top = `${top - conentHeight / 2 + height / 2 - 4 + parallel}px`;
           }
           }
           if (skew == 'start') {
           if (skew == 'start') {
-            styles.top = `${top}px`;
+            styles.top = `${top + parallel}px`;
           }
           }
           if (skew == 'end') {
           if (skew == 'end') {
-            styles.top = `${top + height}px`;
+            styles.top = `${top + height + parallel}px`;
           }
           }
         }
         }
       }
       }

+ 138 - 41
src/packages/__VUE/tour/demo.vue

@@ -2,16 +2,95 @@
   <div class="demo">
   <div class="demo">
     <h2>{{ translate('title') }}</h2>
     <h2>{{ translate('title') }}</h2>
 
 
-    <div class="music" @click="showTourHandle"> 新手引导 </div>
+    <nut-cell title="点击试试" @click="showTour3 = true">
+      <template v-slot:link>
+        <nut-switch id="target7" />
+      </template>
+    </nut-cell>
 
 
-    <div>
-      <div class="index-header"
-        ><img
-          src="https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png"
-          @click="showTour2 = true"
-        /><div class="info"><h1>NutUI</h1><p id="target6">京东风格的轻量级移动端 Vue 组件库</p></div></div
-      >
-    </div>
+    <nut-tour
+      class="nut-custom-tour nut-customword-tour"
+      v-model:visible="showTour3"
+      :steps="steps3"
+      type="tile"
+      location="bottom-end"
+    ></nut-tour>
+
+    <h2>自定义样式</h2>
+
+    <nut-cell title="点击试试" @click="showTourHandle">
+      <template v-slot:link>
+        <nut-switch id="target5" />
+      </template>
+    </nut-cell>
+
+    <nut-tour
+      class="nut-custom-tour nut-customword-tour nut-customstyle-tour"
+      v-model:visible="showTour1"
+      :steps="steps1"
+      location="bottom-end"
+      type="tile"
+      bgColor="#f00"
+      theme="dark"
+      :offset="[0, 0]"
+      maskWidth="50"
+      maskHeight="50"
+    ></nut-tour>
+
+    <h2>设置偏移量</h2>
+
+    <nut-cell title="点击试试" @click="showTour2 = true">
+      <template v-slot:link>
+        <div class="tour-demo-img">
+          <img
+            id="target6"
+            src="https://img14.360buyimg.com/imagetools/jfs/t1/167902/2/8762/791358/603742d7E9b4275e3/e09d8f9a8bf4c0ef.png"
+            alt=""
+          />
+          <img
+            src="https://img10.360buyimg.com/imagetools/jfs/t1/31842/40/20385/1762/63998e3eE594254bb/98ff51da635ead4a.png"
+            alt=""
+          />
+          <img src="https://storage.jd.com/oss-dev/test/3.2.6/Jdweapp.png" alt="" />
+        </div>
+      </template>
+    </nut-cell>
+
+    <nut-tour
+      class="nut-custom-tour nut-customword-tour"
+      v-model:visible="showTour2"
+      :steps="steps2"
+      type="tile"
+      bgColor="#f00"
+      theme="dark"
+      location="bottom-end"
+      :offset="[8, 8]"
+    ></nut-tour>
+
+    <h2>自定义内容</h2>
+
+    <nut-cell title="点击试试" @click="showTour4 = true">
+      <template v-slot:link>
+        <nut-switch id="target8" />
+      </template>
+    </nut-cell>
+
+    <nut-tour
+      class="nut-custom-tour nut-customword-tour"
+      v-model:visible="showTour4"
+      :steps="steps4"
+      type="tile"
+      theme="dark"
+      location="bottom-end"
+      :offset="[8, 8]"
+      :closeOnClickOverlay="false"
+    >
+      <div class="tour-demo-custom-content">
+        <div>nutui 4.x 即将发布,敬请期待</div>
+        <nut-divider direction="vertical" />
+        <div @click="showTour4 = false">知道了</div>
+      </div>
+    </nut-tour>
 
 
     <nut-tabbar :bottom="true">
     <nut-tabbar :bottom="true">
       <nut-tabbar-item
       <nut-tabbar-item
@@ -40,40 +119,14 @@
       ></nut-tabbar-item>
       ></nut-tabbar-item>
     </nut-tabbar>
     </nut-tabbar>
 
 
-    <nut-grid icon-size="18px">
-      <nut-grid-item icon="my2" text="文字"></nut-grid-item>
-      <nut-grid-item icon="star" text="文字"></nut-grid-item>
-      <nut-grid-item icon="dshop" text="文字"></nut-grid-item>
-      <nut-grid-item icon="shop" text="文字" id="target5"></nut-grid-item>
-    </nut-grid>
-
     <nut-tour
     <nut-tour
       class="nut-custom-tour"
       class="nut-custom-tour"
       v-model:visible="showTour"
       v-model:visible="showTour"
       :steps="steps"
       :steps="steps"
       location="top-start"
       location="top-start"
-      :offset="offset"
-    ></nut-tour>
-
-    <nut-tour
-      class="nut-custom-tour"
-      v-model:visible="showTour1"
-      :steps="steps1"
-      location="bottom-end"
-      type="tile"
-      bgColor="#f00"
-      theme="dark"
       :offset="[0, 0]"
       :offset="[0, 0]"
-    ></nut-tour>
-
-    <nut-tour
-      class="nut-custom-tour"
-      v-model:visible="showTour2"
-      :steps="steps2"
-      type="tile"
-      bgColor="#f00"
-      theme="dark"
-      location="bottom-start"
+      maskWidth="50"
+      maskHeight="50"
     ></nut-tour>
     ></nut-tour>
   </div>
   </div>
 </template>
 </template>
@@ -116,6 +169,8 @@ export default createDemo({
       showTour: false,
       showTour: false,
       showTour1: false,
       showTour1: false,
       showTour2: false,
       showTour2: false,
+      showTour3: false,
+      showTour4: false,
       offset: [-3, -8],
       offset: [-3, -8],
       steps: [
       steps: [
         {
         {
@@ -148,7 +203,22 @@ export default createDemo({
       steps2: [
       steps2: [
         {
         {
           content: '这里换成关注和粉丝啦,听歌时长点击头像可见',
           content: '这里换成关注和粉丝啦,听歌时长点击头像可见',
-          target: 'target6'
+          target: 'target6',
+          popoverOffset: [40, 12],
+          arrowOffset: -36
+        }
+      ],
+
+      steps3: [
+        {
+          content: '邀请有礼,全新改版,奖励多多哦',
+          target: 'target7'
+        }
+      ],
+
+      steps4: [
+        {
+          target: 'target8'
         }
         }
       ],
       ],
 
 
@@ -157,7 +227,7 @@ export default createDemo({
 
 
     setTimeout(() => {
     setTimeout(() => {
       state.showTour = true;
       state.showTour = true;
-    }, 1000);
+    }, 100);
 
 
     const showTourHandle = () => {
     const showTourHandle = () => {
       state.showTour1 = true;
       state.showTour1 = true;
@@ -180,9 +250,12 @@ export default createDemo({
   .nut-popover-content {
   .nut-popover-content {
     width: auto !important;
     width: auto !important;
   }
   }
-  /* .nut-tour-content-inner {
+}
+
+.nut-customword-tour {
+  .nut-tour-content-inner {
     width: max-content;
     width: max-content;
-  } */
+  }
 }
 }
 
 
 .index-header {
 .index-header {
@@ -211,4 +284,28 @@ export default createDemo({
     }
     }
   }
   }
 }
 }
+
+.nut-customstyle-tour {
+  .nut-tour-mask {
+    border-radius: 50%;
+  }
+}
+
+.tour-demo-img {
+  img {
+    width: 20px;
+    height: 20px;
+    margin-right: 10px;
+  }
+}
+.tour-demo-custom-content {
+  padding: 8px;
+  display: flex;
+  width: max-content;
+  align-items: center;
+
+  .nut-divider {
+    border-color: #fff;
+  }
+}
 </style>
 </style>

+ 6 - 4
src/packages/__VUE/tour/index.scss

@@ -1,14 +1,11 @@
 .nut-tour {
 .nut-tour {
   &-mask {
   &-mask {
     position: fixed;
     position: fixed;
-
     width: 100px;
     width: 100px;
     height: 50px;
     height: 50px;
     box-shadow: 0px 0px 0px 100vh rgba(0, 0, 0, 0.5);
     box-shadow: 0px 0px 0px 100vh rgba(0, 0, 0, 0.5);
     border-radius: 10px;
     border-radius: 10px;
-
     z-index: 1002;
     z-index: 1002;
-
     &-none {
     &-none {
       box-shadow: none;
       box-shadow: none;
     }
     }
@@ -20,6 +17,11 @@
 
 
     &-top {
     &-top {
       text-align: right;
       text-align: right;
+
+      &-close {
+        width: 10px;
+        height: 10px;
+      }
     }
     }
 
 
     &-inner {
     &-inner {
@@ -35,7 +37,7 @@
       }
       }
       &-operate {
       &-operate {
         display: flex;
         display: flex;
-        justify-content: end;
+        justify-content: flex-end;
         &-btn {
         &-btn {
           display: inline-block;
           display: inline-block;
           border: 1px solid $disable-color;
           border: 1px solid $disable-color;

+ 71 - 40
src/packages/__VUE/tour/index.vue

@@ -1,7 +1,8 @@
 <template>
 <template>
   <div :class="classes">
   <div :class="classes">
-    <div class="nut-tour-masked" v-if="showTour"></div>
-    <div v-for="(step, i) in steps" :key="i">
+    <div class="nut-tour-masked" v-show="showTour" @click="handleClickMask"></div>
+
+    <div v-for="(step, i) in steps" :key="i" style="height: 0">
       <template v-if="i == active">
       <template v-if="i == active">
         <div
         <div
           class="nut-tour-mask"
           class="nut-tour-mask"
@@ -17,41 +18,45 @@
           :bgColor="bgColor"
           :bgColor="bgColor"
           :theme="theme"
           :theme="theme"
           :close-on-click-outside="false"
           :close-on-click-outside="false"
+          :offset="step.popoverOffset || [0, 12]"
+          :arrowOffset="step.arrowOffset || 0"
         >
         >
           <template #content>
           <template #content>
-            <div class="nut-tour-content" v-if="type == 'step'">
-              <div class="nut-tour-content-top">
-                <div class="nut-tour-content-top-close" @click="close">
-                  <Close size="10" name="close" />
+            <slot>
+              <div class="nut-tour-content" v-if="type == 'step'">
+                <div class="nut-tour-content-top">
+                  <div @click="close">
+                    <Close class="nut-tour-content-top-close" />
+                  </div>
                 </div>
                 </div>
-              </div>
-              <div class="nut-tour-content-inner">
-                {{ step.content }}
-              </div>
-              <div class="nut-tour-content-bottom">
-                <div class="nut-tour-content-bottom-init">{{ active + 1 }}/{{ steps.length }}</div>
-                <div class="nut-tour-content-bottom-operate">
-                  <div class="nut-tour-content-bottom-operate-btn" @click="changeStep('prev')" v-if="active != 0">{{
-                    prevStepTxt
-                  }}</div>
-                  <div
-                    class="nut-tour-content-bottom-operate-btn active"
-                    @click="close"
-                    v-if="steps.length - 1 == active"
-                    >{{ completeTxt }}</div
-                  >
-                  <div class="nut-tour-content-bottom-operate-btn active" @click="changeStep('next')" v-else>{{
-                    nextStepTxt
-                  }}</div>
+                <div class="nut-tour-content-inner">
+                  {{ step.content }}
+                </div>
+                <div class="nut-tour-content-bottom">
+                  <div class="nut-tour-content-bottom-init">{{ active + 1 }}/{{ steps.length }}</div>
+                  <div class="nut-tour-content-bottom-operate">
+                    <div class="nut-tour-content-bottom-operate-btn" @click="changeStep('prev')" v-if="active != 0">{{
+                      prevStepTxt
+                    }}</div>
+                    <div
+                      class="nut-tour-content-bottom-operate-btn active"
+                      @click="close"
+                      v-if="steps.length - 1 == active"
+                      >{{ completeTxt }}</div
+                    >
+                    <div class="nut-tour-content-bottom-operate-btn active" @click="changeStep('next')" v-else>{{
+                      nextStepTxt
+                    }}</div>
+                  </div>
                 </div>
                 </div>
               </div>
               </div>
-            </div>
 
 
-            <div class="nut-tour-content nut-tour-content-tile" v-if="type == 'tile'">
-              <div class="nut-tour-content-inner">
-                {{ step.content }}
+              <div class="nut-tour-content nut-tour-content-tile" v-if="type == 'tile'">
+                <div class="nut-tour-content-inner">
+                  {{ step.content }}
+                </div>
               </div>
               </div>
-            </div>
+            </slot>
           </template>
           </template>
         </nut-popover>
         </nut-popover>
       </template>
       </template>
@@ -68,7 +73,9 @@ import { Close } from '@nutui/icons-vue';
 interface StepOptions {
 interface StepOptions {
   target: Element;
   target: Element;
   content: String;
   content: String;
-  location: PopoverLocation;
+  location?: PopoverLocation;
+  popoverOffset?: number[];
+  arrowOffset?: number;
 }
 }
 const { create } = createComponent('tour');
 const { create } = createComponent('tour');
 export default create({
 export default create({
@@ -120,6 +127,18 @@ export default create({
     theme: {
     theme: {
       type: String,
       type: String,
       default: 'light'
       default: 'light'
+    },
+    maskWidth: {
+      type: [Number, String],
+      default: ''
+    },
+    maskHeight: {
+      type: [Number, String],
+      default: ''
+    },
+    closeOnClickOverlay: {
+      type: Boolean,
+      default: true
     }
     }
   },
   },
   emits: ['update:visible', 'change', 'close'],
   emits: ['update:visible', 'change', 'close'],
@@ -130,7 +149,9 @@ export default create({
       active: 0
       active: 0
     });
     });
 
 
-    const maskRect = ref<any>({});
+    const maskRect = ref<{
+      [props: string]: number;
+    }>({});
 
 
     const classes = computed(() => {
     const classes = computed(() => {
       const prefixCls = 'nut-tour';
       const prefixCls = 'nut-tour';
@@ -138,13 +159,18 @@ export default create({
     });
     });
 
 
     const maskStyle = computed(() => {
     const maskStyle = computed(() => {
-      const { offset } = props;
+      const { offset, maskWidth, maskHeight } = props;
       const { width, height, left, top } = maskRect.value;
       const { width, height, left, top } = maskRect.value;
+
+      const center = [left + width / 2, top + height / 2]; // 中心点 【横,纵】
+      const w: number = Number(maskWidth ? maskWidth : width);
+      const h: number = Number(maskHeight ? maskHeight : height);
+
       const styles = {
       const styles = {
-        width: `${width + offset[1] * 2}px`,
-        height: `${height + offset[0] * 2}px`,
-        top: `${top - offset[0]}px`,
-        left: `${left - offset[1]}px`
+        width: `${w + +offset[1] * 2}px`,
+        height: `${h + +offset[0] * 2}px`,
+        top: `${center[1] - h / 2 - +offset[0]}px`,
+        left: `${center[0] - w / 2 - +offset[1]}px`
       };
       };
       return styles;
       return styles;
     });
     });
@@ -174,16 +200,20 @@ export default create({
     const close = () => {
     const close = () => {
       state.showTour = false;
       state.showTour = false;
       state.showPopup = false;
       state.showPopup = false;
+      emit('close', state.active);
       emit('update:visible', false);
       emit('update:visible', false);
     };
     };
 
 
+    const handleClickMask = () => {
+      props.closeOnClickOverlay && close();
+    };
+
     watch(
     watch(
       () => props.visible,
       () => props.visible,
       (val) => {
       (val) => {
         state.showTour = val;
         state.showTour = val;
-
+        state.showPopup = val;
         if (val) {
         if (val) {
-          state.showPopup = true;
           getRootPosition();
           getRootPosition();
         }
         }
       }
       }
@@ -194,7 +224,8 @@ export default create({
       classes,
       classes,
       maskStyle,
       maskStyle,
       changeStep,
       changeStep,
-      close
+      close,
+      handleClickMask
     };
     };
   }
   }
 });
 });