zoukankan      html  css  js  c++  java
  • socket + vue + canvas实践,你画我猜(一)

    正式项目未开始,先先自己练手,做一个你画我猜小游戏,先上一个不完善的dome

    在线地址  
    1.node; 安装socket,启动服务

    var io = require('socket.io').listen(server);

    var messages = [];//暂时存放消息

    //socket连接成功之后触发,用于初始化
    io.sockets.on('connection', function(socket){
    socket.on('getAllMessages', function(){
    //用户连上后,发送messages
    socket.emit('allMessages', messages);
    });
    socket.on('createMessage', function(message){
    //用户向服务器发送消息,存放到messages
    //messages.push(message);
    //向除自己外的所有用户发送消息
    socket.broadcast.emit('messageAdded', message);
    });
    }) 
    2.vue 设置;先在index.html直接引入socket.io.js,此文件由node生成;

    <script type='text/javascript' src='http://localhost:3000/socket.io/socket.io.js' charset='utf-8'></script>

    //然后在vue对象上新增socket属性方便全局使用
    //连接socket
    Vue.prototype.socket = io.connect('http://localhost:3000/');
     
    3.vue文件的画图与数据传输交互

    <template>
    <div id="gameRoom">
    <header class="mui-bar mui-bar-nav">
    <a class="mui-icon mui-icon-arrowleft Hui-icon-left" v-on:tap="back()"></a>
    <h1 class="mui-title Hui-title"><p class="ellipsis">房间名字</p><i class="ellipsis">你画我猜</i></h1>
    <a class="Hui-icon-right mui-icon-extra mui-icon-extra-peoples Hui-icon"></a>
    </header>
    <nav class="mui-bar mui-bar-tab Hui-chat-bar" style="height:auto">
    <div class="sentNews">
    <a href="javascript:;"><i class="mui-icon mui-icon-mic"></i></a>
    <div contenteditable="true"></div>
    <a href="javascript:;"><i class="Hui-icon Hui-icon-face"></i></a>
    <a href="javascript:;"><i class="mui-icon mui-icon-plus"></i></a>
    </div>
    <div style="100%;height:200px;display:none"></div>
    </nav>
    <div class="gameRoom-canvas">
    <div class="canvas-bar"><span>1号正在画,请先围观~{{screenHeight}}</span><span>剩余时间:<i>60</i></span></div>
    <canvas id="gameCanvas" v-bind:width="screenWidth" v-bind:height="screenHeight" v-on:touchstart="touchStart($event)" v-on:touchmove="touchMove($event)" v-on:touchcancel="touchCancel($event)" v-on:touchend="touchEnd($event)" v-on:touchleave="touchEnd($event)"></canvas>
    </div>
    <div id="chat-scroll" class="mui-content Hui-chat-scroll" v-bind:style="{top:screenHeight+68+'px'}">
    <input type="color" value="#333333" list="colors">
    <datalist id="colors">
    <option>#ffffff</option>
    <option>#ff0000</option>
    <option>#ff7700</option>
    </datalist>
    <input type="range" name="points" min="1" max="10" />
    </div>
    </div>
    </template>

    <script>
    export default{
    data(){
    return {
    screenHeight: '',
    screenWidth: '',
    canvasGo:'',
    messages:[],
    dom:false
    }
    },
    mounted(){
    var that = this;
    this.canvasGo = new operatCanvas();
    this.screenWidth = document.body.clientWidth;
    this.screenHeight = this.screenWidth*(3/5);
    //接收消息
    this.socket.on('messageAdded', function(message){
    if(that.dom){
    that.canvasGo.drawCanvas(message.parameter,message.opt,message.Start);
    }else{
    that.messages.push(message);
    }
    });
    //页面大小改变
    window.onresize = function(){
    that.screenWidth = document.body.clientWidth;
    that.screenHeight = that.screenWidth*(3/5);
    }
    },
    methods:{
    back(){
    this.$router.go(-1);
    },
    updateMessage: function () {
    this.$nextTick(function () {//当值变化dom更新完成
    this.dom = true;
    if(this.messages.length>0){
    for(let i=0; i<this.messages.length; i++){
    this.canvasGo.drawCanvas(message[i].parameter,message[i].opt,message[i].Start);
    }
    }
    })
    },
    send:function(message){
    //发送消息
    this.socket.emit('createMessage',message);
    },
    touchStart:function(event){
    let that = this;
    this.canvasGo.handleStart(event,function(message){
    that.send(message);
    });
    },
    touchMove:function(event){
    let that = this;
    this.canvasGo.handleMove(event,function(message){
    that.send(message);
    });
    },
    touchCancel:function(event){
    this.canvasGo.handleCancel(event);
    },
    touchEnd:function(event){
    let that = this;
    this.canvasGo.handleEnd(event,function(message){
    that.send(message);
    });
    }
    },
    watch:{
         screenHeight:'updateMessage'//当值变化时触发
      }
    }

    //获取坐标点与颜色画笔类型
    function operatCanvas(){
    var gameCanvas = document.getElementById("gameCanvas");
    var ctx=gameCanvas.getContext("2d");
    var touchAggregate = new Array();
    var that = this;
    var _default = {
    color: '#333', //画笔颜色
    lineWidth: 3, //画笔大小
    lineCap: 'round', //绘制圆形的结束线帽 ,可选值:square
    lineJoin: 'round' //当两条线条交汇时,创建圆形边角
    };
    var ongoingTouchIndexById = function(idToFind){
    for (let i=0; i<touchAggregate.length; i++) {
    let id = touchAggregate[i].identifier;

    if (id == idToFind) {
    return i;
    }
    }
    return -1; // not found
    }
    this.handleStart = function(event,callback){
    event.preventDefault();
    var touches = event.changedTouches;//获取正在发生此事件的
    var Start = true;
    for(let i=0; i<touches.length; i++){
    touchAggregate.push(touches[i]);
    let opt = {
    x:touches[i].pageX,
    y:touches[i].pageY
    }
    that.drawCanvas(_default,opt,Start);
    that.back(_default,opt,Start,callback);
    }
    };
    this.handleMove = function(event,callback){
    event.preventDefault();
    var touches = event.changedTouches;//获取正在发生此事件的
    for(let i=0; i<touches.length; i++){
    let idx = ongoingTouchIndexById(touches[i].identifier);
    let opt = {
    x:touches[i].pageX,
    y:touches[i].pageY,
    sx:touchAggregate[idx].pageX,
    sy:touchAggregate[idx].pageY
    }
    that.drawCanvas(_default,opt);
    touchAggregate.splice(idx, 1, touches[i]);
    that.back(_default,opt,false,callback);
    }
    };
    this.handleEnd = function(event,callback){
    event.preventDefault();
    var touches = event.changedTouches;
    for (let i=0; i<touches.length; i++) {
    let idx = ongoingTouchIndexById(touches[i].identifier);
    let opt = {
    x:touches[i].pageX,
    y:touches[i].pageY,
    sx:touchAggregate[idx].pageX,
    sy:touchAggregate[idx].pageY
    }
    that.drawCanvas(_default,opt);
    touchAggregate.splice(i, 1); // remove it; we're done
    that.back(_default,opt,false,callback);
    }
    };

    this.handleCancel = function(event) {
    evt.preventDefault();
    var touches = evt.changedTouches;

    for (let i=0; i<touches.length; i++) {
    touchAggregate.splice(i, 1); // remove it; we're done
    }
    }
    this.drawCanvas = function(_default,opt,Start){
    ctx.lineWidth = _default.lineWidth;
    ctx.strokeStyle = _default.color;
    ctx.lineCap = _default.lineCap;
    ctx.lineJoin = _default.lineJoin;
    if(Start){
    ctx.beginPath();
    ctx.moveTo(opt.x-1, opt.y-69);
    ctx.lineTo(opt.x, opt.y-68);
    ctx.closePath();
    ctx.stroke();
    }else{
    ctx.beginPath();
    ctx.moveTo(opt.sx, opt.sy-68);
    ctx.lineTo(opt.x, opt.y-68);
    ctx.closePath();
    ctx.stroke();
    }
    }
    this.back = function(_default,opt,Start,callback){
    var message = {
    parameter: _default,
    opt: opt,
    Start: Start
    };
    callback(message);
    }
    }
    </script>

    <style lang="less" scoped>
    @bg-default:#cd3d3d;
    @color-default:#cd3d3d;
    @text-color:#f67575;
    .gameRoom-canvas{
    position: absolute;
    top: 44px;
    left: 0;
    100%;
    background: #fff;
    z-index: 99;
    .canvas-bar{
    color: #fff;
    background: #999;
    font-size: 12px;
    padding: 2px 10px;
    line-height: 20px;
    overflow: hidden;
    >span:last-child{
    float: right;
    color: #f5ef3c;
    }
    }
    #gameCanvas{
    background: #fff;
    display: block;
    }
    }
    #app{
    .mui-bar.mui-bar-nav{
    box-shadow: none;
    .Hui-icon-left{
    font-size: 34px;
    padding: 5px 0;
    margin: 0;
    position: absolute;
    top: 0;
    left: 0;
    }
    .Hui-icon-right{
    display: block;
    color: #fff;
    position: absolute;
    top: 0;
    right: 10px;
    padding: 5px 0;
    font-size: 26px;
    line-height: 34px;
    }
    .Hui-title{
    line-height: 20px;
    >p{
    font-size: 16px;
    line-height: 22px;
    padding-top: 5px;
    color: #fff;
    }
    >i{
    display: block;
    font-size: 12px;
    font-weight: 400;
    line-height: 14px;
    }
    }
    }
    .Hui-chat-bar{
    background: #fffcfc;
    border: none;
    box-shadow: none;
    border-top: #E8E8E8 1px solid;
    box-sizing: content-box;
    z-index: 9998;
    .mui-icon{
    color: #666;
    }
    i.Hui-icon-face{
    background: url(../../assets/images/icon2.png) no-repeat center;
    background-size: 100%;
    }
    }
    }
    .sentNews{
    display: flex;
    overflow: hidden;
    align-items:flex-end;
    height: 50px;
    >div{
    flex-grow: 1;
    line-height: 18px;
    padding: 8px 3px 2px 3px;
    font-size: 14px;
    word-break:break-all;
    word-wrap:break-word;
    margin-bottom: 12px;
    border-bottom: #ddd 1px solid;
    }
    >a{
    padding: 0 5px;
    height: 50px;
    flex-grow: 0;
    flex-shrink: 0;
    >i.mui-icon{
    font-size: 30px;
    padding-top: 10px;
    padding-bottom: 5px;
    vertical-align: bottom;
    }
    >i.Hui-icon{
    30px;
    height: 30px;
    background-size: 24px;
    margin-top: 10px;
    }
    }
    >a:nth-of-type(2){
    padding-right: 0;
    }
    >a:last-child{
    padding-right: 10px;
    }
    }
    #chat-scroll{
    background: #F5F5F5;
    }
    .Hui-chat-scroll{
    position: fixed;
    top: 400px;
    bottom: 61px;
    padding: 0 !important;
    z-index: 10;
    left: 0;
    100%;
    overflow-x: hidden;
    overflow-y: auto;
    }
    </style> 
    现在开启多个页面,就可以同步画布,剩下的很多东西,慢慢完善。


    ————————————————
    版权声明:本文为CSDN博主「点点悠悠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/huaxiongbiao/article/details/70173853

  • 相关阅读:
    Oracle 11g SQL Fundamentals Training Introduction02
    Chapter 05Reporting Aggregated data Using the Group Functions 01
    Chapter 01Restriicting Data Using The SQL SELECT Statemnt01
    Oracle 11g SQL Fundamentals Training Introduction01
    Chapter 04Using Conversion Functions and Conditional ExpressionsConditional Expressions
    Unix时代的开创者Ken Thompson (zz.is2120.bg57iv3)
    我心目中计算机软件科学最小必读书目 (zz.is2120)
    北京将评估分时分区单双号限行 推进错时上下班 (zz)
    佳能G系列领军相机G1X
    选购单反相机的新建议——心民谈宾得K5(转)
  • 原文地址:https://www.cnblogs.com/javalinux/p/14768937.html
Copyright © 2011-2022 走看看