vue使用canvas手寫(xiě)輸入識(shí)別中文
效果圖:

前言:
最近做一個(gè)室外大屏項(xiàng)目,系統(tǒng)上的輸入法使用不方便,客戶要求做一個(gè)嵌入web網(wǎng)頁(yè)的手寫(xiě)輸入法。
核心:
后端接口api:使用 QQ輸入法手寫(xiě)接口
https://handwriting.shuru.qq.com/cloud/cgi-bin/cloud_hw_pub.wsgi
| 參數(shù) | 說(shuō)明 | 類(lèi)型 | 默認(rèn)值 |
|---|---|---|---|
| track_str | 筆畫(huà)字符串,單筆畫(huà)以'x1,y1,x2,y2,…‘格式拼接,多筆畫(huà)在單筆畫(huà)的基礎(chǔ)上以eb拼接,例如'x1,y1,x2,y2,eb,x3,y3,x4,y4' | string | - |
| cmd | 未知,目前傳0 | number | - |
注:此接口通過(guò)其他大佬文章獲知,原文在此,本人未能查到官方文檔相關(guān)地址,如果有大佬知曉還請(qǐng)留言告知,感謝!
思路:
(1)創(chuàng)建一個(gè)canvas繪圖區(qū)域
// template
<div class="canvas-container">
<canvas ref="canvas" width="300" height="200">你的瀏覽器不支持 canvas,請(qǐng)升級(jí)你的瀏覽器。</canvas>
</div>
// scss
.canvas-container {
background: #fafafa;
canvas {
background: #fff;
border: 1px solid #000;
}
}
(2)獲取初始橫縱坐標(biāo)
data() {
return {
initX: 0, // 初始橫坐標(biāo)
initY: 0, // 初始縱坐標(biāo)
}
},
mounted() {
this.initBound()
},
methods: {
// 初始化canvas位置
initBound() {
let bound = this.$refs.canvas.getBoundingClientRect()
this.initX = bound.x
this.initY = bound.y
}
}
(3)添加鼠標(biāo)點(diǎn)擊事件、移動(dòng)事件、松開(kāi)事件
// template
<div class="canvas-container">
<canvas ref="canvas" width="300" height="200" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp">你的瀏覽器不支持 canvas,請(qǐng)升級(jí)你的瀏覽器。</canvas>
</div>
// script
data() {
return {
// ...
lastX: 0, // 上一個(gè)橫坐標(biāo)
lastY: 0, // 上一個(gè)縱坐標(biāo)
isHandWrite: false, // 是否開(kāi)始手寫(xiě)
pointsXY: [], // 單筆畫(huà)
allPointsXY: [], // 全部筆畫(huà)
}
},
methods: {
onMouseDown(e) {
this.pointsXY = []
let cx = e.clientX - this.initX
let cy = e.clientY - this.initY
this.lastX = cx
this.lastY = cy
this.pointsXY.push(cx)
this.pointsXY.push(cy)
this.isHandWrite = true
},
onMouseMove(e) {
if (this.isHandWrite) {
let cx = e.clientX - this.initX
let cy = e.clientY - this.initY
this.pointsXY.push(cx - this.lastX)
this.pointsXY.push(cy - this.lastY)
// 獲取2d上下文對(duì)象
let ctx = this.$refs.canvas.getContext('2d')
// 新建一條路徑
ctx.beginPath()
ctx.strokeStyle = '#000'
ctx.fillStyle = '#000'
ctx.lineWidth = 8
ctx.lineCap = 'round'
ctx.moveTo(this.lastX, this.lastY)
ctx.lineTo(cx, cy)
ctx.stroke()
this.lastX = cx
this.lastY = cy
}
},
onMouseUp(e) {
if (this.isHandWrite) {
this.isHandWrite = false
this.allPointsXY.push(this.pointsXY.join(','))
this.queryText() // 識(shí)別文字
}
},
}
(4)添加識(shí)別文字接口以及jsonp回調(diào)函數(shù),跨域請(qǐng)求使用了 vue-jsonp ,具體用法可參vue中jsonp的使用方法
// script
data() {
return {
// ...
write_result: [], // 返回相近字
}
},
mounted() {
// ...
let _this = this
// 添加jsonp回調(diào)函數(shù), qq輸入法特定
window['QQShuru'] = {
HWPanel: {
ajax_callback: function (res) {
_this.write_result = res.cand
},
},
}
},
methods: {
queryText() {
let track_str = this.allPointsXY.join(',eb,')
this.$jsonp(
`https://handwriting.shuru.qq.com/cloud/cgi-bin/cloud_hw_pub.wsgi?track_str=${track_str}&cmd=0`
).catch(err => {
console.log(err)
})
},
}
(5)最后再加個(gè)清除畫(huà)布的重寫(xiě)按鈕
// template
<div>
<button @click="onReload">重寫(xiě)</button>
</div>
// script
onReload() {
if (!this.$refs.canvas) return
this.pointsXY = []
this.allPointsXY = []
let ctx = this.$refs.canvas.getContext('2d')
ctx.clearRect(0, 0, 300, 200)
}
全部代碼如下:
<template>
<div id="app">
<div class="canvas-container">
<canvas ref="canvas" width="300" height="200" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp">你的瀏覽器不支持 canvas,請(qǐng)升級(jí)你的瀏覽器。</canvas>
</div>
<div>[{{ lastX + ', ' + lastY }}]</div>
<div>
<button @click="onReload">重寫(xiě)</button>
</div>
<div>返回相近字:{{ write_result }}</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
initX: 0, // 初始橫坐標(biāo)
initY: 0, // 初始縱坐標(biāo)
lastX: 0, // 上一個(gè)橫坐標(biāo)
lastY: 0, // 上一個(gè)縱坐標(biāo)
isHandWrite: false, // 是否開(kāi)始手寫(xiě)
pointsXY: [], // 單筆畫(huà)
allPointsXY: [], // 全部筆畫(huà)
write_result: [], // 返回相近字
}
},
mounted() {
this.initBound()
let _this = this
// 添加jsonp回調(diào)函數(shù), qq輸入法特定
window['QQShuru'] = {
HWPanel: {
ajax_callback: function (res) {
_this.write_result = res.cand
},
},
}
},
methods: {
// 初始化canvas位置
initBound() {
let bound = this.$refs.canvas.getBoundingClientRect()
this.initX = bound.x
this.initY = bound.y
},
onMouseDown(e) {
console.log('onDown', e)
this.pointsXY = []
let cx = e.clientX - this.initX
let cy = e.clientY - this.initY
this.lastX = cx
this.lastY = cy
this.pointsXY.push(cx)
this.pointsXY.push(cy)
this.isHandWrite = true
},
onMouseMove(e) {
if (this.isHandWrite) {
let cx = e.clientX - this.initX
let cy = e.clientY - this.initY
this.pointsXY.push(cx - this.lastX)
this.pointsXY.push(cy - this.lastY)
// 獲取2d上下文對(duì)象
let ctx = this.$refs.canvas.getContext('2d')
// 新建一條路徑
ctx.beginPath()
ctx.strokeStyle = '#000'
ctx.fillStyle = '#000'
ctx.lineWidth = 8
ctx.lineCap = 'round'
ctx.moveTo(this.lastX, this.lastY)
ctx.lineTo(cx, cy)
ctx.stroke()
this.lastX = cx
this.lastY = cy
}
},
onMouseUp(e) {
if (this.isHandWrite) {
this.isHandWrite = false
this.allPointsXY.push(this.pointsXY.join(','))
this.queryText()
}
},
// 識(shí)別文字
queryText() {
let track_str = this.allPointsXY.join(',eb,')
this.$jsonp(
`https://handwriting.shuru.qq.com/cloud/cgi-bin/cloud_hw_pub.wsgi?track_str=${track_str}&cmd=0`
).catch(err => {
console.log(err)
})
},
onReload() {
if (!this.$refs.canvas) return
this.pointsXY = []
this.allPointsXY = []
let ctx = this.$refs.canvas.getContext('2d')
ctx.clearRect(0, 0, 300, 200)
},
},
}
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
.canvas-container {
background: #fafafa;
canvas {
background: #fff;
border: 1px solid #000;
}
}
}
</style>
到此這篇關(guān)于vue使用canvas手寫(xiě)輸入識(shí)別中文的文章就介紹到這了,更多相關(guān)vue使用canvas手寫(xiě)輸入識(shí)別中文內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue使用Canvas生成隨機(jī)大小且不重疊圓
- Vue使用canvas實(shí)現(xiàn)圖片壓縮上傳
- vue+canvas繪制時(shí)間軸的方法
- VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的全過(guò)程
- VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲
- 如何用VUE和Canvas實(shí)現(xiàn)雷霆戰(zhàn)機(jī)打字類(lèi)小游戲
- VUE+Canvas 實(shí)現(xiàn)桌面彈球消磚塊小游戲的示例代碼
- Vue使用鼠標(biāo)在Canvas上繪制矩形
- vue使用canvas實(shí)現(xiàn)移動(dòng)端手寫(xiě)簽名
- vue+canvas實(shí)現(xiàn)拼圖小游戲
相關(guān)文章
vue directive定義全局和局部指令及指令簡(jiǎn)寫(xiě)
這篇文章主要介紹了vue directive定義全局和局部指令及指令簡(jiǎn)寫(xiě),本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
vue中如何動(dòng)態(tài)綁定圖片,vue中通過(guò)data返回圖片路徑的方法
下面小編就為大家分享一篇vue中如何動(dòng)態(tài)綁定圖片,vue中通過(guò)data返回圖片路徑的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Vue中的transition封裝組件的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue中的transition封裝組件的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
el-input無(wú)法輸入的問(wèn)題和表單驗(yàn)證失敗問(wèn)題解決
在做項(xiàng)目的時(shí)候發(fā)現(xiàn)一個(gè)情況,輸入框無(wú)法輸入值并且表單校驗(yàn)失靈,所以下面這篇文章主要給大家介紹了關(guān)于el-input無(wú)法輸入的問(wèn)題和表單驗(yàn)證失敗問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2023-02-02
vue中el-autocomplete支持分頁(yè)上拉加載功能
最近在項(xiàng)目中使用了ElementUI的el-autocomplete,下面這篇文章主要介紹了vue中el-autocomplete支持分頁(yè)上拉加載功能的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11
vue3中的elementPlus全局組件中文轉(zhuǎn)換方式
這篇文章主要介紹了vue3中的elementPlus全局組件中文轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
vue-quill-editor的使用及個(gè)性化定制操作
這篇文章主要介紹了vue-quill-editor的使用及個(gè)性化定制操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08

