mirror of
https://github.com/youzan/vant.git
synced 2026-04-25 01:06:31 +08:00
feat(Signature): add undo functionality (#13775)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'الهاتف',
|
||||
save: 'حفظ',
|
||||
clear: 'مسح',
|
||||
undo: 'تراجع',
|
||||
cancel: 'إلغاء',
|
||||
confirm: 'تأكيد',
|
||||
delete: 'حذف',
|
||||
@@ -15,9 +16,17 @@ export default {
|
||||
end: 'نهاية',
|
||||
start: 'بداية',
|
||||
title: 'التقويم',
|
||||
weekdays: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
|
||||
weekdays: [
|
||||
'الأحد',
|
||||
'الاثنين',
|
||||
'الثلاثاء',
|
||||
'الأربعاء',
|
||||
'الخميس',
|
||||
'الجمعة',
|
||||
'السبت',
|
||||
],
|
||||
monthTitle: (year: number, month: number) => `${year}/${month}`,
|
||||
rangePrompt: (maxRange: number) => `اختر لا يزيد عن ${maxRange} أيام`
|
||||
rangePrompt: (maxRange: number) => `اختر لا يزيد عن ${maxRange} أيام`,
|
||||
},
|
||||
vanCascader: {
|
||||
select: 'اختر',
|
||||
@@ -59,4 +68,4 @@ export default {
|
||||
vanAddressList: {
|
||||
add: 'إضافة عنوان جديد',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Телефон',
|
||||
save: 'Запазване',
|
||||
clear: 'ясно',
|
||||
undo: 'Отмени',
|
||||
cancel: 'Отказ',
|
||||
confirm: 'Потвърди',
|
||||
delete: 'Изтриване',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'ফোন',
|
||||
save: 'সংরক্ষণ করুন',
|
||||
clear: 'পরিষ্কার',
|
||||
undo: 'পূর্বাবস্থা',
|
||||
cancel: 'বাতিল',
|
||||
confirm: 'নিশ্চিত করুন',
|
||||
delete: 'মুছুন',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Gem',
|
||||
clear: 'Klar',
|
||||
undo: 'Fortryd',
|
||||
cancel: 'Annuller',
|
||||
confirm: 'Bekræft',
|
||||
delete: 'Slet',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Speichern',
|
||||
clear: 'Klar',
|
||||
undo: 'Rückgängig',
|
||||
cancel: 'Abbrechen',
|
||||
confirm: 'Bestätigen',
|
||||
delete: 'Löschen',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Speichern',
|
||||
clear: 'Klar',
|
||||
undo: 'Rückgängig',
|
||||
cancel: 'Abbrechen',
|
||||
confirm: 'Bestätigen',
|
||||
delete: 'Löschen',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Τηλέφωνο',
|
||||
save: 'Αποθήκευση',
|
||||
clear: 'Σαφή',
|
||||
undo: 'Αναίρεση',
|
||||
cancel: 'Ακύρωση',
|
||||
confirm: 'Επιβεβαίωση',
|
||||
delete: 'Διαγραφή',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Phone',
|
||||
save: 'Save',
|
||||
clear: 'Clear',
|
||||
undo: 'Undo',
|
||||
cancel: 'Cancel',
|
||||
confirm: 'Confirm',
|
||||
delete: 'Delete',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefonnumero',
|
||||
save: 'Konservi',
|
||||
clear: 'Klara',
|
||||
undo: 'Malfari',
|
||||
cancel: 'Rezigni',
|
||||
confirm: 'Konfirmi',
|
||||
delete: 'Forigi',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Teléfono',
|
||||
save: 'Guardar',
|
||||
clear: 'Claro',
|
||||
undo: 'Deshacer',
|
||||
cancel: 'Cancelar',
|
||||
confirm: 'Confirmar',
|
||||
delete: 'Eliminar',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'تلفن',
|
||||
save: 'ذخیره',
|
||||
clear: 'پاک کردن',
|
||||
undo: 'واگرد',
|
||||
cancel: 'انصراف',
|
||||
confirm: 'تایید',
|
||||
delete: 'حذف',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telephone',
|
||||
save: 'Sauvegarder',
|
||||
clear: 'Clair',
|
||||
undo: 'Défaire',
|
||||
cancel: 'Annuler',
|
||||
confirm: 'Confirmer',
|
||||
delete: 'Suprimer',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'טלפון',
|
||||
save: 'שמור',
|
||||
clear: 'ברור',
|
||||
undo: 'בטל',
|
||||
cancel: 'ביטול',
|
||||
confirm: 'אישור',
|
||||
delete: 'מחיקה',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'फ़ोन',
|
||||
save: 'सहेजें',
|
||||
clear: 'साफ़',
|
||||
undo: 'पूर्ववत',
|
||||
cancel: 'रद्द करें',
|
||||
confirm: 'पुष्टि करना',
|
||||
delete: 'हटाएं',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telepon',
|
||||
save: 'Simpan',
|
||||
clear: 'Jernih',
|
||||
undo: 'Batalkan',
|
||||
cancel: 'Batal',
|
||||
confirm: 'Konfirmasi',
|
||||
delete: 'Hapus',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Sími',
|
||||
save: 'Vista',
|
||||
clear: 'Hreinsa',
|
||||
undo: 'Afturkalla',
|
||||
cancel: 'hætta við',
|
||||
confirm: 'Staðfesta',
|
||||
delete: 'Eyða',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefono',
|
||||
save: 'Salva',
|
||||
clear: 'Chiaro',
|
||||
undo: 'Annulla',
|
||||
cancel: 'Annulla',
|
||||
confirm: 'Conferma',
|
||||
delete: 'Elimina',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: '電話番号',
|
||||
save: 'セーブ',
|
||||
clear: 'クリア',
|
||||
undo: '元に戻す',
|
||||
cancel: 'キャンセル',
|
||||
confirm: '確認',
|
||||
delete: '削除',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Телефон',
|
||||
save: 'Сақтау',
|
||||
clear: 'Тазарту',
|
||||
undo: 'Болдырмау',
|
||||
cancel: 'Бастарту',
|
||||
confirm: 'Растау',
|
||||
delete: 'Жою',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'ទូរស័ព្ទ',
|
||||
save: 'រក្សាទុក',
|
||||
clear: 'ច្បាស់',
|
||||
undo: 'មិនធ្វើវិញ',
|
||||
cancel: 'បោះបង់',
|
||||
confirm: 'យល់ព្រម',
|
||||
delete: 'លុប',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: '핸드폰',
|
||||
save: '구하다',
|
||||
clear: '분명한',
|
||||
undo: '실행 취소',
|
||||
cancel: '취소',
|
||||
confirm: '확인',
|
||||
delete: '삭제',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'ໂທລະສັບ',
|
||||
save: 'ບັນທຶກ',
|
||||
clear: 'ຈະແຈ້ງ',
|
||||
undo: 'ຍົກເລີກ',
|
||||
cancel: 'ຍົກເລີກ',
|
||||
confirm: 'ຢຶນຢັນ',
|
||||
delete: 'ລືບ',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Утас',
|
||||
save: 'Хадгалах',
|
||||
clear: 'Тодорхой',
|
||||
undo: 'Буцаах',
|
||||
cancel: 'Цуцлах',
|
||||
confirm: 'Баталгаажуулах',
|
||||
delete: 'Устгах',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Lagre',
|
||||
clear: 'Klar',
|
||||
undo: 'Angre',
|
||||
cancel: 'Avbryt',
|
||||
confirm: 'Bekreft',
|
||||
delete: 'Slett',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefoon',
|
||||
save: 'Opslaan',
|
||||
clear: 'Duidelijk',
|
||||
undo: 'Ongedaan maken',
|
||||
cancel: 'Annuleren',
|
||||
confirm: 'Bevestigen',
|
||||
delete: 'Verwijderen',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Zapisz',
|
||||
clear: 'Wyczyść',
|
||||
undo: 'Cofnij',
|
||||
cancel: 'Anuluj',
|
||||
confirm: 'Potwierdź',
|
||||
delete: 'Usuń',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Fone',
|
||||
save: 'Salvar',
|
||||
clear: 'Claro',
|
||||
undo: 'Desfazer',
|
||||
cancel: 'Cancelar',
|
||||
confirm: 'Confirmar',
|
||||
delete: 'Excluir',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Salvează',
|
||||
clear: 'Clar',
|
||||
undo: 'Anulează',
|
||||
cancel: 'Anulează',
|
||||
confirm: 'Confirmă',
|
||||
delete: 'Șterge',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Телефон',
|
||||
save: 'Сохранить',
|
||||
clear: 'Прозрачный',
|
||||
undo: 'Отменить',
|
||||
cancel: 'Отмена',
|
||||
confirm: 'Подтвердить',
|
||||
delete: 'Удалить',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Broj telefona',
|
||||
save: 'Sačuvaj',
|
||||
clear: 'Prazno',
|
||||
undo: 'Поништи',
|
||||
cancel: 'Otkaži',
|
||||
confirm: 'Potvrdi',
|
||||
delete: 'Brisanje',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Spara',
|
||||
clear: 'Klar',
|
||||
undo: 'Ångra',
|
||||
cancel: 'Avbryt',
|
||||
confirm: 'Bekräfta',
|
||||
delete: 'Radera',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'โทรศัพท์',
|
||||
save: 'บันทึก',
|
||||
clear: 'ชัดเจน',
|
||||
undo: 'เลิกทำ',
|
||||
cancel: 'ยกเลิก',
|
||||
confirm: 'ยืนยัน',
|
||||
delete: 'ลบ',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Telefon',
|
||||
save: 'Kaydet',
|
||||
clear: 'Temizlemek',
|
||||
undo: 'Geri Al',
|
||||
cancel: 'İptal',
|
||||
confirm: 'Onayla',
|
||||
delete: 'Sil',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Телефон',
|
||||
save: 'Зберегти',
|
||||
clear: 'ясно',
|
||||
undo: 'Скасувати',
|
||||
cancel: 'Скасувати',
|
||||
confirm: 'Підтвердити',
|
||||
delete: 'Видалити',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: 'Điện thoại',
|
||||
save: 'Cứu',
|
||||
clear: 'Thông thoáng',
|
||||
undo: 'Hoàn tác',
|
||||
cancel: 'Hủy bỏ',
|
||||
confirm: 'Xác nhận',
|
||||
delete: 'Xóa',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: '电话',
|
||||
save: '保存',
|
||||
clear: '清空',
|
||||
undo: '撤销',
|
||||
cancel: '取消',
|
||||
confirm: '确认',
|
||||
delete: '删除',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: '電話',
|
||||
save: '保存',
|
||||
clear: '清空',
|
||||
undo: '撤銷',
|
||||
cancel: '取消',
|
||||
confirm: '確認',
|
||||
delete: '刪除',
|
||||
|
||||
@@ -3,6 +3,7 @@ export default {
|
||||
tel: '電話',
|
||||
save: '儲存',
|
||||
clear: '清空',
|
||||
undo: '復原',
|
||||
cancel: '取消',
|
||||
confirm: '確認',
|
||||
delete: '刪除',
|
||||
|
||||
@@ -84,9 +84,11 @@ Use `background-color` prop to set the color of the background.
|
||||
| type | Export image type | _string_ | `png` |
|
||||
| pen-color | Color of the brush stroke, default is black | _string_ | `#000` |
|
||||
| line-width | Width of the line | _number_ | `3` |
|
||||
| history-size | Maximum undo history size | _number_ | `20` |
|
||||
| background-color | Background color | _string_ | - |
|
||||
| tips | Text that appears when Canvas is not supported | _string_ | - |
|
||||
| clear-button-text | Clear button text | _string_ | `Clear` |
|
||||
| undo-button-text | Undo button text | _string_ | `Undo` |
|
||||
| confirm-button-text | Confirm button text | _string_ | `Confirm` |
|
||||
|
||||
### Events
|
||||
@@ -114,6 +116,7 @@ Use [ref](https://vuejs.org/guide/essentials/template-refs.html) to get Signatur
|
||||
| resize `v4.7.3` | Resize Signature when container element resized or visibility changed | - | - |
|
||||
| clear `v4.8.6` | Can be called to clear the signature | - | - |
|
||||
| submit `v4.8.6` | Trigger the `submit` event, which is equivalent to clicking the confirm button. | - | - |
|
||||
| undo | Undo the last stroke | - | - |
|
||||
|
||||
### Types
|
||||
|
||||
|
||||
@@ -84,9 +84,11 @@ export default {
|
||||
| type | 导出图片类型 | _string_ | `png` |
|
||||
| pen-color | 笔触颜色,默认黑色 | _string_ | `#000` |
|
||||
| line-width | 线条宽度 | _number_ | `3` |
|
||||
| history-size | 撤销历史记录最大数量 | _number_ | `20` |
|
||||
| background-color | 背景颜色 | _string_ | - |
|
||||
| tips | 当不支持 Canvas 的时候出现的提示文案 | _string_ | - |
|
||||
| clear-button-text | 清除按钮文案 | _string_ | `清空` |
|
||||
| undo-button-text | 撤销按钮文案 | _string_ | `撤销` |
|
||||
| confirm-button-text | 确认按钮文案 | _string_ | `确认` |
|
||||
|
||||
### Events
|
||||
@@ -114,6 +116,7 @@ export default {
|
||||
| resize `v4.7.3` | 外层元素大小或组件显示状态变化时,可以调用此方法来触发重绘 | - | - |
|
||||
| clear `v4.8.6` | 可调用此方法来清除签名 | - | - |
|
||||
| submit `v4.8.6` | 触发 `submit` 事件,与点击确认按钮的效果等价 | - | - |
|
||||
| undo | 撤销上一次笔画 | - | - |
|
||||
|
||||
### 类型定义
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ export const signatureProps = {
|
||||
type: makeStringProp('png'),
|
||||
penColor: makeStringProp('#000'),
|
||||
lineWidth: makeNumberProp(3),
|
||||
historySize: makeNumberProp(20),
|
||||
undoButtonText: String,
|
||||
clearButtonText: String,
|
||||
backgroundColor: makeStringProp(''),
|
||||
confirmButtonText: String,
|
||||
@@ -66,6 +68,19 @@ export default defineComponent({
|
||||
let canvasHeight = 0;
|
||||
let canvasRect: DOMRect;
|
||||
|
||||
const history = ref<ImageData[]>([]);
|
||||
|
||||
const saveState = () => {
|
||||
if (ctx.value && canvasWidth && canvasHeight) {
|
||||
if (history.value.length >= props.historySize) {
|
||||
history.value.shift();
|
||||
}
|
||||
history.value.push(
|
||||
ctx.value.getImageData(0, 0, canvasWidth, canvasHeight),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const touchStart = () => {
|
||||
if (!ctx.value) {
|
||||
return false;
|
||||
@@ -100,6 +115,7 @@ export default defineComponent({
|
||||
|
||||
const touchEnd = (event: TouchEvent) => {
|
||||
preventDefault(event);
|
||||
saveState();
|
||||
emit('end');
|
||||
};
|
||||
|
||||
@@ -152,9 +168,27 @@ export default defineComponent({
|
||||
ctx.value.closePath();
|
||||
setCanvasBgColor(ctx.value);
|
||||
}
|
||||
history.value = [];
|
||||
emit('clear');
|
||||
};
|
||||
|
||||
const undo = () => {
|
||||
if (history.value.length) {
|
||||
history.value.pop();
|
||||
if (ctx.value) {
|
||||
ctx.value.clearRect(0, 0, canvasWidth, canvasHeight);
|
||||
setCanvasBgColor(ctx.value);
|
||||
if (history.value.length) {
|
||||
ctx.value.putImageData(
|
||||
history.value[history.value.length - 1],
|
||||
0,
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const initialize = () => {
|
||||
if (isRenderCanvas && canvasRef.value) {
|
||||
const canvas = canvasRef.value;
|
||||
@@ -183,6 +217,7 @@ export default defineComponent({
|
||||
resize,
|
||||
clear,
|
||||
submit,
|
||||
undo,
|
||||
});
|
||||
|
||||
return () => (
|
||||
@@ -205,6 +240,9 @@ export default defineComponent({
|
||||
<Button size="small" onClick={clear}>
|
||||
{props.clearButtonText || t('clear')}
|
||||
</Button>
|
||||
<Button size="small" onClick={undo}>
|
||||
{props.undoButtonText || t('undo')}
|
||||
</Button>
|
||||
<Button type="primary" size="small" onClick={submit}>
|
||||
{props.confirmButtonText || t('confirm')}
|
||||
</Button>
|
||||
|
||||
@@ -22,29 +22,6 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Confirm
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!--[-->
|
||||
<div class="van-signature">
|
||||
<div class="van-signature__content">
|
||||
<canvas>
|
||||
</canvas>
|
||||
</div>
|
||||
<div class="van-signature__footer">
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
@@ -53,7 +30,7 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Clear
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
@@ -92,6 +69,18 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
@@ -127,6 +116,65 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Confirm
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!--[-->
|
||||
<div class="van-signature">
|
||||
<div class="van-signature__content">
|
||||
<canvas>
|
||||
</canvas>
|
||||
</div>
|
||||
<div class="van-signature__footer">
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Clear
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
|
||||
@@ -21,36 +21,13 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Confirm
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-signature">
|
||||
<div class="van-signature__content">
|
||||
<canvas
|
||||
width="100"
|
||||
height="100"
|
||||
>
|
||||
</canvas>
|
||||
</div>
|
||||
<div class="van-signature__footer">
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Clear
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
@@ -87,6 +64,16 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
@@ -120,6 +107,59 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Confirm
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-signature">
|
||||
<div class="van-signature__content">
|
||||
<canvas
|
||||
width="100"
|
||||
height="100"
|
||||
>
|
||||
</canvas>
|
||||
</div>
|
||||
<div class="van-signature__footer">
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Clear
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
|
||||
@@ -12,6 +12,16 @@ exports[`should allow to custom button text 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
@@ -43,6 +53,16 @@ exports[`should render tips correctly 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
|
||||
@@ -19,6 +19,18 @@ exports[`should render correctly when SSR 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--default van-button--small"
|
||||
style
|
||||
>
|
||||
<div class="van-button__content">
|
||||
<span class="van-button__text">
|
||||
<!--[-->
|
||||
Undo
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="van-button van-button--primary van-button--small"
|
||||
|
||||
@@ -108,3 +108,88 @@ test('should call resize when window width changes', async () => {
|
||||
await trigger(window, 'resize');
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
|
||||
test('expose undo method', async () => {
|
||||
const wrapper = mount(Signature);
|
||||
expect(wrapper.vm.undo).toBeTypeOf('function');
|
||||
});
|
||||
|
||||
test('should allow to custom undo button text', async () => {
|
||||
const wrapper = mount(Signature, {
|
||||
props: {
|
||||
undoButtonText: 'Back',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find('.van-signature__footer').text()).toContain('Back');
|
||||
});
|
||||
|
||||
test('undo should restore canvas to previous state', async () => {
|
||||
const wrapper = mount(Signature);
|
||||
const canvas = wrapper.find('canvas');
|
||||
const ctx = canvas.element.getContext('2d')!;
|
||||
|
||||
const putImageDataSpy = vi.spyOn(ctx, 'putImageData');
|
||||
const clearRectSpy = vi.spyOn(ctx, 'clearRect');
|
||||
|
||||
// First stroke
|
||||
await canvas.trigger('touchstart');
|
||||
await canvas.trigger('touchmove', {
|
||||
touches: [{ clientX: 10, clientY: 10 }],
|
||||
});
|
||||
await canvas.trigger('touchend');
|
||||
|
||||
// Second stroke
|
||||
await canvas.trigger('touchstart');
|
||||
await canvas.trigger('touchmove', {
|
||||
touches: [{ clientX: 50, clientY: 50 }],
|
||||
});
|
||||
await canvas.trigger('touchend');
|
||||
|
||||
// Undo should restore to state after first stroke
|
||||
wrapper.vm.undo();
|
||||
expect(clearRectSpy).toHaveBeenCalled();
|
||||
expect(putImageDataSpy).toHaveBeenCalled();
|
||||
|
||||
// Undo again should clear canvas (no more history)
|
||||
wrapper.vm.undo();
|
||||
expect(clearRectSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test('history should be limited by historySize prop', async () => {
|
||||
const wrapper = mount(Signature, {
|
||||
props: {
|
||||
historySize: 3,
|
||||
},
|
||||
});
|
||||
const canvas = wrapper.find('canvas');
|
||||
const ctx = canvas.element.getContext('2d')!;
|
||||
|
||||
const getImageDataSpy = vi.spyOn(ctx, 'getImageData');
|
||||
|
||||
// Draw 5 strokes
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await canvas.trigger('touchstart');
|
||||
await canvas.trigger('touchmove', {
|
||||
touches: [{ clientX: i * 10, clientY: i * 10 }],
|
||||
});
|
||||
await canvas.trigger('touchend');
|
||||
}
|
||||
|
||||
// getImageData should be called 5 times
|
||||
expect(getImageDataSpy).toHaveBeenCalledTimes(5);
|
||||
|
||||
// Undo 3 times (max history size)
|
||||
const clearRectSpy = vi.spyOn(ctx, 'clearRect');
|
||||
wrapper.vm.undo();
|
||||
wrapper.vm.undo();
|
||||
wrapper.vm.undo();
|
||||
|
||||
expect(clearRectSpy).toHaveBeenCalledTimes(3);
|
||||
|
||||
// Fourth undo should do nothing (history exhausted)
|
||||
const putImageDataSpy = vi.spyOn(ctx, 'putImageData');
|
||||
putImageDataSpy.mockClear();
|
||||
wrapper.vm.undo();
|
||||
expect(putImageDataSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ export type SignatureExpose = {
|
||||
resize: () => void;
|
||||
clear: () => void;
|
||||
submit: () => void;
|
||||
undo: () => void;
|
||||
};
|
||||
|
||||
export type SignatureInstance = ComponentPublicInstance<
|
||||
|
||||
Reference in New Issue
Block a user