H5制作簡易畫板


今天看了下h5的canves,想了下,准備用它制作一個簡易畫板:

畫板主要有兩個組件,一個畫板,一個調色板,開始調色板想使用其他插件,但引入太麻煩了,就直接用canves生成了一個;

1.畫板:

  電腦用鼠標事件(down,move,up來控制),平板/手機用相應其他的事件,這里需要做一個事件傳遞的優化,目前還沒搞;

  先給幾個模式:素描,畫圓,畫矩形,畫線段....

   切換結構如下:

  eventon=mode;

  if(mode changed){enevton=null;eventon=mode}

<div class="btn-group" data-toggle="buttons">
                        <label class="btn btn-primary glyphicon glyphicon-pencil" data-toggle="popover" title="素描">
                            <input type="radio" name="options" value='0'>
                        </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="圓"><input type="radio" name="options" value='1'>
                         </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="矩形">
                            矩形<input type="radio" name="options" value='2'>
                        </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="線段">
                            線段<input type="radio" name="options" value='3'>
                        </label>
                    </div>
View Code
$("input[name='options']").off().change((e)=>{
                let mode =$(e.target).attr('value');
                let a =context.getMode(mode);
                startmode(box,context.getMode(mode));
            });
var context={
                map:function(){
                    let map= new Map();
                    map.set('0',pencil);
                    map.set('1',drawcCircle);
                    map.set('2',drawRectangle);
                    map.set('3',drawcLine);
                    return map;
                }(),
                getMode:function(mode){
                    return this.map.get(mode);
                }
}
View Code

 

   mode結構如下:

  down觸發 move監聽 up結束

  例如素描的mode:

function pencil(box){//素描
                let cxt = box.getContext("2d");
                box.onmousedown = function(e){
                    let x = e.offsetX;
                    let y = e.offsetY;
                    box.onmousemove = function(e1){
                                cxt.beginPath();
                                cxt.moveTo(x,y);
                                x = e1.offsetX;
                                y = e1.offsetY;
                                cxt.lineTo(x,y);
                                cxt.closePath();
                                cxt.stroke();
                           }
                }
                box.onmouseup  = function(e){
                    box.onmousemove = null;
                    context.backStore(box);
                }
            }
View Code

2.調色板:

  生成一個漸變顏色條帶

function initcolor(){//調色板初始化
                //顏色初始化
                let can = document.getElementById("colorPicker");
                let ctx=can.getContext("2d");
                let colors=[
                    '#000000',
                    '#FF0000',
                    '#00FF00',
                    '#0000FF',
                    '#FFFF00',
                    '#00FFFF',
                    '#FF00FF',
                    '#C0C0C0',
                    '#FFFFFF'
                ];
                   var gradientBar = ctx.createLinearGradient(0, 0, can.width, 0);
                   for(let i=0;i<colors.length;i++){
                    gradientBar.addColorStop(i/(colors.length-1), colors[i]);
                }
                ctx.fillStyle = gradientBar;
                ctx.beginPath();
                ctx.rect(0, 0,  can.width, can.height);
                ctx.fill();
                ctx.closePath();
                ctx.restore();
                return can;
            }
View Code

 監聽選擇的顏色值.賦值給畫板的strokeStyle;

colorBox.onmousedown  = function(e){
                let x = e.offsetX;
                let y = e.offsetY;
                let imgData=colorBox.getContext("2d").getImageData(x,0,x+1,1);
                box.getContext("2d").strokeStyle ='rgb('+imgData['data'][0]+','+imgData['data'][1]+','+imgData['data'][2]+')'
            }
View Code

3.效果圖:

 

4.源碼:

