uni-app 开发 App 、 H5 横屏签名(基于lime-signature)

所用插件:lime-signature

使用到 CSS 特性

  1. 绝对定位
  2. transform 旋转
  3. transform-origin transform 原点

复习一下定位元素(相对定位、绝对定位、粘性定位)

代码#

html 复制代码
<template>
  <view class="signature-page">
    <view class="operate-box">
      <button @click="handleSignatureClick('back')">
        {{ $t("common.back") }}
      </button>
      <button @click="handleSignatureClick('clear')">
        {{ $t("maintenance.signatureBtns[0]") }}
      </button>
      <button @click="handleSignatureClick('undo')">
        {{ $t("maintenance.signatureBtns[1]") }}
      </button>
      <button @click="handleSignatureClick('save')">
        {{ $t("maintenance.signatureBtns[2]") }}
      </button>
    </view>
    <view class="canvas-box">
      <l-signature
        disableScroll
        backgroundColor="#fff"
        ref="signatureRef"
        :penColor="penColor"
        :penSize="penSize"
        :openSmooth="openSmooth"
        :landscape="IsLandscape"
      ></l-signature>
    </view>
  </view>
</template>

<script>
/**
 * 签名-横屏
 * @author demon3443002624@outlook.com
 * @version 1.0.0
 */
import { dataURLtoFile, changeUrl } from "@/common/utils.js";
const UPLOAD_FILE_URL_MAINTENANCE5 =
  changeUrl("/Lease/UploadLeaseMaintenanceNewV2File") + "?type=5";
export default {
  data() {
    return {
      type: null,
      penColor: "#000",
      penSize: 5,
      openSmooth: true,
      IsLandscape: false,
    };
  },
  onLoad(params) {
    const _this = this;
    const eventChannel = this.getOpenerEventChannel();
    // 监听acceptData事件,获取上一页通过eventChannel传送到当前页面的数据
    eventChannel.on("acceptData", function (data) {
      _this.type = data.type;
    });
    // 横屏签名
    this.IsLandscape = true;

    // #ifdef APP-PLUS
    // this.IsLandscape = true
    // plus.screen.lockOrientation('landscape-primary') // App 屏幕旋转
    // #endif
  },
  onUnload() {
    // #ifdef APP-PLUS
    // plus.screen.lockOrientation('portrait-primary') // App 屏幕旋转
    // #endif
  },
  methods: {
    handleSignatureClick(type) {
      if (type == "back") {
        uni.navigateBack();
        return;
      }
      if (type == "openSmooth") {
        this.openSmooth = !this.openSmooth;
        return;
      }
      const signatureRefStr = "signatureRef";
      if (type == "save") {
        this.$refs[signatureRefStr].canvasToTempFilePath({
          success: (res) => {
            // App 生成的图片路径, H5 生成的base64 处理方式不同
            const commonHandler = (resultInner) => {
              if (resultInner.statusCode === 200) {
                const responseDataJson = resultInner.data;
                if (responseDataJson) {
                  const responseData = JSON.parse(responseDataJson);
                  const eventChannel = this.getOpenerEventChannel();
                  // 向上一页通过事件传递数据
                  eventChannel.emit("editData", {
                    type: this.type,
                    url: responseData.Data,
                  });
                  uni.navigateBack();
                }
              }
            };

            // #ifdef H5
            uni.uploadFile({
              url: UPLOAD_FILE_URL_MAINTENANCE5,
              file: dataURLtoFile(res.tempFilePath, "file.png"), // ** 没有文件名,后台出错
              name: "file",
              success: (result) => {
                commonHandler(result);
              },
              fail: (err) => {},
            });
            // #endif
            // #ifdef APP
            uni.uploadFile({
              url: UPLOAD_FILE_URL_MAINTENANCE5,
              filePath: res.tempFilePath,
              name: "file",
              success: (result) => {
                commonHandler(result);
              },
              fail: (err) => {},
            });
            // #endif
          },
        });
        return;
      }
      if (this.$refs[signatureRefStr]) this.$refs[signatureRefStr][type]();
    },
  },
};
</script>

<style lang="scss">
$operate-btn-width: 100rpx;
.signature-page {
  margin-top: var(--status-bar-height);
  height: calc(
    100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom)
  );
  width: 100%;
  position: relative;
  .canvas-box {
    height: 100%;
    margin-left: $operate-btn-width;
  }

  .operate-box {
    position: absolute;
    display: flex;
    transform: rotate(90deg);
    transform-origin: top left;
    height: $operate-btn-width;
    width: calc(
      100vh - var(--window-top) - var(--status-bar-height) -
        var(--window-bottom)
    );
    top: 0;
    left: $operate-btn-width;
    z-index: 1;
    uni-button {
      flex: 1;
      margin: 5rpx 10rpx;
    }
  }
}
</style>

结果


相关推荐
白帽攻防录1 小时前
SRC 挖洞:PostScript 打印机驱动双 RCE,打印服务器怎么变成内网跳板
开发语言·网络安全·php·内网安全
十年Java程序媛2 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
2603_965148112 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
lpfasd1232 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
xixiaoyunya3 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
学逆向的3 小时前
C 循环结构的执行效率分析
c语言·开发语言·数据结构·网络安全
小坏讲微服务3 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
Data analyse4565 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai5 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
打工仔折腾 AI5 小时前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战