文章出處

  這周有點迷茫,不知道干嘛了,一天天就過去了!我在博客右側公告欄加了qq交流,各位有好的主題,或者有趣的技術,歡迎交流!今天突發奇想,就寫了2個h5 canvas的demo玩玩!

demo一:刮刮樂

  舍不得買2塊錢的刮刮樂,就只能寫個類似的功能過過彩票癮了!

布局

<div id="lottery" style="width:300px;height:500px;margin:10px;background-color:lightskyblue;border-radius:5px;float:left;">
         <div style="width:300px;height:100px;line-height:100px;text-align:center;font-size:33px;color:blueviolet;">NICK彩票</div>
         <div id="txt" style="width:300px;height:200px;font-size:40px;color:peachpuff;display:flex;justify-content:center;align-items:center;flex-direction:column;">
             <span></span>
             <span></span>
             <span></span>
             <span></span>
         </div>
         <div id="canvasArea" style="width:300px;height:200px;position:relative;">
             <div style="width:300px;height:200px;position:absolute;top:0;left:0;z-index:1;text-align:center;line-height:200px;font-weight:bold;font-size:56px;color:indianred;">一等獎</div>
             <canvas id="canvas" width="300px" height="200px" style="position:absolute;top:0;left:0;z-index:2;"></canvas>
         </div>
     </div>

這段html要注意的地方有2個:

  1. flex布局,將‘祝君中獎’垂直居中,目前還有兼容問題,不過看我們大前端的發展趨勢,應該很快就能搞定了;
  2. canvas和‘一等獎’div的z-index問題,將canvas的z-index設置較高,使其置于一等獎div上面。

設置canvas畫布

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

繪制刮獎區域

        context.fillStyle='#A9AB9D';
        context.fillRect(10,10,280,180);
        context.fillStyle='#000';
        context.font='50px Arial';
        context.fillText('刮獎區',75,115);
  1. 填充顏色;
  2. 繪制實心矩形;
  3. 設置字體顏色;
  4. 設置字體大小類型;
  5. 繪制實心字體。

以上都是canvas基礎api,看w3c就ok了。

為了好看,我將‘祝君中獎’加個字體變色

        setInterval(function(){
            document.getElementById('txt').style.color = document.getElementById('txt').style.color=='peachpuff' ? 'yellow' : 'peachpuff';
        },500);

刮獎功能函數

        var brush=function(){//刮獎
            context.clearRect(event.offsetX,event.offsetY,20,20);
        };

為canvas元素onmousedown和onmouseup事件

        canvas.onmousedown = function(){
            // 鼠標按下時 - 綁定鼠標跟隨事件
            bindHandler(canvas,'mousemove',brush,false);
        }
        canvas.onmouseup = function(){
            // 停止刮獎功能 - 解綁鼠標跟隨事件
            removeHandler(canvas,"mousemove",brush,false);
        }

這里的事件綁定與解綁我上篇博文有封裝,最后完整代碼也有!

刮刮樂happy到底結束!最后附上完整代碼,再看看效果吧!

demo二:畫筆

布局

     <div style="width:300px;height:500px;margin:10px;border-radius:10px;overflow:hidden;float:right;">
         <canvas id="canvas2" width="300px" height="500px" style="background-color:lightblue;"></canvas>
     </div>

設置canvas畫布

        var canvas2 = document.getElementById("canvas2");
        var context2 = canvas2.getContext("2d");

畫筆功能函數

        var draw=function(){
            context2.fillRect(event.offsetX,event.offsetY,10,10);
        };

為canvas元素onmousedown和onmouseup事件

        context2.font='20px Arial';
        context2.strokeText('NICK畫筆',100,30);//寫個頭
        //1. 為canvas元素onmousedown和onmouseup事件
        canvas2.onmousedown = function(){
            // 啟用畫筆功能 - 綁定鼠標跟隨事件
            bindHandler(canvas2,'mousemove',draw,false);
        }
        canvas2.onmouseup = function(){
            // 停止畫筆功能 - 解綁鼠標跟隨事件
            removeHandler(canvas2,"mousemove",draw,false);
        }

畫圖工具的畫筆功能到底結束!

多謝各位老司機的鞭策與提醒,說畫筆功能有不連續的現象!

現已改良,并兼容了移動端!

