使用websocket实现手机扫描PC端二维码,移动端canvas手绘签名确定后将图片同步到PC端 扫码及时更新图片
这个Demo我放到线上啦,大家可以试一下(前端是用vue写的,后台是用springboot写的 还处于学习阶段 帮不到各位大神也请各位轻点喷http://draw.niezhiliang.com/我们首先看下效果,我把图截下来来:1.这个是线上地址打开的页面2.这是扫描二维码后手机打开的界面(不要用微信去扫,微信显示不安全 用支付宝或其他的可以出来页面)3.当手机页...
这个Demo我放到线上啦,大家可以试一下(前端是用vue写的,后台是用springboot写的 还处于学习阶段 帮不到各位大神也请各位轻点喷
我们首先看下效果,我把图截下来来:
1.这个是线上地址打开的页面
2.这是扫描二维码后手机打开的界面(不要用微信去扫,微信显示不安全 用支付宝或其他的可以出来页面)
3.当手机页面绘制忘了你想要绘制的东西,点击提交 PC端页面就会变成这个样子啦 (达到了及时更新的效果)
4.写了一个小时的博客 ,发布上去就成了五十个字啦 我特么也不知道咋回事 这就跟你写一篇作文,你认真去写 但是意外跑题啦, 再写一遍再也没那个心情啦 我把线上地址放出来 自己测试 可以问我要代码(到时候找个时间整理出来)
开始讲一下实现原理:
1.分为三部分 1.就是上面的线上链接页面 2.手机扫码出现的页面3.后台代码
使用的东西(前端vue 二维码插件是vue-qr 后台是springboot)
首先就是生产一张二维码,然后在页面加载的时候跟后台进行websocket的连接,连接的时候必须传一个userid,目的就是为了让后台知道是谁在跟我进行连接,然后二维码地址也必须带一个参数参数名无所谓 但是值必须是userid。为的就是让后台收到手机端的canvas的base64 转换成图片后 上传到oss的地址推送给线上的链接页面,PC端页面接受到来自后台推送的图片地址 然后将图片的地址换了 就达到了及时更新的效果。
生成二维码代码: text属性就是我们要的网址(这句代码只能使用vue框架和vue-qr组件才能实现二维码)
<vue-qr :bgSrc='config.imagePath' :logoSrc="config.imagePath" :text="config.url" height="300" width="300"></vue-qr>
2.进行websocket连接的代码
init : function() {
if (vc.get('token-qrcode')) {
this.identity = vc.get('token-qrcode')
} else {
this.identity = 'qrcode'+this.initidentity(10);
vc.set('token-qrcode', this.identity, 1);
}//这个就是连接后台的地址 一定要给后面这个参数
let url = "ws://draw.niezhiliang.com:8080/socketServer/"+this.identity
if ('WebSocket' in window){
this.ws = new WebSocket(url);
}
else if ('MozWebSocket' in window){
this.ws = new MozWebSocket(url);
}
//普通的js写法不支持赋值操作
this.ws.onmessage = (evt) => {
this.config.imgpath = evt.data
}
}
vc.get() 和vc.set() 是对cookie进行操作 其实这个你们不必这么做,给个固定的userid就够了 我是通过这个做了当前在线的操作,所以才把userid保存到了cookie 然后用的时候从cookie里面拿出来。
这个页面就说完了。
3.我们说下手机浏览器的页面
<template>
<div class="inner draw" @mousemove="beginPath($event)">
<div class="wrap" style="position: relative;">
<canvas
id="canvas"
class="fl"
:width="screenWidth"
:height="screenHeight"
@mousedown="canvasDown($event)"
@mouseup="canvasUp($event)"
@mousemove="canvasMove($event)"
@touchstart="canvasDown($event)"
@touchend="canvasUp($event)"
@touchmove="canvasMove($event)"
>
</canvas>
<div id="control" style="float: left">
<div id="canvas-control">
<button class="el-button btn-orange el-button--primary"
@click="controlCanvas('clear')">
清除
</button>
<button @click="getImage" class="el-button btn-orange el-button--primary">
确定
</button>
</div>
</div>
</div>
</div>
</template>
手机端主要就是一个canvas,两个按钮 ,一个清空画板,一个保存数据提交到后台 。
我们通过记录手机触摸点的各个位置 然后给它的移动留下轨迹 就形成了我们要的图片内容
canvas里面全是一些事件 记录运动轨迹的,绘制完了我们通过点击 确定按钮 然后通过canvas提供的方法得到图片 但是得到的是base64所以我们在后台还进行了一次转图片的操作 然后再保存的oss。
// 生成图片的方法
getImage () {
const canvas = document.querySelector('#canvas')
const src = canvas.toDataURL('image/png')
let pic = src;
let id = null
let url = window.location.href;
id = url.substring(url.lastIndexOf('=')+1)
//后台的请求地址 id是二维码地址穿过来的 我们截取一下就得到了
request.post('upload', { base64code: pic,userid: id }).then(res => {
if (res.data.status === 20) {
alert('绘制成功,请到pc端查看')
window.opener = null
window.close()
}
}).catch(function (err) {
alert(err)
})
},
后台代码:
后台主要就是websocket啦 如果你不是很懂得话 可以去看看我的另一篇博客 其实原理就是通过那篇博客的内容来实现的。
我们来看代码:
定义的websocket的入口(注意有个userid)
@ServerEndpoint(value = "/socketServer/{userid}")
@Component
public class SocketServer {
private Session session;
private static Map<String,Session> sessionPool = new HashMap<String,Session>();
private static Map<String,String> sessionIds = new HashMap<String,String>();
private static Map<String,String> onlinesize = new HashMap<String, String>();
Set<String> online = new HashSet<String>();
@OnOpen
public void open(Session session,@PathParam(value="userid")String userid){
this.session = session;
sessionPool.put(userid, session);
sessionIds.put(session.getId(), userid);
}
public static void sendMessage(String message,String userId){
Session s = sessionPool.get(userId);
if(s!=null){
try {
s.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
手机页面点确定跳转的controller(主要就是把前端传的base64转成流 然后保存到oss 然后返回文件地址 调用socket的发现信息方法,将地址推送到前端页面)
/**上传base64到oss**/
@RequestMapping(value = "base64upload")
public String qrcodesign(@RequestBody QrcodePo qrcodePo) {
RestInfo restInfo = new RestInfo();
if(qrcodePo.getUserid() == null || qrcodePo.getBase64code() == null) {
restInfo.setCode(InfoCode.ERROR);
restInfo.setMessage("用户名和base64都必传");
} else {
//这里主要是为了url转码用
String code = qrcodePo.getBase64code().replace(' ','+');
restInfo = fileupload(code);
}
SocketServer.sendMessage(restInfo.getContent().toString(),qrcodePo.getUserid());
return JSON.toJSONString(restInfo);
}
/**
* 文件上传
* @param
* @return
*/
public RestInfo fileupload (String code) {
OssUtil ossUtil = new OssUtil();
FileOpea fileOpea = new FileOpea();
RestInfo respInfo = new RestInfo();
String oss_file_path ="person/sign/" ;
String fileType = ".png";
byte [] bytes = Base64toImg.GenerateByte(code);
BufferedImage bufferedImage = null;
try {
bufferedImage = ImgUtil.spin(270,bytes);
bufferedImage = ThumbnailatorUtils.ImgBufferedImage(bufferedImage,"D:/sign",300,150,"test.png");
} catch (Exception e) {
e.printStackTrace();
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", os);
InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
fileOpea.setSuffix(fileType);
String fileName = System.currentTimeMillis()+new Random().nextInt(123456)+fileType;
fileOpea.setOssname(fileName);
oss_file_path += fileName;
ossUtil.upload(oss_file_path,inputStream);
fileOpea.setOss_path(osspath+"/"+oss_file_path);
respInfo.setContent(fileOpea.getOss_path());
respInfo.setCode(InfoCode.SUCCESS);
} catch (IOException e) {
respInfo.setCode(InfoCode.ERROR);
}
return respInfo;
}
更多推荐
所有评论(0)