如何用canvas实现手写输入并能识别的功能
Admin 2022-07-07 群英技术资讯 779 次浏览
效果图:
前言:
最近做一个室外大屏项目,系统上的输入法使用不方便,客户要求做一个嵌入web网页的手写输入法。
核心:
后端接口api:使用 QQ输入法手写接口
https://handwriting.shuru.qq.com/cloud/cgi-bin/cloud_hw_pub.wsgi
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
track_str | 笔画字符串,单笔画以'x1,y1,x2,y2,…‘格式拼接,多笔画在单笔画的基础上以eb拼接,例如'x1,y1,x2,y2,eb,x3,y3,x4,y4' | string | - |
cmd | 未知,目前传0 | number | - |
注:此接口通过其他大佬文章获知,原文在此,本人未能查到官方文档相关地址,如果有大佬知晓还请留言告知,感谢!
思路:
(1)创建一个canvas绘图区域
// template <div class="canvas-container"> <canvas ref="canvas" width="300" height="200">你的浏览器不支持 canvas,请升级你的浏览器。</canvas> </div> // scss .canvas-container { background: #fafafa; canvas { background: #fff; border: 1px solid #000; } }
(2)获取初始横纵坐标
data() { return { initX: 0, // 初始横坐标 initY: 0, // 初始纵坐标 } }, mounted() { this.initBound() }, methods: { // 初始化canvas位置 initBound() { let bound = this.$refs.canvas.getBoundingClientRect() this.initX = bound.x this.initY = bound.y } }
(3)添加鼠标点击事件、移动事件、松开事件
// template <div class="canvas-container"> <canvas ref="canvas" width="300" height="200" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp">你的浏览器不支持 canvas,请升级你的浏览器。</canvas> </div> // script data() { return { // ... lastX: 0, // 上一个横坐标 lastY: 0, // 上一个纵坐标 isHandWrite: false, // 是否开始手写 pointsXY: [], // 单笔画 allPointsXY: [], // 全部笔画 } }, 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上下文对象 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() // 识别文字 } }, }
(4)添加识别文字接口以及jsonp回调函数,跨域请求使用了 vue-jsonp ,具体用法可参vue中jsonp的使用方法
// script data() { return { // ... write_result: [], // 返回相近字 } }, mounted() { // ... let _this = this // 添加jsonp回调函数, 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)最后再加个清除画布的重写按钮
// template <div> <button @click="onReload">重写</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,请升级你的浏览器。</canvas> </div> <div>[{{ lastX + ', ' + lastY }}]</div> <div> <button @click="onReload">重写</button> </div> <div>返回相近字:{{ write_result }}</div> </div> </template> <script> export default { name: 'App', data() { return { initX: 0, // 初始横坐标 initY: 0, // 初始纵坐标 lastX: 0, // 上一个横坐标 lastY: 0, // 上一个纵坐标 isHandWrite: false, // 是否开始手写 pointsXY: [], // 单笔画 allPointsXY: [], // 全部笔画 write_result: [], // 返回相近字 } }, mounted() { this.initBound() let _this = this // 添加jsonp回调函数, 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上下文对象 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() } }, // 识别文字 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>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要为大家介绍了原生javascript中检查对象是否为空示例实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
本文主要介绍了uniapp如何动态获取接口域名,感兴趣的同学,可以参考下,并且试验一下。
在 JavaScript 中如何判断两个值相等,这个问题看起来非常简单,但并非如此,在 JavaScript 中存在 4 种不同的相等逻辑,如果你不知道他们的区别,或者认为判断相等非常简单,本文就来为大家详细讲讲
VUE+Element 前端应用实现国际化的处理还是非常方便的,一般在Main.js函数里面引入语言文件,然后在界面上进行一定的处理,把对应的键值转换为对应语言的语义即可。本篇随笔介绍在VUE+Element 前端应用中如何实现在界面快速的支持多语言国际化的处理逻辑代码。
方法:1、利用getAttribute()方法获取指定class的属性值;2、利用if语句判断获取到的指定class属性值是否为空即可,语法为“if(获取到的指定class属性值=null){不存在代码;}else{存在代码;}”。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008