//改良后的寫法
    var isTouch = "ontouchstart" in window ? true : false;
    var StartDraw = isTouch ? "touchstart" : "mousedown",
            MoveDraw = isTouch ? "touchmove" : "mousemove",
            EndDraw = isTouch ? "touchend" : "mouseup";

    context2.strokeStyle='blue';//線色
    context2.lineCap = "round";//連接處為圓形
    context2.lineWidth =10;//線框

    canvas2.addEventListener(StartDraw, function(ev){
        ev.preventDefault();
        var isX = isTouch ? ev.targetTouches[0].pageX : ev.pageX;
        var isY = isTouch ? ev.targetTouches[0].pageY : ev.pageY;
        var x = isX - canvas2.offsetLeft;
        var y = isY - canvas2.offsetTop;
        context2.beginPath();
        context2.moveTo(x, y);
        function StartMove(ev){
            var isX1 = isTouch ? ev.targetTouches[0].pageX : ev.pageX;
            var isY1 = isTouch ? ev.targetTouches[0].pageY : ev.pageY;
            var x1 = isX1 - canvas2.offsetLeft;
            var y1 = isY1 - canvas2.offsetTop;
            context2.lineTo(x1, y1);

            context2.stroke();
            context2.beginPath();
            context2.moveTo(x1, y1);
        };
        function EndMove(ev){
            var isX1 = isTouch ? ev.changedTouches[0].pageX : ev.pageX;
            var isY1 = isTouch ? ev.changedTouches[0].pageY : ev.pageY;
            var x1 = isX1 - canvas2.offsetLeft;
            var y1 = isY1 - canvas2.offsetTop;
            context2.lineTo(x1, y1);
            context2.stroke();
            canvas2.removeEventListener(MoveDraw, StartMove, false);
            canvas2.removeEventListener(EndDraw, EndMove, false);
        };
        canvas2.addEventListener(MoveDraw, StartMove, false);
        canvas2.addEventListener(EndDraw, EndMove, false);
    }, false);

附上完整代碼:

<!DOCTYPE html>
<html>
<head>
    <title>Canvas lottery brush nick</title>
    <meta charset="utf-8"/>
</head>
<body>
<div style="width:640px;margin:auto;">
    <!--刮刮樂-->
    <div id="lottery" style="width:300px;height:500px;margin:10px;background-color:lightskyblue;border-radius:5px;float:left;">
        <div style="width:300px;height:100px;line-height:100px;text-align:center;font-size:33px;color:blueviolet;">NICK彩票</div>
        <div id="txt" style="width:300px;height:200px;font-size:40px;color:peachpuff;display:flex;justify-content:center;align-items:center;flex-direction:column;">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </div>
        <div id="canvasArea" style="width:300px;height:200px;position:relative;">
            <div style="width:300px;height:200px;position:absolute;top:0;left:0;z-index:1;text-align:center;line-height:200px;font-weight:bold;font-size:56px;color:indianred;">一等獎</div>
            <canvas id="canvas" width="300px" height="200px" style="position:absolute;top:0;left:0;z-index:2;"></canvas>
        </div>
    </div>

    <!--畫圖工具畫筆功能-->
    <div style="width:300px;height:500px;margin:10px;border-radius:10px;overflow:hidden;float:right;">
        <canvas id="canvas2" width="300px" height="500px" style="background-color:lightblue;"></canvas>
    </div>
</div>

<div style="text-align:center;">
    <p>刮刮樂:鼠標按住不放,拖動開始刮獎!</p>
    <p>畫筆:鼠標按住不放,拖動畫畫!</p>
