ソースを参照

feat: signature taro 签名组件适配 (#643)

郭晓 4 年 前
コミット
3736f19790

+ 1 - 1
src/config.json

@@ -805,7 +805,7 @@
         },
         {
           "version": "3.0.0",
-          "taro": false,
+          "taro": true,
           "tarodoc": true,
           "name": "Signature",
           "type": "component",

+ 68 - 76
src/packages/__VUE/signature/doc.taro.md

@@ -1,87 +1,79 @@
-# signature 签名
+#  signature组件
 
 ### 介绍
+    
+    基于Canvas的签名组件。
+    
+### 安装
 
-由于 taro 对原生 canvas 的转换未完成。暂时不支持该组件转小程序的应用
-
-<!-- ### 安装
-
-```javascript
+``` javascript
 import { createApp } from 'vue';
-import { Swiper } from '@nutui/nutui-taro';
+// vue
+import { Signature} from '@nutui/nutui';
 
 const app = createApp();
-app.use(Swiper);
-```
-
-## 代码演示
+app.use(Signature);
 
-### 基础用法
-
-`autoplay` 是否自动切换
-`interval` 自动切换时间间隔
-`current` 当前所在滑块的 index
-`indicator-dots` 是否显示面板指示点
-`indicator-color` 指示点颜色
-
-```html
-<nut-swiper current="1" indicator-dots="true" indicator-color="#426543" autoplay="true" interval="3000">
-   <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg'" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
-  </nut-swiper-item>
-</nut-swiper>
 ```
-
-### 自定义大小
-
-`previous-margin` 前边距,可用于露出前一项的一小部分,接受 px 和 rpx 值
-`next-margin` 后边距,可用于露出后一项的一小部分,接受 px 和 rpx 值
+    
+    
+## 代码演示
+ 
+### 修改颜色和签字粗细
 
 ```html
-<nut-swiper previous-margin="10px" next-margin="10px">
-   <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg'" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
-  </nut-swiper-item>
-</nut-swiper>
+<div class="demo">
+    <nut-signature
+      :lineWidth="lineWidth"
+      :strokeStyle="strokeStyle"
+      @confirm="confirm"
+      @clear="clear"
+    />
+  </div>
+setup() {
+    const state = reactive({
+      lineWidth: 4,
+      strokeStyle: 'green',
+      testimg: ''
+    });
+    const clear = () => {
+      console.log('清除事件');
+    };
+    const confirm = (data: any) => {
+      console.log('图片地址', data);
+      Taro.saveImageToPhotosAlbum({
+        filePath: `${data}`,
+        success(res) {
+          Taro.showToast({
+            title: '保存成功'
+          });
+        },
+        fail(err) {
+          Taro.showToast({
+            title: '保存失败'
+          });
+        }
+      });
+    };
+    return { ...state, confirm, clear };
+  }
 ```
-
-### 垂直方向
-
-`vertical` 滑动方向是否为纵向
-
-
-```html
-<nut-swiper vertical="true">
-    <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg'" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
-  </nut-swiper-item>
-  <nut-swiper-item>
-    <img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
-  </nut-swiper-item>
-</nut-swiper>
-``` -->
-
+    
+## API
+    
+### Props
+    
+| 参数 | 说明 | 类型 | 默认值
+|----- | ----- | ----- | ----- 
+| custom-class | 自定义class | String | -
+| line-width | 线条的宽度 | Number | 3
+| stroke-style | 绘图笔触颜色 | String | '#000'
+| type | 图片格式 | String | 'png'
+| un-support-tpl | 不支持Canvas情况下的展示文案 | String | '对不起,当前浏览器不支持Canvas,无法使用本控件!'
+
+## Event
+
+| 字段 | 说明 | 回调参数 
+|----- | ----- | ----- 
+| confirm | 点击确认按钮触发事件回调函数 | data URI
+| clear | 点击重签按钮触发事件回调函数 | 无

+ 158 - 0
src/packages/__VUE/signature/index.taro.vue

@@ -0,0 +1,158 @@
+<template>
+  <div :class="classes">
+    <div class="nut-signature-inner">
+      <canvas
+        class="spcanvas"
+        id="spcanvas"
+        canvasId="spcanvas"
+        canvas-id="spcanvas"
+        type="2d"
+        disable-scroll="true"
+        @touchstart="startEventHandler"
+        @touchmove="moveEventHandler"
+        @touchend="endEventHandler"
+        @touchleave="leaveEventHandler"
+      />
+    </div>
+    <nut-button class="nut-signature-btn" type="default" @click="clear()"
+      >重签</nut-button
+    >
+    <nut-button class="nut-signature-btn" type="primary" @click="confirm()"
+      >确认</nut-button
+    >
+  </div>
+</template>
+<script lang="ts">
+import Taro from '@tarojs/taro';
+import { ref, reactive, onMounted, computed } from 'vue';
+import { createComponent } from '../../utils/create';
+const { componentName, create } = createComponent('signature');
+
+export default create({
+  props: {
+    customClass: {
+      type: String,
+      default: ''
+    },
+    lineWidth: {
+      type: Number,
+      default: 2
+    },
+    strokeStyle: {
+      type: String,
+      default: '#000'
+    },
+    type: {
+      type: String,
+      default: 'png'
+    },
+    unSupportTpl: {
+      type: String,
+      default: '对不起,当前浏览器不支持Canvas,无法使用本控件!'
+    }
+  },
+  components: {},
+  emits: ['confirm', 'clear'],
+
+  setup(props, { emit }) {
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        [`${props.customClass}`]: props.customClass
+      };
+    });
+    const state = reactive({
+      canvas: null,
+      canvasHeight: 0,
+      canvasWidth: 0,
+      ctx: null
+    });
+
+    const startEventHandler = (event: MouseEvent) => {
+      event.preventDefault();
+      state.ctx.beginPath();
+      state.ctx.lineWidth = props.lineWidth;
+      state.ctx.strokeStyle = props.strokeStyle;
+    };
+
+    const moveEventHandler = (event) => {
+      event.preventDefault();
+
+      let evt = event.changedTouches[0];
+      let mouseX = evt.x;
+      let mouseY = evt.y;
+      state.ctx.lineTo(mouseX, mouseY);
+      state.ctx.stroke();
+    };
+
+    const endEventHandler = (event) => {
+      event.preventDefault();
+    };
+    const leaveEventHandler = (event) => {
+      event.preventDefault();
+    };
+    const clear = () => {
+      state.ctx.clearRect(0, 0, state.canvasWidth, state.canvasHeight);
+      state.ctx.closePath();
+
+      emit('clear');
+    };
+
+    const confirm = () => {
+      onSave();
+    };
+
+    const onSave = () => {
+      if (!state.canvas) {
+        return;
+      }
+      Taro.canvasToTempFilePath({
+        canvas: state.canvas,
+        fileType: props.type
+      })
+        .then((res) => {
+          emit('confirm', res.tempFilePath);
+        })
+        .catch((e) => {
+          emit('confirm', e);
+        });
+    };
+
+    onMounted(() => {
+      setTimeout(() => {
+        Taro.createSelectorQuery()
+          .select('#spcanvas')
+          .fields(
+            {
+              node: true,
+              size: true
+            },
+            function (res) {
+              const canvas = res.node;
+              const ctx = canvas.getContext('2d');
+              state.canvas = canvas;
+              state.ctx = ctx;
+              state.canvasWidth = res.width;
+              state.canvasHeight = res.height;
+            }
+          )
+          .exec();
+      }, 500);
+    });
+    return {
+      confirm,
+      clear,
+      classes,
+      startEventHandler,
+      moveEventHandler,
+      endEventHandler,
+      leaveEventHandler
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 5 - 1
src/sites/mobile-taro/vue/src/app.config.ts

@@ -69,7 +69,11 @@ export default {
     },
     {
       root: 'business',
-      pages: ['pages/address/index', 'pages/barrage/index']
+      pages: [
+        'pages/address/index',
+        'pages/signature/index',
+        'pages/barrage/index'
+      ]
     }
   ],
   window: {

+ 3 - 0
src/sites/mobile-taro/vue/src/business/pages/signature/index.config.js

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Signature'
+};

+ 61 - 0
src/sites/mobile-taro/vue/src/business/pages/signature/index.vue

@@ -0,0 +1,61 @@
+<template>
+  <div class="demo">
+    <h2>基础用法</h2>
+    <nut-signature
+      :lineWidth="lineWidth"
+      :strokeStyle="strokeStyle"
+      @confirm="confirm"
+      @clear="clear"
+    />
+  </div>
+</template>
+
+<script lang="ts">
+import Taro from '@tarojs/taro';
+import { reactive } from 'vue';
+export default {
+  props: {},
+  setup() {
+    const state = reactive({
+      lineWidth: 4,
+      strokeStyle: 'green',
+      testimg: ''
+    });
+    const clear = () => {
+      console.log('清除事件');
+    };
+    const confirm = (data: any) => {
+      console.log('图片地址', data);
+      Taro.saveImageToPhotosAlbum({
+        filePath: `${data}`,
+        success(res) {
+          Taro.showToast({
+            title: '保存成功'
+          });
+        },
+        fail(err) {
+          Taro.showToast({
+            title: '保存失败'
+          });
+        }
+      });
+    };
+    return { ...state, confirm, clear };
+  }
+};
+</script>
+
+<style lang="scss">
+.nut-cell,
+.nut-barrage {
+  padding: 20px 0;
+  height: 120px;
+}
+.test {
+  display: flex;
+  justify-content: space-between;
+  .nut-input {
+    width: 80%;
+  }
+}
+</style>