Skip to content

Commit 111418c

Browse files
committed
feat: 身份证裁剪支持任意角度旋转 (Issue #67)
新增 ±45° 细调滑块,配合原有 90° 粗调按钮,方便矫正拍歪的证件照片
1 parent 8dd6eb6 commit 111418c

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

frontend/src/components/print/ImageCropModal.vue

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,26 @@
99
<div class="relative bg-elevated rounded-lg overflow-hidden" style="max-height: 60vh;">
1010
<img ref="imgRef" :src="imageUrl" class="max-w-full block" />
1111
</div>
12-
<div class="flex items-center justify-between">
13-
<div class="flex gap-1">
12+
<div class="flex items-center gap-2">
13+
<div class="flex gap-1 shrink-0">
1414
<UButton variant="outline" size="sm" icon="i-lucide-rotate-ccw" @click="rotateLeft">左旋</UButton>
1515
<UButton variant="outline" size="sm" icon="i-lucide-rotate-cw" @click="rotateRight">右旋</UButton>
1616
</div>
17-
<div class="flex gap-2">
18-
<UButton variant="ghost" @click="cancel">取消</UButton>
19-
<UButton color="primary" icon="i-lucide-check" @click="confirm">确认裁剪</UButton>
20-
</div>
17+
<input
18+
type="range"
19+
:min="-45"
20+
:max="45"
21+
step="0.5"
22+
v-model.number="fineAngle"
23+
class="flex-1 h-1.5 accent-[var(--ui-primary)]"
24+
@input="onFineRotate"
25+
/>
26+
<span class="text-xs text-muted tabular-nums w-12 text-right shrink-0">{{ fineAngle.toFixed(1) }}°</span>
27+
<UButton v-if="fineAngle !== 0" variant="ghost" size="xs" icon="i-lucide-undo-2" @click="resetFine" />
28+
</div>
29+
<div class="flex justify-end gap-2">
30+
<UButton variant="ghost" @click="cancel">取消</UButton>
31+
<UButton color="primary" icon="i-lucide-check" @click="confirm">确认裁剪</UButton>
2132
</div>
2233
</div>
2334
</template>
@@ -39,12 +50,16 @@ const emit = defineEmits(['cropped', 'close'])
3950
4051
const isOpen = ref(false)
4152
const imgRef = ref(null)
53+
const fineAngle = ref(0)
54+
const baseAngle = ref(0)
4255
let cropper = null
4356
4457
watch(() => props.open, (val) => { isOpen.value = val })
4558
4659
watch(isOpen, (val) => {
4760
if (val) {
61+
fineAngle.value = 0
62+
baseAngle.value = 0
4863
nextTick(() => initCropper())
4964
} else {
5065
destroyCropper()
@@ -165,8 +180,23 @@ function confirm() {
165180
}, 'image/jpeg', 0.92)
166181
}
167182
168-
function rotateLeft() { if (cropper) cropper.rotate(-90) }
169-
function rotateRight() { if (cropper) cropper.rotate(90) }
183+
function rotateLeft() {
184+
if (!cropper) return
185+
baseAngle.value -= 90
186+
cropper.rotateTo(baseAngle.value + fineAngle.value)
187+
}
188+
function rotateRight() {
189+
if (!cropper) return
190+
baseAngle.value += 90
191+
cropper.rotateTo(baseAngle.value + fineAngle.value)
192+
}
193+
function onFineRotate() {
194+
if (cropper) cropper.rotateTo(baseAngle.value + fineAngle.value)
195+
}
196+
function resetFine() {
197+
fineAngle.value = 0
198+
onFineRotate()
199+
}
170200
171201
function cancel() { isOpen.value = false }
172202

0 commit comments

Comments
 (0)