</div>
<script>
    //插件方法封裝區

    ;(function(){
        // 事件綁定
        window.bindHandler = (function() {
            if (window.addEventListener) {// 標準瀏覽器
                return function(elem, type, handler) {
                    // elem:節點    type:事件類型   handler:事件處理函數
                    // 最后一個參數為true:在捕獲階段調用事件處理程序;為false:在冒泡階段調用事件處理程序。注意:ie沒有這個參數
                    elem.addEventListener(type, handler, false);
                }
            } else if (window.attachEvent) {// IE瀏覽器
                return function(elem, type, handler) {
                    elem.attachEvent("on" + type, handler);
                }
            }
        }());

        // 事件解除
        window.removeHandler = (function() {
            if (window.removeEventListener) {// 標準瀏覽器
                return function(elem, type, handler) {
                    elem.removeEventListener(type, handler, false);
                }
            } else if (window.detachEvent) {// IE瀏覽器
                return function(elem, type, handler) {
                    elem.detachEvent("on" + type, handler);
                }
            }
        }());
    }());

    //命名區

    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    var canvas2 = document.getElementById("canvas2");
    var context2 = canvas2.getContext("2d");
    var brush=function(){//刮獎
        context.clearRect(event.offsetX,event.offsetY,20,20);
    };
    var draw=function(){//寫字
        context2.fillRect(event.offsetX,event.offsetY,10,10);
    };

    //功能實現區

    //刮刮樂

    // 1. 繪制刮獎區域
    context.fillStyle='#A9AB9D';
    context.fillRect(10,10,280,180);
    context.fillStyle='#000';
    context.font='50px Arial';
    context.fillText('刮獎區',75,115);
    //字體變色
    setInterval(function(){
        document.getElementById('txt').style.color = document.getElementById('txt').style.color=='peachpuff' ? 'yellow' : 'peachpuff';
    },500);
    //2. 為canvas元素onmousedown和onmouseup事件
    canvas.onmousedown = function(){
        // 鼠標按下時 - 綁定鼠標跟隨事件
        bindHandler(canvas,'mousemove',brush,false);
    }
    canvas.onmouseup = function(){
        // 停止刮獎功能 - 解綁鼠標跟隨事件
        removeHandler(canvas,"mousemove",brush,false);
    }

    //畫筆
    context2.font='20px Arial';
    context2.strokeText('NICK畫筆',100,30);//寫個頭
    //為canvas元素onmousedown和onmouseup事件
    /*
    //這是原來的寫法
    canvas2.onmousedown = function(){
        // 啟用畫筆功能 - 綁定鼠標跟隨事件
        bindHandler(canvas2,'mousemove',draw,false);
    }
    canvas2.onmouseup = function(){
        // 停止畫筆功能 - 解綁鼠標跟隨事件
        removeHandler(canvas2,"mousemove",draw,false);
    }
    */
    //改良后的寫法
    var isTouch = "ontouchstart" in window ? true : false;
    var StartDraw = isTouch ? "touchstart" : "mousedown",
            MoveDraw = isTouch ? "touchmove" : "mousemove",
            EndDraw = isTouch ? "touchend" : "mouseup";

    context2.strokeStyle='blue';//線色
    context2.lineCap = "round";//連接處為圓形
    context2.lineWidth =10;//線框

    canvas2.addEventListener(StartDraw, function(ev){
        ev.preventDefault();
        var isX = isTouch ? ev.targetTouches[0].pageX : ev.pageX;
        var isY = isTouch ? ev.targetTouches[0].pageY : ev.pageY;
        var x = isX - canvas2.offsetLeft;
        var y = isY - canvas2.offsetTop;
        context2.beginPath();
        context2.moveTo(x, y);
        function StartMove(ev){
            var isX1 = isTouch ? ev.targetTouches[0].pageX : ev.pageX;
            var isY1 = isTouch ? ev.targetTouches[0].pageY : ev.pageY;
            var x1 = isX1 - canvas2.offsetLeft;
            var y1 = isY1 - canvas2.offsetTop;
            context2.lineTo(x1, y1);

            context2.stroke();
            context2.beginPath();
            context2.moveTo(x1, y1);
        };
        function EndMove(ev){
            var isX1 = isTouch ? ev.changedTouches[0].pageX : ev.pageX;
            var isY1 = isTouch ? ev.changedTouches[0].pageY : ev.pageY;
            var x1 = isX1 - canvas2.offsetLeft;
            var y1 = isY1 - canvas2.offsetTop;
            context2.lineTo(x1, y1);
            context2.stroke();
            canvas2.removeEventListener(MoveDraw, StartMove, false);
            canvas2.removeEventListener(EndDraw, EndMove, false);
        };
        canvas2.addEventListener(MoveDraw, StartMove, false);
        canvas2.addEventListener(EndDraw, EndMove, false);
    }, false);
</script>
</body>
</html>
View Code

  代碼寫完了,我也想說點其他的:

  上面js代碼中,有不少注釋,我將其分為幾個區域:插件方法封裝區、命名區、功能實現區、刮刮樂區以及畫筆區等,我感覺這樣寫加上一些注釋,能使代碼能加簡潔,便于以后的維護!當然這只是個人觀點,歡迎各位點擊我博客右邊公告欄的qq交流交流!

最后附上:

上篇博文:事件綁定與解綁!(只是一個簡單的封裝)

來看看效果,玩玩吧!

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()