1. 程式人生 > >canvas滑鼠繪圖【新】

canvas滑鼠繪圖【新】

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>canvas滑鼠繪圖</title>
        <link rel="stylesheet" href="colpick.css" type="text/css"/>

        <style type="text/css">
            *{margin:0;padding: 0}
            .painter_win{position:absolute;top:0;bottom:0;background-color: #f2f2f2;width: 100%;font-size: 16px;}
            .painter_win>.setWH{padding: 40px;}
            canvas#box{border: 2px solid #333;box-shadow: 10px 10px 5px #9E9E9E;}
            .painter_win .setWH{background: #ccc;}
            .setWH .setCanvas{display: inline;}
            .setWH #canvas_width,.setWH #canvas_height{width: 50px;}
            .tool{overflow: hidden;display: none;}
            .setWH #submitSet{margin-left: 20px;text-decoration: none;padding: 4px 9px;
                border-radius: 7px;background: #03A9F4;color: #fff;}
            .tool ul{list-style: none;position: relative;left: 50%;margin-left: -284px;margin-top:20px;overflow: hidden;}
            .tool ul>li{float: left;width: 90px; background-color: #03A9F4;color: #fff;padding: 10px;text-align: center;margin-left: 20px;border-radius: 6px;cursor: pointer;}
            .tool ul>li:first-child{margin-left: 0;}
            .tool ul>li:hover{background-color: #607d8b;}
            .tool ul>li.reduceW{width:58px;}
            .tool .setWe{text-align: left;}
            .tool #penWeight,.tool #penColor{width: 17px;display: inline-block;color: #605454;}
            .tool #penColor{cursor: pointer;}
            .painter_win #content{width: 100%;}
            .selectStyle .clicked{background-color: #607d8b}
        </style>
    </head>
    <body>
        <div class="painter_win">
            <div class="setWH">
                <span>請輸入畫布大小:</span>
                <div class="setCanvas">
                    <input type="text" id="canvas_width" value="500"> x <input type="text"  id="canvas_height" value="300">
                </div>
                <button id="submitSet" onclick="createCanvas()">確定</button>
            </div>
            <div class="tool">
                <ul>
                    <li>
                        畫筆顏色
                        <input type="text" id="penColor" color-mark="#ff8800">
                    </li>
                    <li id="setWe">
                        畫筆粗細
                        <input type="text" id="penWeight" value="3" onclick="selectText()">
                    </li>
                    <li class="reduceW" onclick="backStep()">撤回</li>
                    <li class="reduceW" onclick="clearCanvas()">清空</li>
                    <li id="downloadImage">下載圖片</li>
                </ul>
                <ul class="selectStyle">
                    <li onclick="beLine()">直線</li>
                    <li onclick="beRect()">矩形</li>
                    <li onclick="beCircle()">圓</li>
                    <li class="clicked" onclick="bePen()" >筆</li>
                </ul>
            </div>
            <div id="content"></div>
        </div>

    </body>

    <script src="jquery-3.3.1.js"></script>
    <script src="colpick.js" type="text/javascript"></script>
    <script type="text/javascript">
        var record =[];
        $(function(){

            //下載圖片
            var downloadImage = document.getElementById('downloadImage');
            bindButtonEvent(downloadImage, "click", saveAsLocalImage);

            //設定畫筆顏色
            $("#penColor").colpick({
                layout:'rgbhex',
                color:'ff8800',
                onSubmit:function(hsb,hex,rgb,el) {
                    $(el).css('background-color', '#'+hex);
                    $(el).colpickHide();
                    $(el).attr('color-mark','#'+hex);

                }
            }).css('background-color', '#ff8800');

            $(".selectStyle li").click(function(){
                $(this).addClass('clicked');
                $(this).siblings().removeClass('clicked');
            });
        });
       

        //建立canvas畫布
        function createCanvas(){
            if(!$("#content #box")[0]){
                var width = $(".painter_win .setWH #canvas_width").val();
                var height = $(".painter_win .setWH #canvas_height").val();
                if(width || height){
                    initCanvas(width,height);
                    $(".tool").show();
                    $(".setWH").hide();
                }else{
                    alert("請輸入畫布大小");
                }
            }
            
        }

        //初始化畫布,新增滑鼠事件
        function initCanvas(width,height){
            let txt = `<canvas id="box" width="${width}" height="${height}"></canvas>`;
            $("#content").append(txt);
            $("#box").css({
                'position'   : 'relative',
                'left'       : '50%',
                'margin-left':  -width/2,
                'margin-top' : '20px'
            });

            bePen();

        }
        
        //畫筆繪圖
        function bePen(){
            var box=document.getElementById('box');
            var ctx=box.getContext('2d');
            box.onmousedown=function(e){
                record.push(box.toDataURL());
                e=e||window.event;
                var penColor = $("#penColor").attr('color-mark');
                var penWeight = $("#penWeight").val();
                ctx.strokeStyle= penColor;
                ctx.lineWidth = penWeight;
                ctx.beginPath();
                //注意這裡offset獲取到的是box相對上一個定位元素的距離,沒有則為body
                var ox=e.clientX-box.offsetLeft;
                var oy=e.clientY-box.offsetTop;
                ctx.moveTo(ox,oy);

                box.onmousemove=function(e){
                    var ox1=e.clientX-box.offsetLeft;
                    var oy1=e.clientY-box.offsetTop;
                    ctx.lineTo(ox1,oy1);
                    ctx.stroke();                    
                }
                //程式碼改進,在僅有畫筆畫圖時還是改成document.onmouseup較好。
                //因為此處若為box.onmouseup則滑鼠移出canvas鬆開監聽不到導致一直處於onmousemove狀態中
                //這裡是由於其他style(圓、矩形、線條)中只能定義成box.onmouseup,這裡要覆蓋掉不易出bug
                box.onmouseup=function(){
                    box.onmousemove=null;
                    ctx.closePath();
                }
            }
        }

        //直線繪圖
        function beLine(){
            var box=document.getElementById('box');
            var ctx=box.getContext('2d');
            box.onmousedown=function(e){
                record.push(box.toDataURL());
                e=e||window.event;
                var penColor = $("#penColor").attr('color-mark');
                var penWeight = $("#penWeight").val();
                ctx.strokeStyle= penColor;
                ctx.lineWidth = penWeight;
                ctx.beginPath();
                //注意這裡offset獲取到的是box相對上一個定位元素的距離,沒有則為body
                var ox=e.clientX-box.offsetLeft;
                var oy=e.clientY-box.offsetTop;
                ctx.moveTo(ox,oy);

                //暫時不知道該如何做出預覽的效果
                box.onmouseup=function(e){
                   var ox1=e.clientX-box.offsetLeft;
                    var oy1=e.clientY-box.offsetTop; 
                    ctx.lineTo(ox1,oy1);
                    ctx.stroke(); 
                    ctx.closePath();
                }
            }
        }

        //矩形繪圖
        function beRect(){
            var box=document.getElementById('box');
            var ctx=box.getContext('2d');
            box.onmousedown=function(e){
                record.push(box.toDataURL());
                e=e||window.event;
                var penColor = $("#penColor").attr('color-mark');
                var penWeight = $("#penWeight").val();
                ctx.strokeStyle= penColor;
                ctx.lineWidth = penWeight;
                ctx.beginPath();
                var ox=e.clientX-box.offsetLeft;
                var oy=e.clientY-box.offsetTop;


                box.onmouseup=function(e){
                    var ox1=e.clientX-box.offsetLeft;
                    var oy1=e.clientY-box.offsetTop; 
                    //這裡也可以是填充矩形,但是style就不是strokeStyle而是fillStyle
                    ctx.strokeRect(ox,oy,ox1-ox,oy1-oy);
                    ctx.closePath();
                }
            }
        }

        //圓繪圖
        function beCircle(){
            var box=document.getElementById('box');
            var ctx=box.getContext('2d');
            box.onmousedown=function(e){
                record.push(box.toDataURL());
                e=e||window.event;
                var penColor = $("#penColor").attr('color-mark');
                var penWeight = $("#penWeight").val();
                ctx.strokeStyle= penColor;
                ctx.lineWidth = penWeight;
                ctx.beginPath();
                var ox=e.clientX-box.offsetLeft;
                var oy=e.clientY-box.offsetTop;


                box.onmouseup=function(e){
                    var ox1=e.clientX-box.offsetLeft;
                    var oy1=e.clientY-box.offsetTop; 
                    ctx.arc((ox+ox1)/2,(oy+oy1)/2,(ox1-ox)/2,0,2*Math.PI);
                    ctx.stroke();
                    ctx.closePath();
                }
            }
        }

        //撤銷
        function backStep(){
            if(record.length>0){
                 //不加上下面語句會出現oc is not defined問題,暫未理解
                ctx=box.getContext('2d');
                var canvasPic = new Image();
                resetCanvas();
                canvasPic.src = record.pop();
                //一定要載入完圖片再進行繪製
                canvasPic.onload = function(){
                    ctx.drawImage(canvasPic, 0, 0);
                }
            }   
        }

        // 清空canvas畫布
        function resetCanvas(){
            //canvas每當高度或寬度被重設時,畫布內容就會被清空
            box.height = box.height;
        }

        //清空操作 把操作記錄也清空
        function clearCanvas(){
            resetCanvas();
            record = [];
        }

        //指定線型為直線


        
        //新增事件監聽 相容IE
        function bindButtonEvent(element, type, handler){
            if(element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else {
                element.attachEvent('on'+type, handler);
            }
        }
        //儲存本地
        function saveAsLocalImage () {
            var box=document.getElementById('box');
                var image = box.toDataURL("image/png").replace("image/png", "image/octet-stream"); 
                window.location.href=image; 
        }  

        //點選自動選中input內的所有文字
        function selectText(){
            //原生js物件也有此方法
            $("#penWeight").select();
        }

    </script>
</html>

結果如下圖:

 

線上檢視:http://112.74.169.251/canvas/canvas.html