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>

结果


相关推荐
Tiger_shl1 分钟前
三大并发集合ConcurrentDictionary、ConcurrentBag、ConcurrentQueue
开发语言·c#
DoraBigHead8 分钟前
React Fiber:从“递归地狱”到“时间切片”的重生之路
前端·javascript·react.js
游戏开发爱好者816 分钟前
如何系统化掌握 iOS 26 App 耗电管理,多工具协作
android·macos·ios·小程序·uni-app·cocoa·iphone
火锅机器19 分钟前
java 8 lambda表达式对list进行分组
java·开发语言·list
shaominjin12320 分钟前
android在sd卡中可以mkdir, 但是不可以createNewFile
android·开发语言·python
筱砚.25 分钟前
【STL——stack容器】
开发语言·c++
曦樂~25 分钟前
【Qt】定时器--滚动相册
开发语言·qt
lecepin1 小时前
AI Coding 资讯 2025-10-22
前端·javascript·后端
沐知全栈开发1 小时前
Java 文档注释
开发语言
程序_白白2 小时前
探讨一下java将来未来两年内的就业以及发展
java·开发语言