|
@@ -28,7 +28,7 @@
|
|
|
<image
|
|
<image
|
|
|
v-if="currentDataUrl && !hasContent"
|
|
v-if="currentDataUrl && !hasContent"
|
|
|
:src="currentDataUrl"
|
|
:src="currentDataUrl"
|
|
|
- mode="aspectFit"
|
|
|
|
|
|
|
+ mode="widthFix"
|
|
|
class="signature-preview"
|
|
class="signature-preview"
|
|
|
/>
|
|
/>
|
|
|
</view>
|
|
</view>
|
|
@@ -296,9 +296,48 @@ export default {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
this.savingLive = true
|
|
this.savingLive = true
|
|
|
|
|
+ var canvas = this._canvasNode
|
|
|
|
|
+ var dpr = this.dpr || 1
|
|
|
|
|
+ // 计算笔迹包围盒并裁剪留白,使签名占满导出图(横屏画布宽而矮,直接导出会让签名
|
|
|
|
|
+ // 淹没在上下留白中、回显时仅占图片一小条)。失败时回退为整画布导出,保证可用性。
|
|
|
|
|
+ var crop = null
|
|
|
|
|
+ try {
|
|
|
|
|
+ var ictx = this.ctx
|
|
|
|
|
+ var cw = canvas.width
|
|
|
|
|
+ var ch = canvas.height
|
|
|
|
|
+ if (ictx && cw > 0 && ch > 0) {
|
|
|
|
|
+ var img = ictx.getImageData(0, 0, cw, ch)
|
|
|
|
|
+ var px = img.data
|
|
|
|
|
+ var minX = cw, minY = ch, maxX = -1, maxY = -1
|
|
|
|
|
+ var found = false
|
|
|
|
|
+ for (var y = 0; y < ch; y++) {
|
|
|
|
|
+ var row = y * cw
|
|
|
|
|
+ for (var x = 0; x < cw; x++) {
|
|
|
|
|
+ if (px[(row + x) * 4 + 3] > 16) {
|
|
|
|
|
+ found = true
|
|
|
|
|
+ if (x < minX) minX = x
|
|
|
|
|
+ if (x > maxX) maxX = x
|
|
|
|
|
+ if (y < minY) minY = y
|
|
|
|
|
+ if (y > maxY) maxY = y
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (found) {
|
|
|
|
|
+ // 设备像素 → CSS 像素(canvasToTempFilePath 的 x/y/width/height 与绘制坐标一致,均为 CSS px)
|
|
|
|
|
+ var pad = Math.max(2, Math.round(2 * dpr))
|
|
|
|
|
+ var bx = Math.max(0, minX - pad)
|
|
|
|
|
+ var by = Math.max(0, minY - pad)
|
|
|
|
|
+ var bw = Math.min(cw, maxX + pad) - bx
|
|
|
|
|
+ var bh = Math.min(ch, maxY + pad) - by
|
|
|
|
|
+ crop = { x: bx / dpr, y: by / dpr, width: bw / dpr, height: bh / dpr }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ crop = null
|
|
|
|
|
+ }
|
|
|
// 2d 接口传 canvas 节点(不再传 canvasId);第二参数 this 为组件实例
|
|
// 2d 接口传 canvas 节点(不再传 canvasId);第二参数 this 为组件实例
|
|
|
- uni.canvasToTempFilePath({
|
|
|
|
|
- canvas: this._canvasNode,
|
|
|
|
|
|
|
+ var exportOpts = {
|
|
|
|
|
+ canvas: canvas,
|
|
|
x: 0,
|
|
x: 0,
|
|
|
y: 0,
|
|
y: 0,
|
|
|
width: this.canvasWidth,
|
|
width: this.canvasWidth,
|
|
@@ -342,7 +381,16 @@ export default {
|
|
|
uni.showToast({ title: '签名导出失败,请重试', icon: 'none' })
|
|
uni.showToast({ title: '签名导出失败,请重试', icon: 'none' })
|
|
|
self.savingLive = false
|
|
self.savingLive = false
|
|
|
}
|
|
}
|
|
|
- }, this)
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if (crop) {
|
|
|
|
|
+ exportOpts.x = crop.x
|
|
|
|
|
+ exportOpts.y = crop.y
|
|
|
|
|
+ exportOpts.width = crop.width
|
|
|
|
|
+ exportOpts.height = crop.height
|
|
|
|
|
+ exportOpts.destWidth = crop.width
|
|
|
|
|
+ exportOpts.destHeight = crop.height
|
|
|
|
|
+ }
|
|
|
|
|
+ uni.canvasToTempFilePath(exportOpts, this)
|
|
|
},
|
|
},
|
|
|
// 统一回写签名并通知父组件(小程序已转 base64,H5 直接透传 data URL)
|
|
// 统一回写签名并通知父组件(小程序已转 base64,H5 直接透传 data URL)
|
|
|
_emitSignature: function(dataUrl) {
|
|
_emitSignature: function(dataUrl) {
|