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>

结果


相关推荐
福尔摩斯张9 小时前
TCP/IP网络编程深度解析:从Socket基础到高性能服务器构建(超详细)
linux·运维·服务器·开发语言·网络·网络协议·tcp/ip
superman超哥9 小时前
仓颉语言中网络套接字封装的深度剖析与工程实践
c语言·开发语言·c++·python·仓颉
wanghowie9 小时前
01.01 Java基础篇|语言基础与开发环境速成
java·开发语言
风止何安啊9 小时前
🚀别再卷 Redux 了!Zustand 才是 React 状态管理的躺平神器
前端·react.js·面试
白露与泡影9 小时前
2026年Java面试题目收集整理归纳(持续更新)
java·开发语言·面试
鹿角片ljp9 小时前
Spring Boot Web入门:从零开始构建web程序
前端·spring boot·后端
向下的大树9 小时前
Vue 2迁移Vue 3实战:从痛点到突破
前端·javascript·vue.js
我很苦涩的9 小时前
原生小程序使用echarts
前端·小程序·echarts
玉米Yvmi9 小时前
从零理解 CSS 弹性布局:轻松掌控页面元素排布
前端·javascript·css
西洼工作室9 小时前
前端js汉字手写练习系统
前端·javascript·css