all
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
## 1.2.0(2025-03-11)
|
||||
1. 修复示例工程中可能存在的潜在问题(弹窗示例)
|
||||
## 1.1.9(2024-08-28)
|
||||
1. 提供了弹窗模式,详见示例二
|
||||
2. 在弹窗模式下,微信小程序请遵守示例二的关键步骤,正确对签字板进行初始化与销毁
|
||||
## 1.1.8(2024-08-21)
|
||||
1. 修复h5端横屏时可能会出现签名回显的问题
|
||||
## 1.1.7(2024-07-23)
|
||||
1. 修复签字偏移问题
|
||||
## 1.1.6(2024-06-28)
|
||||
1.新增needBack属性:点击取消时是否需要自动返回(默认true)
|
||||
2.修正原取消事件cancel单词写错成cancle的问题
|
||||
## 1.1.5(2024-06-28)
|
||||
1.优化
|
||||
## 1.1.4(2024-05-10)
|
||||
1. 删除冗余代码
|
||||
2. 文档迁移
|
||||
## 1.1.3(2024-04-29)
|
||||
1. 更新示例工程
|
||||
## 1.1.2(2024-04-29)
|
||||
1. 优化了多场景下签名的需求,详情请看示例工程
|
||||
## 1.1.1(2024-04-29)
|
||||
1. 更新
|
||||
## 1.1.0(2024-04-01)
|
||||
1. 更好的兼容支付宝小程序
|
||||
## 1.0.9(2024-03-20)
|
||||
1. 修复小程序无法横屏的问题
|
||||
## 1.0.8(2024-02-28)
|
||||
1. 修复背景颜色修改无效的问题
|
||||
## 1.0.7(2024-02-04)
|
||||
1. 修复签名板在h5端高度异常问题
|
||||
2. 更新示例工程
|
||||
3. 更新文档
|
||||
## 1.0.6(2023-10-20)
|
||||
1. 新增@firstTouchStart首次触碰绘制的方法
|
||||
2. 修复添加动态水印时,初次加载水印失效的bug
|
||||
3. 更新示例项目中水印的使用方式
|
||||
## 1.0.5(2023-10-17)
|
||||
1. 更新示例项目
|
||||
## 1.0.4(2023-10-17)
|
||||
1. 更新文档说明
|
||||
## 1.0.3(2023-10-17)
|
||||
1. 新增图片导出格式与画质配置
|
||||
2. 更新条件编译以更好适配H5、App和小程序端
|
||||
## 1.0.2(2023-10-16)
|
||||
1. 修复横屏适配问题
|
||||
2. 文档更新
|
||||
## 1.0.1(2023-10-16)
|
||||
1. 修复安卓真机canvas无法动态设置宽高的bug
|
||||
2. 修复安卓真机水印与背景底色失效的bug
|
||||
3. 新增监听path字段,现在不仅可以返回base64图片,也可返回临时的图片路径
|
||||
4. 修复vue2、vue3兼容性
|
||||
## 1.0.0(2023-10-13)
|
||||
1. 签字板可添加水印,背景图片,调整画笔样式等
|
||||
2. 适配横竖屏,生成base64格式图片
|
||||
@@ -0,0 +1,196 @@
|
||||
function getLocalFilePath(path) {
|
||||
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('file://') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/storage/emulated/0/') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/') === 0) {
|
||||
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
|
||||
if (localFilePath !== path) {
|
||||
return localFilePath
|
||||
} else {
|
||||
path = path.substr(1)
|
||||
}
|
||||
}
|
||||
return '_www/' + path
|
||||
}
|
||||
|
||||
function dataUrlToBase64(str) {
|
||||
var array = str.split(',')
|
||||
return array[array.length - 1]
|
||||
}
|
||||
|
||||
var index = 0
|
||||
function getNewFileId() {
|
||||
return Date.now() + String(index++)
|
||||
}
|
||||
|
||||
function biggerThan(v1, v2) {
|
||||
var v1Array = v1.split('.')
|
||||
var v2Array = v2.split('.')
|
||||
var update = false
|
||||
for (var index = 0; index < v2Array.length; index++) {
|
||||
var diff = v1Array[index] - v2Array[index]
|
||||
if (diff !== 0) {
|
||||
update = diff > 0
|
||||
break
|
||||
}
|
||||
}
|
||||
return update
|
||||
}
|
||||
|
||||
export function pathToBase64(path) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
if (typeof FileReader === 'function') {
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('GET', path, true)
|
||||
xhr.responseType = 'blob'
|
||||
xhr.onload = function() {
|
||||
if (this.status === 200) {
|
||||
let fileReader = new FileReader()
|
||||
fileReader.onload = function(e) {
|
||||
resolve(e.target.result)
|
||||
}
|
||||
fileReader.onerror = reject
|
||||
fileReader.readAsDataURL(this.response)
|
||||
}
|
||||
}
|
||||
xhr.onerror = reject
|
||||
xhr.send()
|
||||
return
|
||||
}
|
||||
var canvas = document.createElement('canvas')
|
||||
var c2x = canvas.getContext('2d')
|
||||
var img = new Image
|
||||
img.onload = function() {
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
c2x.drawImage(img, 0, 0)
|
||||
resolve(canvas.toDataURL())
|
||||
canvas.height = canvas.width = 0
|
||||
}
|
||||
img.onerror = reject
|
||||
img.src = path
|
||||
return
|
||||
}
|
||||
if (typeof plus === 'object') {
|
||||
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
|
||||
entry.file(function(file) {
|
||||
var fileReader = new plus.io.FileReader()
|
||||
fileReader.onload = function(data) {
|
||||
resolve(data.target.result)
|
||||
}
|
||||
fileReader.onerror = function(error) {
|
||||
reject(error)
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
wx.getFileSystemManager().readFile({
|
||||
filePath: path,
|
||||
encoding: 'base64',
|
||||
success: function(res) {
|
||||
resolve('data:image/png;base64,' + res.data)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
||||
|
||||
export function base64ToPath(base64) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
base64 = base64.split(',')
|
||||
var type = base64[0].match(/:(.*?);/)[1]
|
||||
var str = atob(base64[1])
|
||||
var n = str.length
|
||||
var array = new Uint8Array(n)
|
||||
while (n--) {
|
||||
array[n] = str.charCodeAt(n)
|
||||
}
|
||||
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
|
||||
}
|
||||
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
|
||||
if (extName) {
|
||||
extName = extName[1]
|
||||
} else {
|
||||
reject(new Error('base64 error'))
|
||||
}
|
||||
var fileName = getNewFileId() + '.' + extName
|
||||
if (typeof plus === 'object') {
|
||||
var basePath = '_doc'
|
||||
var dirPath = 'uniapp_temp'
|
||||
var filePath = basePath + '/' + dirPath + '/' + fileName
|
||||
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
|
||||
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
|
||||
entry.getDirectory(dirPath, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.getFile(fileName, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.createWriter(function(writer) {
|
||||
writer.onwrite = function() {
|
||||
resolve(filePath)
|
||||
}
|
||||
writer.onerror = reject
|
||||
writer.seek(0)
|
||||
writer.writeAsBinary(dataUrlToBase64(base64))
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
return
|
||||
}
|
||||
var bitmap = new plus.nativeObj.Bitmap(fileName)
|
||||
bitmap.loadBase64Data(base64, function() {
|
||||
bitmap.save(filePath, {}, function() {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
|
||||
wx.getFileSystemManager().writeFile({
|
||||
filePath: filePath,
|
||||
data: dataUrlToBase64(base64),
|
||||
encoding: 'base64',
|
||||
success: function() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
<template>
|
||||
<view class="sign-page">
|
||||
<view class="sign-body">
|
||||
<canvas
|
||||
id="signCanvas"
|
||||
canvas-id="signCanvas"
|
||||
class="sign-canvas"
|
||||
disable-scroll
|
||||
@touchstart="signCanvasStart"
|
||||
@touchmove="signCanvasMove"
|
||||
@touchend="signCanvasEnd"
|
||||
></canvas>
|
||||
<!-- #ifndef APP -->
|
||||
<!--用于临时储存横屏图片的canvas容器,H5和小程序需要-->
|
||||
<canvas
|
||||
v-if="horizontal"
|
||||
id="hsignCanvas"
|
||||
canvas-id="hsignCanvas"
|
||||
style="position: absolute; left: -1000px; z-index: -1"
|
||||
:style="{ width: canvasHeight + 'px', height: canvasWidth + 'px' }"
|
||||
></canvas>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view v-if="!popupMode" class="sign-footer" :class="[horizontal ? 'horizontal-btns' : 'vertical-btns']">
|
||||
<view class="btn" @click="cancel">取消</view>
|
||||
<view class="btn" @click="reset">重写</view>
|
||||
<view class="btn" @click="confirm">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { pathToBase64, base64ToPath } from './index.js'
|
||||
export default {
|
||||
name: 'sign',
|
||||
props: {
|
||||
// 签字板id,用于多签名场景下作为区分
|
||||
sid: {
|
||||
type: String,
|
||||
default: 'sign-board'
|
||||
},
|
||||
// 是否是弹窗模式
|
||||
popupMode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 背景水印图,优先级大于 bgColor
|
||||
bgImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 背景纯色底色,为空则透明
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否显示水印
|
||||
showMark: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 水印内容,可多行
|
||||
markText: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [] // ['水印1', '水印2']
|
||||
}
|
||||
},
|
||||
// 水印样式
|
||||
markStyle: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
fontSize: 12, // 水印字体大小
|
||||
fontFamily: 'microsoft yahei', // 水印字体
|
||||
color: '#cccccc', // 水印字体颜色
|
||||
rotate: 60, // 水印旋转角度
|
||||
step: 2.2 // 步长,部分场景下可通过调节该参数来调整水印间距,建议为1.4-2.6左右
|
||||
}
|
||||
}
|
||||
},
|
||||
// 是否横屏
|
||||
horizontal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 画笔样式
|
||||
penStyle: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
lineWidth: 3, // 画笔线宽 建议1~5
|
||||
color: '#000000' // 画笔颜色
|
||||
}
|
||||
}
|
||||
},
|
||||
// 导出图片配置
|
||||
expFile: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
fileType: 'png', // png/jpg (png不可压缩质量,支持透明;jpg可压缩质量,不支持透明)
|
||||
quality: 1 // 范围 0 - 1 (仅jpg支持)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 取消时是否需要返回
|
||||
needBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
canvasCtx: null, // canvascanvasWidth: 0, // canvas宽度
|
||||
canvasWidth: 0, // canvas宽度
|
||||
canvasHeight: 0, // canvas高度
|
||||
x0: 0, // 初始横坐标或上一段touchmove事件中触摸点的横坐标
|
||||
y0: 0, // 初始纵坐标或上一段touchmove事件中触摸点的纵坐标
|
||||
signFlag: false // 签名旗帜
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.createCanvas()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 创建canvas实例
|
||||
createCanvas() {
|
||||
this.canvasCtx = uni.createCanvasContext('signCanvas', this)
|
||||
this.canvasCtx.setLineCap('round') // 向线条的每个末端添加圆形线帽
|
||||
|
||||
// 获取canvas宽高
|
||||
const query = uni.createSelectorQuery().in(this)
|
||||
query
|
||||
.select('.sign-body')
|
||||
.boundingClientRect((data) => {
|
||||
this.canvasWidth = data.width
|
||||
this.canvasHeight = data.height
|
||||
})
|
||||
.exec(async () => {
|
||||
await this.drawBg()
|
||||
this.drawMark(this.markText)
|
||||
})
|
||||
},
|
||||
async drawBg() {
|
||||
if (this.bgImg) {
|
||||
const img = await uni.getImageInfo({ src: this.bgImg })
|
||||
this.canvasCtx.drawImage(img.path, 0, 0, this.canvasWidth, this.canvasHeight)
|
||||
} else if (this.bgColor) {
|
||||
// 绘制底色填充,否则为透明
|
||||
this.canvasCtx.setFillStyle(this.bgColor)
|
||||
this.canvasCtx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||
}
|
||||
},
|
||||
// 绘制动态水印
|
||||
drawMark(textArray) {
|
||||
if (!this.showMark) {
|
||||
this.canvasCtx.draw()
|
||||
return
|
||||
}
|
||||
// 绘制背景
|
||||
this.drawBg()
|
||||
|
||||
// 水印参数
|
||||
const markStyle = Object.assign(
|
||||
{
|
||||
fontSize: 12, // 水印字体大小
|
||||
fontFamily: 'microsoft yahei', // 水印字体
|
||||
color: '#cccccc', // 水印字体颜色
|
||||
rotate: 60, // 水印旋转角度
|
||||
step: 2 // 步长,部分场景下可通过调节该参数来调整水印间距,建议为1.4-2.6左右
|
||||
},
|
||||
this.markStyle
|
||||
)
|
||||
this.canvasCtx.font = `${markStyle.fontSize}px ${markStyle.fontFamily}`
|
||||
this.canvasCtx.fillStyle = markStyle.color
|
||||
// 文字坐标
|
||||
const maxPx = Math.max(this.canvasWidth / 2, this.canvasHeight / 2)
|
||||
const stepPx = Math.floor(maxPx / markStyle.step)
|
||||
let arrayX = [0] // 初始水印位置 canvas坐标 0 0 点
|
||||
while (arrayX[arrayX.length - 1] < maxPx / 2) {
|
||||
arrayX.push(arrayX[arrayX.length - 1] + stepPx)
|
||||
}
|
||||
arrayX.push(
|
||||
...arrayX.slice(1, arrayX.length).map((item) => {
|
||||
return -item
|
||||
})
|
||||
)
|
||||
|
||||
for (let i = 0; i < arrayX.length; i++) {
|
||||
for (let j = 0; j < arrayX.length; j++) {
|
||||
this.canvasCtx.save()
|
||||
this.canvasCtx.translate(this.canvasWidth / 2, this.canvasHeight / 2) // 画布旋转原点 移到 图片中心
|
||||
this.canvasCtx.rotate(Math.PI * (markStyle.rotate / 180))
|
||||
textArray.forEach((item, index) => {
|
||||
let offsetY = markStyle.fontSize * index
|
||||
this.canvasCtx.fillText(item, arrayX[i], arrayX[j] + offsetY)
|
||||
})
|
||||
this.canvasCtx.restore()
|
||||
}
|
||||
}
|
||||
|
||||
this.canvasCtx.draw()
|
||||
},
|
||||
cancel() {
|
||||
//取消按钮事件
|
||||
this.$emit('cancel')
|
||||
this.reset()
|
||||
if (this.needBack) uni.navigateBack()
|
||||
},
|
||||
async reset() {
|
||||
this.$emit('reset')
|
||||
this.signFlag = false
|
||||
this.canvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||
await this.drawBg()
|
||||
this.drawMark(this.markText)
|
||||
},
|
||||
async confirm() {
|
||||
this.$emit('confirm')
|
||||
// 确认按钮事件
|
||||
if (!this.signFlag) {
|
||||
uni.showToast({
|
||||
title: '请签名后再点击确定',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '确认',
|
||||
content: '确认签名无误吗',
|
||||
showCancel: true,
|
||||
success: async ({ confirm }) => {
|
||||
if (confirm) {
|
||||
let tempFile
|
||||
if (this.horizontal) {
|
||||
tempFile = await this.saveHorizontalCanvas()
|
||||
} else {
|
||||
tempFile = await this.saveCanvas()
|
||||
}
|
||||
const base64 = await pathToBase64(tempFile)
|
||||
const path = await base64ToPath(base64)
|
||||
uni.$emit('getSignImg', { base64, path, sid: this.sid })
|
||||
if (this.needBack) uni.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
signCanvasEnd(e) {
|
||||
// 签名抬起事件
|
||||
// console.log(e, 'signCanvasEnd')
|
||||
this.x0 = 0
|
||||
this.y0 = 0
|
||||
},
|
||||
signCanvasMove(e) {
|
||||
// 签名滑动事件
|
||||
// console.log(e, 'signCanvasMove')
|
||||
let dx = e.touches[0].x
|
||||
let dy = e.touches[0].y
|
||||
|
||||
this.canvasCtx.moveTo(this.x0, this.y0)
|
||||
this.canvasCtx.lineTo(dx, dy)
|
||||
this.canvasCtx.setLineWidth(this.penStyle?.lineWidth || 4)
|
||||
this.canvasCtx.strokeStyle = this.penStyle?.color || '#000000' // 赋值过去
|
||||
this.canvasCtx.stroke()
|
||||
this.canvasCtx.draw(true)
|
||||
|
||||
this.x0 = e.touches[0].x
|
||||
this.y0 = e.touches[0].y
|
||||
},
|
||||
signCanvasStart(e) {
|
||||
// 签名按下事件 app获取的e不一样区分小程序app
|
||||
// console.log('signCanvasStart', e)
|
||||
if (!this.signFlag) {
|
||||
// 第一次开始触碰事件
|
||||
this.$emit('firstTouchStart')
|
||||
}
|
||||
this.signFlag = true
|
||||
this.x0 = e.touches[0].x
|
||||
this.y0 = e.touches[0].y
|
||||
},
|
||||
// 保存竖屏图片
|
||||
async saveCanvas() {
|
||||
return await new Promise((resolve, reject) => {
|
||||
uni.canvasToTempFilePath(
|
||||
{
|
||||
canvasId: 'signCanvas',
|
||||
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||
quality: this.expFile.quality, // 范围 0 - 1
|
||||
success: (res) => {
|
||||
if (!res.tempFilePath) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '保存签名失败',
|
||||
showCancel: false
|
||||
})
|
||||
return
|
||||
}
|
||||
resolve(res.tempFilePath)
|
||||
},
|
||||
fail: (r) => {
|
||||
console.log('图片生成失败:' + r)
|
||||
resolve(false)
|
||||
}
|
||||
},
|
||||
this
|
||||
)
|
||||
})
|
||||
},
|
||||
// 保存横屏图片
|
||||
async saveHorizontalCanvas() {
|
||||
return await new Promise((resolve, reject) => {
|
||||
uni.canvasToTempFilePath(
|
||||
{
|
||||
canvasId: 'signCanvas',
|
||||
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||
success: (res) => {
|
||||
if (!res.tempFilePath) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '保存签名失败',
|
||||
showCancel: false
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// #ifdef APP
|
||||
uni.compressImage({
|
||||
src: res.tempFilePath,
|
||||
quality: this.expFile.quality * 100, // 范围 0 - 100
|
||||
rotate: 270,
|
||||
success: (r) => {
|
||||
console.log('==== compressImage :', r)
|
||||
resolve(r.tempFilePath)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP
|
||||
uni.getImageInfo({
|
||||
src: res.tempFilePath,
|
||||
success: (r) => {
|
||||
// console.log('==== getImageInfo :', r)
|
||||
// 将signCanvas的内容复制到hsignCanvas中
|
||||
const hcanvasCtx = uni.createCanvasContext('hsignCanvas', this)
|
||||
// 横屏宽高互换
|
||||
hcanvasCtx.translate(this.canvasHeight / 2, this.canvasWidth / 2)
|
||||
hcanvasCtx.rotate(Math.PI * (-90 / 180))
|
||||
hcanvasCtx.drawImage(
|
||||
r.path,
|
||||
-this.canvasWidth / 2,
|
||||
-this.canvasHeight / 2,
|
||||
this.canvasWidth,
|
||||
this.canvasHeight
|
||||
)
|
||||
hcanvasCtx.draw(false, async () => {
|
||||
const hpathRes = await uni.canvasToTempFilePath(
|
||||
{
|
||||
canvasId: 'hsignCanvas',
|
||||
fileType: this.expFile.fileType, // 只支持png和jpg
|
||||
quality: this.expFile.quality // 范围 0 - 1
|
||||
},
|
||||
this
|
||||
)
|
||||
let tempFile = ''
|
||||
if (Array.isArray(hpathRes)) {
|
||||
hpathRes.some((item) => {
|
||||
if (item) {
|
||||
tempFile = item.tempFilePath
|
||||
return
|
||||
}
|
||||
})
|
||||
} else {
|
||||
tempFile = hpathRes.tempFilePath
|
||||
}
|
||||
resolve(tempFile)
|
||||
})
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('图片生成失败:' + err)
|
||||
resolve(false)
|
||||
}
|
||||
},
|
||||
this
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sign-page {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.sign-body {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
|
||||
.sign-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.sign-footer {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
border-top: 1px solid #cccccc;
|
||||
box-sizing: border-box;
|
||||
|
||||
.btn {
|
||||
line-height: 66rpx;
|
||||
text-align: center;
|
||||
border-radius: 12rpx;
|
||||
|
||||
&:nth-child(1) {
|
||||
background-color: #ff0800;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
background-color: #00d000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
background-color: #0184ff;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vertical-btns {
|
||||
.btn {
|
||||
width: 120rpx;
|
||||
height: 66rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.horizontal-btns {
|
||||
.btn {
|
||||
width: 66rpx;
|
||||
height: 120rpx;
|
||||
writing-mode: vertical-lr;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"id": "sp-sign-board",
|
||||
"displayName": "签字板 签名版 手写 动态水印 可叠加背景 可导出图片",
|
||||
"version": "1.2.0",
|
||||
"description": "签字板,可添加背景图或动态水印,可适配横竖屏,并将签名生成base64格式图片",
|
||||
"keywords": [
|
||||
"签字",
|
||||
"签名",
|
||||
"水印",
|
||||
"base64"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.5.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# sp-sign-board
|
||||
|
||||
### 文档迁移
|
||||
|
||||
> 防止文档失效,提供下列五个地址,内容一致
|
||||
|
||||
- [地址一](https://sonvee.github.io/sv-app-docs/docs-github/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||
- [地址二](https://sv-app-docs.pages.dev/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||
- [地址三](https://sv-app-docs.4everland.app/src/plugins/sp-sign-board/sp-sign-board.html)
|
||||
- [地址四](https://sv-app-docs.vercel.app/src/plugins/sp-sign-board/sp-sign-board.html) (需要梯子)
|
||||
- [地址五](https://static-mp-74bfcbac-6ba6-4f39-8513-8831390ff75a.next.bspapp.com/docs-uni/src/plugins/sp-sign-board/sp-sign-board.html) (有IP限制)
|
||||
Reference in New Issue
Block a user