<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8"> 
    <title>畫板功能</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">  
      <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
      <script src="https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <style type="text/css">
        html,body{height:100%;}
        .container{width: 80%;height: 80%;}
        .header-p{width:  100%;    height: 20%;}
        .header-body{width:  100%;height: 80%;}
        #colorPicker{height: 17px;width: max-content;}
    </style>
    <script>
        window.onload=function(){
            var  box = init();
            var  colorBox = initcolor();
            colorBox.onmousedown  = function(e){
                let x = e.offsetX;
                let y = e.offsetY;
                let imgData=colorBox.getContext("2d").getImageData(x,0,x+1,1);
                box.getContext("2d").strokeStyle ='rgb('+imgData['data'][0]+','+imgData['data'][1]+','+imgData['data'][2]+')'
            }
            $("input[name='options']").off().change((e)=>{
                let mode =$(e.target).attr('value');
                let a =context.getMode(mode);
                startmode(box,context.getMode(mode));
            });
            $("#reset").click(()=>{
                context.back_back(box);
            });
            $("#advance").click(()=>{
                context.back_advance(box);
            });
            $("#save").click(()=>{
                var a = document.createElement('a');
               a.href = box.toDataURL('image/png'); //下載圖片
               a.download = 'canvas.png';
               a.click();
            })
            function init(){//初始化
                //畫板
                var  box = document.getElementById("myCanvas");
                box.width = $(".text-center.header-body").width();
                box.height = $(".text-center.header-body").height();
                return box;
            }
            function initcolor(){//調色板初始化
                //顏色初始化
                let can = document.getElementById("colorPicker");
                let ctx=can.getContext("2d");
                let colors=[
                    '#000000',
                    '#FF0000',
                    '#00FF00',
                    '#0000FF',
                    '#FFFF00',
                    '#00FFFF',
                    '#FF00FF',
                    '#C0C0C0',
                    '#FFFFFF'
                ];
                   var gradientBar = ctx.createLinearGradient(0, 0, can.width, 0);
                   for(let i=0;i<colors.length;i++){
                    gradientBar.addColorStop(i/(colors.length-1), colors[i]);
                }
                ctx.fillStyle = gradientBar;
                ctx.beginPath();
                ctx.rect(0, 0,  can.width, can.height);
                ctx.fill();
                ctx.closePath();
                ctx.restore();
                return can;
            }
            function startmode(box,f){//模式選擇
                box.onmousedown=null;
                box.onmousemove=null;
                box.onmouseup=null;
                f(box);
            }
            var context={
                rollbackSize:20,//回滾步數20步
                bakStores:function(){
                    let stores = [];
                    let backCanvas = document.createElement('canvas');
                    let backCtx = backCanvas.getContext('2d');
                    backCanvas.width = box.width;
                    backCanvas.height = box.height;
                    backCtx.drawImage(box, 0, 0, box.width, box.height);
                    stores.push(backCanvas);
                    return stores;
                }(),//提供回滾,撤銷操作
                backflag:0,//回滾標記
                map:function(){
                    let map= new Map();
                    map.set('0',pencil);
                    map.set('1',drawcCircle);
                    map.set('2',drawRectangle);
                    map.set('3',drawcLine);
                    return map;
                }(),
                getMode:function(mode){
                    return this.map.get(mode);
                },
                backStore:function(box){//存儲
                    let backCanvas = document.createElement('canvas');
                    let backCtx = backCanvas.getContext('2d');
                    backCanvas.width = box.width;
                    backCanvas.height = box.height;
                    backCtx.drawImage(box, 0, 0, box.width, box.height);
                    this.bakStores.push(backCanvas);
                    if(this.bakStores.length>=this.rollbackSize){
                        bakStores.shift();
                    }
                    this.backflag = 0;
                },
                back_back:function(box){//后退
                    if(this.bakStores.length-this.backflag>1){
                        this.backflag++;
                        let cxt = box.getContext("2d");
                        cxt.clearRect(0, 0, box.width, box.height);
                        cxt.drawImage(this.bakStores[this.bakStores.length-this.backflag-1], 0, 0, box.width, box.height);
                        cxt.stroke();
                    }
                    
                },
                back_advance:function(box){//前進
                    if(this.bakStores.length-this.backflag>0&&this.backflag>0){
                        this.backflag --;
                        let cxt = box.getContext("2d");
                        cxt.clearRect(0, 0, box.width, box.height);
                        cxt.drawImage(this.bakStores[this.bakStores.length-this.backflag-1], 0, 0, box.width, box.height);
                        cxt.stroke();
                    }
                }
            }
            function pencil(box){//素描
                let cxt = box.getContext("2d");
                box.onmousedown = function(e){
                    let x = e.offsetX;
                    let y = e.offsetY;
                    box.onmousemove = function(e1){
                                cxt.beginPath();
                                cxt.moveTo(x,y);
                                x = e1.offsetX;
                                y = e1.offsetY;
                                cxt.lineTo(x,y);
                                cxt.closePath();
                                cxt.stroke();
                           }
                }
                box.onmouseup  = function(e){
                    box.onmousemove = null;
                    context.backStore(box);
                }
            }
            function drawcLine(box){//線段
                let cxt = box.getContext("2d");
                box.onmousedown = function(e){
                    //緩存起始點圖像,移動時不斷加載刷新
                    let backCanvas = document.createElement('canvas');
                    let backCtx = backCanvas.getContext('2d');
                    backCanvas.width = box.width;
                    backCanvas.height = box.height;
                    backCtx.drawImage(box, 0, 0, box.width, box.height);
                    let x = e.offsetX;
                    let y = e.offsetY;
                    box.onmousemove = function(e1){
                                let x1 = e1.offsetX;
                                let y1 = e1.offsetY;
                                cxt.clearRect(0, 0, box.width, box.height);
                                cxt.drawImage(backCanvas, 0, 0, box.width, box.height);
                                cxt.beginPath();
                                cxt.moveTo(x,y);
                                cxt.lineTo(x1,y1);
                                cxt.closePath();
                                cxt.stroke();
                           }

                }
                box.onmouseup = function(e){
                    box.onmousemove = null;
                    context.backStore(box);
                }
            }
            function drawcCircle(box){//畫圓
                let cxt = box.getContext("2d");
                box.onmousedown = function(e){
                    //緩存起始點圖像,移動時不斷加載刷新
                    let backCanvas = document.createElement('canvas');
                    let backCtx = backCanvas.getContext('2d');
                    backCanvas.width = box.width;
                    backCanvas.height = box.height;
                    backCtx.drawImage(box, 0, 0, box.width, box.height);
                    let x = e.offsetX;
                    let y = e.offsetY;
                    box.onmousemove = function(e1){
                                let x1 = e1.offsetX;
                                let y1 = e1.offsetY;
                                let distance=Math.sqrt(Math.pow(Math.abs(x - x1),2)+Math.pow(Math.abs(y - y1),2));
                                cxt.clearRect(0, 0, box.width, box.height);
                                cxt.drawImage(backCanvas, 0, 0, box.width, box.height);
                                cxt.beginPath();
                                cxt.arc(x+(x1-x)/2,y+(y1-y)/2,distance/2,0,2*Math.PI);
                                cxt.stroke();
                           }

                }
                box.onmouseup = function(e){
                    box.onmousemove = null;
                    context.backStore(box);
                }
            }
            function drawRectangle(box){//畫矩形
                let cxt = box.getContext("2d");
                //與畫圓原理相同,同上
                box.onmousedown = function(e){
                    let backCanvas = document.createElement('canvas');
                    let backCtx = backCanvas.getContext('2d');
                    backCanvas.width = box.width;
                    backCanvas.height = box.height;
                    backCtx.drawImage(box, 0, 0, box.width, box.height);
                    let x = e.offsetX;
                    let y = e.offsetY;
                    box.onmousemove = function(e1){
                                cxt.clearRect(0, 0, box.width, box.height);
                                cxt.drawImage(backCanvas, 0, 0, box.width, box.height);
                                cxt.beginPath();
                                cxt.rect(x,y,e1.offsetX - x,e1.offsetY - y);
                                cxt.stroke();
                           }
                }
                box.onmouseup  = function(e){
                    box.onmousemove = null;
                    context.backStore(box);
                }
            }
        }
        
        
    </script>
