使用websocket实现手机扫描PC端二维码,移动端canvas手绘签名确定后将图片同步到PC端 扫码及时更新图片

这个Demo我放到线上啦,大家可以试一下(前端是用vue写的,后台是用springboot写的 还处于学习阶段  帮不到各位大神也请各位轻点喷

http://huluwa-test.oss-cn-hangzhou.aliyuncs.com/pdf/index.html#/qrcode

我们首先看下效果,我把图截下来来:

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://www.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.replace(/^data:image\/(png|jpg);base64,/, '')
        let id = null
        let url = window.location.href;
        id = url.substring(url.lastIndexOf('=')+1)
        //后台的请求地址 id是二维码地址穿过来的  我们截取一下就得到了
        request.post('qrcode/base64upload', { 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;
    }

猜你喜欢

转载自blog.csdn.net/qq_38082304/article/details/79567130
今日推荐