嘉兴绿城濮院
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

190 lines
4.8 KiB

<template>
<canvas
:style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }"
ref="inkCanvasRef"
:width="width"
:height="height"
id="ink-canvas"
></canvas>
<div></div>
</template>
<script lang="ts" setup>
import { reactive, computed, onMounted, onBeforeUnmount, watch, ref } from 'vue'
import { getHandWriting } from '@/http/api'
type WriteType = 'CN' | 'EN'
type State = {
handWrite: string
isClick: boolean
//轨迹X
clickX: number[]
//轨迹Y
clickY: number[]
//轨迹标志位,为1则是终点
clickC: number[]
X: number
Y: number
oldX: number
oldY: number
timer: number
list: string[] //返回汉字列表
}
type Props = {
width: number
height: number
lang: WriteType
backgroundColor: string
borderRadius: string
fillText: string
fillFontSize: string
strokeStyle: string
fillStyle: string
}
const props = withDefaults(defineProps<Props>(), {
width: 800,
height: 800,
lang: 'CN',
backgroundColor: '#f2f2f2',
borderRadius: '10px',
fillText: '手写区域',
fillFontSize: '100px',
strokeStyle: '#000',
fillStyle: 'rgba(85, 73, 54, 0.1)'
})
const emits = defineEmits(['result'])
const state = reactive<State>({
handWrite: '',
isClick: false,
//轨迹X
clickX: [],
//轨迹Y
clickY: [],
//轨迹标志位,为1则是终点
clickC: [],
X: 0,
Y: 0,
oldX: 0,
oldY: 0,
timer: 0,
list: [] //返回汉字列表
})
const inkCanvasRef = ref<HTMLCanvasElement | null>(null)
const ctxComRef = computed(() => (inkCanvasRef.value as HTMLCanvasElement).getContext('2d'))
function updateBound() {
const bound = (inkCanvasRef.value as HTMLCanvasElement).getBoundingClientRect()
state.X = bound.x
state.Y = bound.y
}
function down(ev: MouseEvent | TouchEvent) {
const cx = Math.floor((ev as MouseEvent).clientX || (ev as TouchEvent).targetTouches[0].clientX) - state.X
const cy = Math.floor((ev as MouseEvent).clientY || (ev as TouchEvent).targetTouches[0].clientY) - state.Y
clearTimeout(state.timer)
state.oldX = cx
state.oldY = cy
ctxComRef.value && ctxComRef.value.beginPath()
state.isClick = true
}
function move(ev: MouseEvent | TouchEvent) {
ev.preventDefault()
if (state.isClick) {
const cx = Math.floor((ev as MouseEvent).clientX || (ev as TouchEvent).targetTouches[0].clientX) - state.X
const cy = Math.floor((ev as MouseEvent).clientY || (ev as TouchEvent).targetTouches[0].clientY) - state.Y
state.clickX.push(cx)
state.clickY.push(cy)
state.clickC.push(0)
//画图
;(ctxComRef.value as CanvasRenderingContext2D).lineWidth = 8
;(ctxComRef.value as CanvasRenderingContext2D).lineCap = 'round'
ctxComRef.value && ctxComRef.value.moveTo(state.oldX, state.oldY)
ctxComRef.value && ctxComRef.value.lineTo(cx, cy)
ctxComRef.value && ctxComRef.value.stroke()
state.oldX = cx
state.oldY = cy
}
}
function mouseUp() {
if (state.isClick) {
state.isClick = false
state.timer = setTimeout(() => {
reload()
}, 1500)
//标记最后一点为终点
state.clickC.pop()
state.clickC.push(1)
_getHandWriting()
}
}
function reload() {
if (!inkCanvasRef.value) {
return
}
state.clickX = []
state.clickY = []
state.clickC = []
;(ctxComRef.value as CanvasRenderingContext2D).strokeStyle = props.strokeStyle
;(ctxComRef.value as CanvasRenderingContext2D).fillStyle = props.fillStyle
;(ctxComRef.value as CanvasRenderingContext2D).clearRect(0, 0, props.width, props.height)
;(ctxComRef.value as CanvasRenderingContext2D).font = `bold ${props.fillFontSize} Arial`
;(ctxComRef.value as CanvasRenderingContext2D).textAlign = 'center'
;(ctxComRef.value as CanvasRenderingContext2D).textBaseline = 'middle'
ctxComRef.value && ctxComRef.value.fillText(props.fillText, props.width / 2, props.height / 2, 1000)
}
function _getHandWriting() {
const params = {
lib: props.lang,
lpXis: state.clickX,
lpYis: state.clickY,
lpCis: state.clickC
}
getHandWriting(params)
.then(res => {
const { data } = res
state.list = data as string[]
})
.catch(err => {
console.log(err)
})
}
watch(
() => state.list,
newVal => {
emits('result', newVal)
}
)
onMounted(() => {
updateBound()
reload()
;(inkCanvasRef.value as HTMLElement).addEventListener('touchstart', down)
;(inkCanvasRef.value as HTMLElement).addEventListener('touchmove', move)
;(inkCanvasRef.value as HTMLElement).addEventListener('touchend', mouseUp)
})
onBeforeUnmount(() => {
;(inkCanvasRef.value as HTMLElement).removeEventListener('touchstart', down)
;(inkCanvasRef.value as HTMLElement).removeEventListener('touchmove', move)
;(inkCanvasRef.value as HTMLElement).removeEventListener('touchend', mouseUp)
})
defineExpose({
updateBound,
reload
})
defineExpose({
updateBound,
reload
})
</script>