</head>
 
<body>
    <div class="container">
        <p class="text-center header-p">
            <table class="table">
              <thead>
                <tr>
                  <th width="20%">
                      <div class="btn-group" data-toggle="buttons">
                        <label class="btn btn-primary glyphicon glyphicon-pencil" data-toggle="popover" title="素描">
                            <input type="radio" name="options" value='0'>
                        </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="圓"><input type="radio" name="options" value='1'>
                         </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="矩形">
                            矩形<input type="radio" name="options" value='2'>
                        </label>
                        <label class="btn btn-primary glyphicon" data-toggle="popover" title="線段">
                            線段<input type="radio" name="options" value='3'>
                        </label>
                    </div>
                  </th>
                  <th width="40%">
                      <div class="btn-group">
                          <label class="btn btn-primary glyphicon">調色板:</label>
                          <label class="btn btn-primary glyphicon">
                              <canvas id="colorPicker"></canvas>
                          </label>
                    </div>
                  </th>
                  <th width="20%" style="text-align: right">
                      <div class="btn-group">
                          <button class="btn btn-primary glyphicon"  type="button" id ="reset">
                              撤銷<span class='glyphicon-chevron-left'></span>
                          </button>
                          <button class="btn btn-primary glyphicon"  type="button" id ="advance">
                              恢復<span class='glyphicon-chevron-right'></span>
                          </button>
                          <button class="btn btn-primary glyphicon"  type="button" id ="save">
                              保存
                          </button>
                    </div>
                  </th>
                </tr>
              </thead>
            </table>
        </p>
        <p class="text-center header-body">
            <canvas id="myCanvas" style="border:1px solid #c3c3c3;">
                Your browser does not support the canvas element.
            </canvas>
        </p>
    </div>
</body>
 
</html>
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM