【js案例】使用js制作写字画布

11人阅读 评论(0) 收藏 举报
分类:

canvas实现画板功能

需求分析 
1.具有基本的铅笔功能 
2.即时直线绘制 
3.即时绘制矩形 
4.即时圆形 
5.即时橡皮擦 
7.插入图片 
8.把画板保存为图片并下载 //此处还没做好,画板底色是黑色的 
9.选择颜色 
10.选择线条粗细

Setp1:构建网页基本样式

html代码

    <!--可选操作-->
    <div id="select">
        <button id="pen">铅笔</button>
        <button id="line">直线</button>
        <button id="rect">矩形</button>
        <button id="arc">圆形</button>
        <button id="robber">橡皮檫</button>
        <button id="img">图片</button>
        <button id="save">保存</button>
        <input type="file" id="file" name="img" style="display: none"/>
        <input type="color" id="color"/>
        <input type="number" id="lineWidth"/>
    </div>

    <!--画板-->
    <canvas id="penal" width="800" height="800"></canvas>

css代码

    /*只有一句,用来初始化画板颜色*/
    #penal {
        width: 800px;
        height: 800px;
        background-color: #ccc;
    }

Step2:构造实现画板各个功能的js代码

1.构造Draw()类,并初始化必要的参数

    var Draw = function(){
        this.type = 'pen';  //选项类型,默认为铅笔
        this.penal = document.getElementById('penal');
        this.pen = this.penal.getContext('2d');
        this.isDraw = false;    //绘画开关
        this.color = document.getElementById('color');
        this.lineWidth = document.getElementById('lineWidth');
        this.select = document.getElementById('select');    //选择面板
        this.img = new Image();//用于动态绘制直线,矩形,圆形
    };

2.这里只需要构造一个初始化函数init()

初始化函数内部需要用到的变量

    Draw.prototype.init = function(){
        var self = this;
        var originX = null;
        var originY = null;
    }

先绑定选择操作

    this.select.addEventListener('click',function(event){
        if(event.target.id == 'pen'){
            self.type = 'pen';
        }else if(event.target.id == 'line'){
            self.type = 'line';
        }else if(event.target.id == 'rect'){
            self.type = 'rect';
        }else if(event.target.id == 'arc'){
            self.type = 'arc';
        }else if(event.target.id == 'robber'){
            self.type = 'robber';
        }else if(event.target.id == 'img'){
            document.getElementById('file').click();    //默认触发选择文件操作
            document.getElementById('file').onchange = function(e){
                var reader = new FileReader();          //这是H5新增加的读取文件函数
                reader.readAsDataURL(e.target.files[0]);
                reader.onload = function(ent){          //文件读取完毕后触发操作
                    var img = new Image();
                    img.src = ent.target.result;        //读取的结果默认存放在result上
                    self.pen.drawImage(img,0,0);        //把图片直接画在画布上
                }
            }
        }
        else if(event.target.id == 'save'){
            var a = document.createElement('a');
            a.href = self.penal.toDataURL('image/png');     //把画布转化为base64
            a.download = 'image.jpeg';
            a.id = 'download';
            a.innerHTML = 'download';
            document.body.appendChild(a);
            document.getElementById('download').style.display = 'none';
            document.getElementById('download').click();    //默认出发下载操作

        }
    },false);

可以知道当绘画时,mousedown事件触发时,需要把this.isDraw = true,同时记录鼠标所在坐标,获取选择的colorlinewidth,并开启绘画路径

    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;
        originX = event.clientX - self.penal.offsetLeft;    //原点x坐标
        originY = event.clientY - self.penal.offsetTop;     //原点y坐标
        self.pen.moveTo(originX, originY);
        self.pen.strokeStyle = self.color.value;
        self.pen.lineWidth = self.lineWidth.value;
        self.pen.beginPath();

    },false);

然后当触发mouseup事件时,可知需要结束绘画,若鼠标离开画布,即mouseleave时,也需要结束绘画,这部分很简单只需把this.isDraw = false和关闭绘画路径

    this.penal.addEventListener('mouseleave', function () {
        if(self.isDraw){
            self.pen.closePath();
            self.isDraw = false;
        }
    },false);
    this.penal.addEventListener('mouseup', function (event) {
        if(self.isDraw){
            self.pen.closePath();
            self.isDraw = false;
        }
    },false);

接下来就是最难的部分的,当mouseover时,需要即时绘制 
先实现铅笔功能

    this.penal.addEventListener('mousemove',function(event){
        //只有可绘画时才可画
        if(self.isDraw){
            var x = event.clientX - self.penal.offsetLeft;  //移动过程中的x坐标
            var y = event.clientY - self.penal.offsetTop;   //移动过程中的y坐标

            if(self.type == 'pen'){
                self.pen.lineTo(x,y);
                self.pen.stroke();
            }
        }
    },false);

接下来实现橡皮擦功能,实现方法是把绘画线条加粗,并颜色默认选择画布底色

    if(self.type == 'robber'){
         self.pen.strokeStyle = '#ccc';
         self.pen.clearRect(x-10,y-10,20,20);
    }

接下来实现绘制直线,矩形和圆形的方法其实大同小异,然后为了能让我们画矩形和圆形能在所有方向都能画,我们增加了newOriginXnewOriginY两个变量

    var newOriginX  = originX,newOriginY = originY;

    if(self.type == 'line'){
        self.pen.moveTo(originX,originY);
        self.pen.lineTo(x,y);
        self.pen.stroke();

    }else if(self.type == 'rect'){
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        self.pen.rect(newOriginX,newOriginY,Math.abs(x-originX),Math.abs(y-originY));
        self.pen.stroke();
    }else if(self.type == 'arc'){
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        var r = Math.sqrt(Math.abs(x-originX) * Math.abs(x-originX) + Math.abs(y-originY) * Math.abs(y-originY))
        self.pen.arc(Math.abs(x-originX)+newOriginX, Math.abs(y-originY)+newOriginY , r, 0, 2*Math.PI);
        self.pen.fillStyle = self.color.value;
        self.pen.fill();
    }

question:此时我们发现画的直线,矩形和圆形都会在画的时候留下移动的痕迹,这不是我们希望的结果,所以解决方法是: 
mousedown时,把当前画布内容保存为图片,并用初始化时一直没有使用过的this.img来保存,然后每次画直线等的时候先把画布全部清空,然后在把this.img画到画布上 
把原来的mousedown事件添加一句代码

    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;

        //增加一句代码
        self.img.src = self.penal.toDataURL('image/png');

        originX = event.clientX - self.penal.offsetLeft;    //原点x坐标
        originY = event.clientY - self.penal.offsetTop;     //原点y坐标
        self.pen.moveTo(originX, originY);
        self.pen.strokeStyle = self.color.value;
        self.pen.lineWidth = self.lineWidth.value;
        self.pen.beginPath();

    },false);

mouseover事件的代码稍作更改

    if(self.type == 'line'){

        self.pen.clearRect(0,0,800,800);//增加代码
        self.pen.drawImage(self.img, 0, 0);//增加代码
        self.pen.beginPath();//增加代码

        self.pen.moveTo(originX,originY);
        self.pen.lineTo(x,y);
        self.pen.stroke();

        self.pen.closePath();//增加代码
    }else if(self.type == 'rect'){
        self.pen.clearRect(0,0,800,800);//增加代码
        self.pen.drawImage(self.img, 0, 0);//增加代码
        self.pen.beginPath();//增加代码

        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        self.pen.rect(newOriginX,newOriginY,Math.abs(x-originX),Math.abs(y-originY));
        self.pen.stroke();

        self.pen.closePath();//增加代码
    }else if(self.type == 'arc'){
        self.pen.clearRect(0,0,800,800);//增加代码
        self.pen.drawImage(self.img, 0, 0);//增加代码
        self.pen.beginPath();//增加代码

        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        var r = Math.sqrt(Math.abs(x-originX) * Math.abs(x-originX) + Math.abs(y-originY) * Math.abs(y-originY))
        self.pen.arc(Math.abs(x-originX)+newOriginX, Math.abs(y-originY)+newOriginY , r, 0, 2*Math.PI);
        self.pen.fillStyle = self.color.value;
        self.pen.fill();
        self.pen.closePath();//增加代码
    }

Step3:加载js文件

    <script src="draw.js"></script>
    <script>
        window.onload = function (){
            var draw = new Draw();
            draw.init();
        };
    </script>

最后简单的画板功能就是实现了,如有不足之处请指出 
demo地址:https://github.com/1364137942/canvas-draw-panel


转自: https://blog.csdn.net/ali1995/article/details/52734253



查看评论

h5 canvas  在canvas上画图 在canvas上写字 文字换行

//canvas文字换行 function write_text_other_line_auto(ctx,font,align,color,text,x,y,line_count,li...
  • sinat_29843547
  • sinat_29843547
  • 2015-09-24 09:43:12
  • 4387

Html5 canvas 简单画布画板涂鸦例子

简单的Html5 画板例子,巧妙的使用onmousemove 事件来实现画画, 可以
  • tuposky
  • tuposky
  • 2014-11-04 22:54:53
  • 4048

像素显字的小实例(使用canvas)

学习canvas的第二天,依然先不总结,简单的把用到的知识点说一下1、绘制文本:fillText(),这个方法接收四个参数:要绘制的文本字符串,x坐标,y坐标和可选的最大像素宽度(尚未得到所有浏览器的...
  • lhjuejiang
  • lhjuejiang
  • 2018-03-28 18:50:52
  • 37

JavaScript之Canvas画布

HTML5有个强大的功能,就是利用canvas进行画图。
  • h15882065951
  • h15882065951
  • 2017-04-18 23:10:18
  • 3911

关于HTML5的画布canvas

关于HTML5的画布canvas,实现的效果有:几何形状,直线,文本,渐变 效果。
  • u012311697
  • u012311697
  • 2015-03-27 00:48:56
  • 497

用js+html5画布功能做转盘

首先 设置一个宽500px,高500px的画布: canvas id="cvs" width="500" height="500">canvas> 对其样式进行简单的设置,以便于我们的观察...
  • fionafung58
  • fionafung58
  • 2015-11-15 21:22:58
  • 724

JavaScript中使用画布实现笑脸火柴人

在这之前,根本不知道JavaScript具体到底有多重要,现在才明白JavaScript也很强大,从网上看了几个js写的网页小游戏,我都惊呆了,以后一定要好好学习js。。。。 functi...
  • wojiaohuangyu
  • wojiaohuangyu
  • 2015-07-29 19:30:08
  • 1514

利用canvas实现田字格里写字,并适配移动端

结构: html> charset="UTF-8"> 我们一起学写字 type="text/javascript" src="js/jquery.js"> ty...
  • TomcatLOVEMysql
  • TomcatLOVEMysql
  • 2016-04-14 08:51:00
  • 1386

10分钟,利用canvas画一个小的loading界面(顺便讨论下绘制效率问题)

首先利用定义下canvas得样式 你的游览器不支持canvas  这里主要要说的就是宽高,不要在style里面定义,不然会被拉伸。(对于这点,建议大家看下W3c文档,不是很懂) 高度和宽...
  • qazwsx2345
  • qazwsx2345
  • 2014-07-15 12:19:52
  • 1313
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 7万+
    积分: 3184
    排名: 1万+
    博客专栏