Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/component/signature.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ onMounted(() => {
| confirm-text | 确认按钮的文本 | string | - | - |
| file-type | 导出图片类型 | string | png | - |
| quality | 导出图片质量(0-1) | number | 1 | - |
| angle | 导出图片旋转角度 | number | 0 | - |
| export-scale | 导出图片的缩放比例 | number | 1 | - |
| disabled | 是否禁用签名板 | boolean | false | - |
| background-color | 画板的背景色 | string | - | - |
Expand Down
11 changes: 7 additions & 4 deletions src/uni_modules/wot-design-uni/components/wd-checkbox/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
}

@include b(checkbox) {
display: block;
display: flex;
margin-bottom: $-checkbox-margin;
font-size: 0;
-webkit-tap-highlight-color: transparent;
Expand All @@ -86,11 +86,14 @@
display: inline-block;
width: $-checkbox-size;
height: $-checkbox-size;
min-width: $-checkbox-size;
min-height: $-checkbox-size;
flex-shrink: 0;
border: 2px solid $-checkbox-border-color;
border-radius: 50%;
color: $-checkbox-check-color;
background: $-checkbox-bg;
vertical-align: middle;
vertical-align: top;
transition: background 0.2s;
box-sizing: border-box;

Expand All @@ -116,9 +119,9 @@

@include e(txt) {
display: inline-block;
vertical-align: middle;
vertical-align: top;
line-height: 20px;
@include lineEllipsis;
@include multiEllipsis(2);
}

@include e(label) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ export const signatureProps = {
type: Number,
default: 1
},
/**
* 在横屏的模式下保存图片的方向
* ps:签名横向的时候
*/
angle: {
type: Number,
default: 0
},
/**
* 是否禁用签名板
* 类型:boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const emit = defineEmits(['start', 'end', 'signing', 'confirm', 'clear'])
const { translate } = useTranslate('signature')
const { proxy } = getCurrentInstance() as any
const canvasId = ref<string>(`signature${uuid()}`) // canvas 组件的唯一标识符
let canvas: null = null //canvas对象 微信小程序生成图片必须传入
let canvas: any = null //canvas对象 微信小程序生成图片必须传入
const drawing = ref<boolean>(false) // 是否正在绘制
const pixelRatio = ref<number>(1) // 像素比

Expand Down Expand Up @@ -567,23 +567,66 @@ function setLine() {
* canvas 绘制图片输出成文件类型
*/
function canvasToImage() {
const { fileType, quality, exportScale } = props
const { fileType, quality, exportScale, angle } = props
const { canvasWidth, canvasHeight } = canvasState
// 修复:所有平台都要定义exportCanvas、exportWidth、exportHeight
let exportCanvas = canvas
let exportWidth = canvasWidth
let exportHeight = canvasHeight
// #ifdef MP-WEIXIN
console.log(angle, 'angle')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

移除调试用的 console.log 语句。

生产代码中不应保留调试日志,建议删除此行。

-  console.log(angle, 'angle')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(angle, 'angle')
🤖 Prompt for AI Agents
In src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue at
line 577, remove the debugging console.log(angle, 'angle') statement; simply
delete that line (or replace it with a proper logger call if persistent
instrumentation is required) so no console debugging remains in production code.

if (angle && angle % 360 !== 0 && canvas) {
try {
let rad = (angle * Math.PI) / 180
let newWidth = canvasWidth
let newHeight = canvasHeight
if (angle % 180 !== 0) {
newWidth = canvasHeight
newHeight = canvasWidth
}
// 创建离屏canvas
const offScreenCanvas = wx.createOffscreenCanvas({
type: '2d',
width: newWidth,
height: newHeight
})
const offContext = offScreenCanvas.getContext('2d')
offContext.save()
// 旋转中心平移
if (angle === 90 || angle === -270) {
offContext.translate(newWidth, 0)
} else if (angle === 180 || angle === -180) {
offContext.translate(newWidth, newHeight)
} else if (angle === 270 || angle === -90) {
offContext.translate(0, newHeight)
}
offContext.rotate(rad)
// 绘制原始内容
offContext.drawImage(canvas, 0, 0)
offContext.restore()
exportCanvas = offScreenCanvas
exportWidth = newWidth
exportHeight = newHeight
} catch (error) {
console.error('旋转画布时出错:', error)
}
Comment on lines +578 to +612
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

旋转逻辑仅支持 90 度倍数的角度,但条件检查允许任意角度。

当前实现中,translate() 的调用仅处理了 90°、180°、270° 及其负值。如果传入其他角度值(如 45°、135°),虽然条件 angle % 360 !== 0 会通过,但平移逻辑缺失,导致图像位置错误。

建议方案之一:添加角度有效性校验,仅接受 90 度倍数的旋转角度。

- if (angle && angle % 360 !== 0 && canvas) {
+ if (angle && angle % 90 === 0 && angle % 360 !== 0 && canvas) {

或者添加对非标准角度的警告提示:

  if (angle && angle % 360 !== 0 && canvas) {
+   if (angle % 90 !== 0) {
+     console.warn('wd-signature: angle 仅支持 90 的倍数')
+   }
    try {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (angle && angle % 360 !== 0 && canvas) {
try {
let rad = (angle * Math.PI) / 180
let newWidth = canvasWidth
let newHeight = canvasHeight
if (angle % 180 !== 0) {
newWidth = canvasHeight
newHeight = canvasWidth
}
// 创建离屏canvas
const offScreenCanvas = wx.createOffscreenCanvas({
type: '2d',
width: newWidth,
height: newHeight
})
const offContext = offScreenCanvas.getContext('2d')
offContext.save()
// 旋转中心平移
if (angle === 90 || angle === -270) {
offContext.translate(newWidth, 0)
} else if (angle === 180 || angle === -180) {
offContext.translate(newWidth, newHeight)
} else if (angle === 270 || angle === -90) {
offContext.translate(0, newHeight)
}
offContext.rotate(rad)
// 绘制原始内容
offContext.drawImage(canvas, 0, 0)
offContext.restore()
exportCanvas = offScreenCanvas
exportWidth = newWidth
exportHeight = newHeight
} catch (error) {
console.error('旋转画布时出错:', error)
}
if (angle && angle % 90 === 0 && angle % 360 !== 0 && canvas) {
try {
let rad = (angle * Math.PI) / 180
let newWidth = canvasWidth
let newHeight = canvasHeight
if (angle % 180 !== 0) {
newWidth = canvasHeight
newHeight = canvasWidth
}
// 创建离屏canvas
const offScreenCanvas = wx.createOffscreenCanvas({
type: '2d',
width: newWidth,
height: newHeight
})
const offContext = offScreenCanvas.getContext('2d')
offContext.save()
// 旋转中心平移
if (angle === 90 || angle === -270) {
offContext.translate(newWidth, 0)
} else if (angle === 180 || angle === -180) {
offContext.translate(newWidth, newHeight)
} else if (angle === 270 || angle === -90) {
offContext.translate(0, newHeight)
}
offContext.rotate(rad)
// 绘制原始内容
offContext.drawImage(canvas, 0, 0)
offContext.restore()
exportCanvas = offScreenCanvas
exportWidth = newWidth
exportHeight = newHeight
} catch (error) {
console.error('旋转画布时出错:', error)
}
Suggested change
if (angle && angle % 360 !== 0 && canvas) {
try {
let rad = (angle * Math.PI) / 180
let newWidth = canvasWidth
let newHeight = canvasHeight
if (angle % 180 !== 0) {
newWidth = canvasHeight
newHeight = canvasWidth
}
// 创建离屏canvas
const offScreenCanvas = wx.createOffscreenCanvas({
type: '2d',
width: newWidth,
height: newHeight
})
const offContext = offScreenCanvas.getContext('2d')
offContext.save()
// 旋转中心平移
if (angle === 90 || angle === -270) {
offContext.translate(newWidth, 0)
} else if (angle === 180 || angle === -180) {
offContext.translate(newWidth, newHeight)
} else if (angle === 270 || angle === -90) {
offContext.translate(0, newHeight)
}
offContext.rotate(rad)
// 绘制原始内容
offContext.drawImage(canvas, 0, 0)
offContext.restore()
exportCanvas = offScreenCanvas
exportWidth = newWidth
exportHeight = newHeight
} catch (error) {
console.error('旋转画布时出错:', error)
}
if (angle && angle % 360 !== 0 && canvas) {
if (angle % 90 !== 0) {
console.warn('wd-signature: angle 仅支持 90 的倍数')
}
try {
let rad = (angle * Math.PI) / 180
let newWidth = canvasWidth
let newHeight = canvasHeight
if (angle % 180 !== 0) {
newWidth = canvasHeight
newHeight = canvasWidth
}
// 创建离屏canvas
const offScreenCanvas = wx.createOffscreenCanvas({
type: '2d',
width: newWidth,
height: newHeight
})
const offContext = offScreenCanvas.getContext('2d')
offContext.save()
// 旋转中心平移
if (angle === 90 || angle === -270) {
offContext.translate(newWidth, 0)
} else if (angle === 180 || angle === -180) {
offContext.translate(newWidth, newHeight)
} else if (angle === 270 || angle === -90) {
offContext.translate(0, newHeight)
}
offContext.rotate(rad)
// 绘制原始内容
offContext.drawImage(canvas, 0, 0)
offContext.restore()
exportCanvas = offScreenCanvas
exportWidth = newWidth
exportHeight = newHeight
} catch (error) {
console.error('旋转画布时出错:', error)
}
🤖 Prompt for AI Agents
In src/uni_modules/wot-design-uni/components/wd-signature/wd-signature.vue
around lines 578-612, the rotation branch allows arbitrary angles but only
handles 90° multiples in translate(), causing mis-positioned output for angles
like 45°; either (A) validate the incoming angle and only allow multiples of 90°
(angle % 90 === 0) and log/warn/skip rotation for other values, or (B) implement
a correct general-angle rotation: compute radians, calculate the rotated canvas
bounding box (newWidth/newHeight = absolute combinations of width/height with
cos/sin), translate the offscreen context to the rotation center
(translate(newWidth/2, newHeight/2)), rotate by rad, draw the source image
centered with drawImage(canvas, -canvasWidth/2, -canvasHeight/2), then restore;
choose A for simplicity or B to support arbitrary angles and ensure
newWidth/newHeight and translations are computed accordingly.

}
// #endif
uni.canvasToTempFilePath(
{
width: canvasWidth,
height: canvasHeight,
destWidth: canvasWidth * exportScale,
destHeight: canvasHeight * exportScale,
width: exportWidth,
height: exportHeight,
destWidth: exportWidth * exportScale,
destHeight: exportHeight * exportScale,
fileType,
quality,
canvasId: canvasId.value,
canvas: canvas,
canvas: exportCanvas,
success: (res) => {
const result: SignatureResult = {
tempFilePath: res.tempFilePath,
width: (canvasWidth * exportScale) / pixelRatio.value,
height: (canvasHeight * exportScale) / pixelRatio.value,
width: (exportWidth * exportScale) / pixelRatio.value,
height: (exportHeight * exportScale) / pixelRatio.value,
success: true
}
// #ifdef MP-DINGTALK
Expand All @@ -594,8 +637,8 @@ function canvasToImage() {
fail: () => {
const result: SignatureResult = {
tempFilePath: '',
width: (canvasWidth * exportScale) / pixelRatio.value,
height: (canvasHeight * exportScale) / pixelRatio.value,
width: (exportWidth * exportScale) / pixelRatio.value,
height: (exportHeight * exportScale) / pixelRatio.value,
success: false
}
emit('confirm', result)
Expand Down
Loading