HTML5基于canvas的网页绘画系统

绘画是一种在平面上以手工方式临摹自然或非自然,以其达到二维(平面或三维)效果的艺术,在中世纪的欧洲,常把绘画称作“猴子的艺术”,因为如同猴子喜欢模仿人类活动一样,绘画也是模仿场景。 《汉书·赵充国传》:“乃召黄门郎 扬雄 即 充国 图画而颂之。” 五代齐己 《题画鹭鸶兼简孙郎中》诗:“曾向沧江看不真,却因图画见精神。”鲁迅 《集外集·编校后记二》:“因为图画是人类共通的语言,很难由第三者从中作梗的。”
绘画,不仅仅是一种描绘事物的的工具,也是大家寄托情感,修身养性的方式之一。从前绘画的工具大部分是画笔和颜料,在实体纸张上通过不同画笔和颜料的选择,描绘出自己想要的的效果,随着科技的发展,出现了许许多多的绘图软件帮助我们更好的去绘画,更加方便和简洁,单一个ctrl+z,就比得过无数橡皮和辛劳的日日夜夜。电脑软件现在越来越全面了,很多事情都不需要人工去做。
用电脑绘图画更精致,比起手绘,绘图软件在精致方面可谓是无敌,因为他的准确性,可以完美地画出一张不差毫厘的图。而且电脑绘图比手绘更易入门 ,你可能不会手绘,但你也能用绘图软件做出一张图。因为软件中给你提供了千千万万的素材,而手绘是,会就会,不会就不会。尽管现在越来越多的人使用电脑绘图,但是真正好的设计师依然对手绘有着比较高的要求,清华大学建筑系教授奚树祥曾就公开表示:从几十年经验看,手绘画得好的,设计也往往做得好。

本次课程设计基于html5的canvas制作了一个自定义的网页绘画系统,有不同的笔刷设置和颜色选择,也可以对图片进行操作。

一、相关背景

Canvas是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
​它最初由苹果内部使用自己MacOS X WebKit推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。 后来,有人通过Gecko内核的浏览器 (尤其是Mozilla和Firefox),Opera和Chrome和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。
​Canvas是由HTML代码配合高度和宽度属性而定义出的可绘制区域。JavaScript代码可以访问该区域,类似于其他通用的二维API,通过一套完整的绘图函数来动态生成图形。Mozilla 程序从 Gecko 1.8 (Firefox 1.5)开始支持 , Internet Explorer 从IE9开始 。Chrome和Opera 9+ 也支持 。
以前在网页中进行交互绘图是很困难的(需要依赖额外的第三方插件),而引入的Canvas特性使得作者可以很容易的在网页上绘制各种图形和图像。
Canvas提供了脚本(JavaScript)应用接口,我们可以使用JS代码来操作画布,添加各种图形以及实现用户交互。这些特性使得HTML5在开发网页游戏和一些复杂的网页动画上变得更加方便。

二、创作思路

既然是绘画系统,那么绘画的基本功能自然是少不了的,简单总结了一下绘图软件的基本功能,自定义绘画系统的基本框架如下图:
在这里插入图片描述

三、创作流程

(1)创建画板容器。

    <meta charset="UTF-8">
    <meta id="viewport" name="viewport" content="width=540,user-scalable=no,target-densitydpi=high-dpi">
    <title>创意画板</title>

(2)不同画笔类型实现

  function repaint(paint) {
 
 
                for (var i = 0; i < shapeArray.length; i++) {
 
                    if (shapeArray[i].shape == '矩形') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
 
                        Draw.rect(can, Da.p, Da.p1, Da.fill, Da.stroke, Da.linew, Da.du, 1, 1, Da.apl, Da.shadow);
                        paint.rect(Da.p.x, Da.p.y, Da.p1.x, Da.p1.y);
                        if (paint.isPointInPath(tcx, tcy)) {
                            if (tczkg) {
 
                                shapeArray[i].fill = D.fill;
                                shapeArray[i].stroke = D.stroke;
                                shapeArray[i].du = rotatez;
                                shapeArray[i].linew= D.linew;
                            }
 
                        }
                        ;
 
                    }
                    if (shapeArray[i].shape == '文字') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.word(can, true, Da.stroke, Da.text, Da.p.x, Da.p.y + Da.p1.y, Da.p1.y, Da.kind, Da.alg, Da.fill);
 
                    }
 
                    if (shapeArray[i].shape == '圆形') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.crl(can, Da.linew, Da.stroke, Da.fill, Da.p, Da.r, 0, 360, false, Da.apl, Da.shadow);
                        paint.arc(Da.p.x, Da.p.y, Da.r, 0, 360, false);
                        if (paint.isPointInPath(tcx, tcy)) {
                            if (tczkg) {
 
                                shapeArray[i].fill = D.fill;
                                shapeArray[i].stroke = D.stroke;
                                shapeArray[i].du = rotatez;
                                shapeArray[i].linew= D.linew;
 
                            }
 
                        }
                        ;
 
                    }
 
                    if (shapeArray[i].shape == '多边形') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.nGon(can, Da.p.x, Da.p.y, Da.n, Da.r, Da.du, Da.linew, Da.fill, Da.stroke, Da.apl, Da.shadow,tcx,tcy,function(){
                            if(tczkg){
                                shapeArray[i].fill = D.fill;
                                shapeArray[i].stroke = D.stroke;
                                shapeArray[i].du = rotatez;
                                shapeArray[i].linew= D.linew;
 
                            }
 
                        });
                        paint.closePath();
 
                    }
 
                    if (shapeArray[i].shape == '多角形') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.nStar(can, Da.p.x, Da.p.y, Da.n, Da.r, Da.fill, Da.stroke, Da.linew, Da.du, Da.apl, Da.shadow,tcx,tcy,function(){
                            if(tczkg){
                                shapeArray[i].fill = D.fill;
                                shapeArray[i].stroke = D.stroke;
                                shapeArray[i].du = rotatez;
                                shapeArray[i].linew= D.linew;
                            }
 
                        });
                        paint.closePath();
                    }
 
 
                    if (shapeArray[i].shape == '直线') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.line(can, Da.linew, Da.stroke, Da.p, Da.p1, Da.apl, Da.shadow,tcx,tcy,function(){
                            if(tczkg){
                                shapeArray[i].fill= D.fill;
                                shapeArray[i].stroke= D.stroke;
 
                            }
 
                        });
 
                    }
                    if (shapeArray[i].shape == 'shape') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.fillShape(can,Da.arr,Da.fill,Da.stroke,Da.linew,Da.apl,Da.shadow,tcx,tcy,function(){
 
                            if(tczkg){
                                shapeArray[i].fill = D.fill;
                                shapeArray[i].stroke = D.stroke;
                                shapeArray[i].du = rotatez;
                                shapeArray[i].linew= D.linew;
 
                            }
                        })
 
 
                        paint.save();
                    }
                    if (shapeArray[i].shape == '铅笔') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
 
 
                         Draw.shape(can, Da.arr, Da.stroke, Da.linew, Da.apl, Da.shadow);
                        paint.save();
                    }
 
 
                    if (shapeArray[i].shape == '曲线') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        Draw.curve(can, Da.linew, Da.stroke, Da.p, Da.p1, Da.p2);
                        paint.save();
                    }

                        paint.save();
                    }
 
                    if (shapeArray[i].shape == '像素') {
 
                        var Da = shapeArray[i];
                        paint.beginPath();
                        if (Da.data) {
                            Draw.putImg(can, Da.data, Da.p, 0, 0, Da.p1, 0);
                        }
                        paint.save();
                    }
 
 
                }
 
            }
 

(3)编辑功能

            clear: function (canv, x, y, w, h) {
                var ctx;
                if ((typeof canv) == "string") {
                    ctx = document.getElementById(canv);
 
                } else if ((typeof canv) == "object" && canv != null) {
                    ctx = canv;
                }
                try {
                    var ctx = ctx.getContext("2d");
                } catch (e) {
                    Draw.trace("提供的画布信息有误!请查看画布设置,或画布的id信息是否有误!");
                    Draw.print("提供的画布信息有误!请查看画布设置,或画布的id信息是否有误!");
                }
 
                ctx.clearRect(x, y, w, h);

            },
 

(4)鼠标控件响应

addEventListener('mousedown', function (e) {
 
            if (inpanl(canC, e)) {
                var xc = getMousePos(canC, e).x;
                var yc = getMousePos(canC, e).y;
                nowColor = quse(xc - 10, yc);
 
                document.getElementById('filCol').value = nowColor;
            }
            if (inpanl(can, e)) {
                pxdata = null;
 
                switch (D.shape) {
 
                    case '矩形':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
 
                        break;
                    case '文字':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1);
                        words.style.left = e.clientX + 'px';
                        words.style.top = e.clientY + 'px';
                        break;
                    case '图片':
 
                            if(picpath==null){
                                alert("请先上传图片");
                            }else{
                                D.startKg = true;
                                D.img.src = picpath;
                                var x1 = getMousePos(can, e).x;
                                var y1 = getMousePos(can, e).y;
                                D.p = new point(x1, y1)
                            }
 
                        break;
                    case '选择':
 
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        cana.style.left = e.clientX + 'px';
                        cana.style.top = e.clientY + 'px';
 
                        break;
                    case '复制':
 
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        cana.style.left = e.clientX + 'px';
                        cana.style.top = e.clientY + 'px';
 
                        break;
                    case '橡皮':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
 
                        break;
 
                    case '圆形':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
 
                        break;
                    case '多边形':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        break;
                    case '多角形':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        break;
 
                    case '直线':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        break;
                    case '铅笔':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        break;
                    case 'shape':
                        D.startKg = true;
                        var x1 = getMousePos(can, e).x;
                        var y1 = getMousePos(can, e).y;
                        D.p = new point(x1, y1)
                        break;
                    case '填充':
                        tczkg = true;
 
                        break;
                    case '曲线':
 
                        if (dkg == 0) {
                            D.startKg = true;
                            var x1 = getMousePos(can, e).x;
                            var y1 = getMousePos(can, e).y;
                            D.p = new point(x1, y1);
                            dkg += 1;
                        } else {
                            var x2 = getMousePos(can, e).x;
                            var y2 = getMousePos(can, e).y;
                            D.p1 = new point(x2, y2);
                            saveShape();
                            dkg = 0;
                            D.quKg = false;
                        }
 
                        break;
                }
 
            }
        });
四、实验结果展示

普通笔刷
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
动态绘制
在这里插入图片描述
在这里插入图片描述

扩展绘画概念的理念

(1)技法

绘画是一门精细的具有实际用途的学问,需要一种活跃又不失严谨的思维状态以及实际操作去学习以及领悟。当然,既绘画作为一种手上技能,那么肯定需要足够多的实际动手操作才能越画越好。本次设计用到的Canvas是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。实际上Canvas规范包含两个部分,一个是HTML5新引入的canvas元素,还有更为关键的2D渲染上下文。实际上前者只是一个容器,后者才是真正绘图的地方。它包含绘图和图形操作所需要的全部方法和丰富功能。

(2)工具

Canvas,用来支持在网页上绘制图形图像,以前在网页中进行交互绘图是很困难的(需要依赖额外的第三方插件),而引入的Canvas特性使得作者可以很容易的在网页上绘制各种图形和图像。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
​它最初由苹果内部使用自己MacOS X WebKit推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。 后来,有人通过Gecko内核的浏览器 (尤其是Mozilla和Firefox),Opera和Chrome和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。
​Canvas是由HTML代码配合高度和宽度属性而定义出的可绘制区域。JavaScript代码可以访问该区域,类似于其他通用的二维API,通过一套完整的绘图函数来动态生成图形。Mozilla 程序从 Gecko 1.8 (Firefox 1.5)开始支持 , Internet Explorer 从IE9开始 。Chrome和Opera 9+ 也支持 。
以前在网页中进行交互绘图是很困难的(需要依赖额外的第三方插件),而引入的Canvas特性使得作者可以很容易的在网页上绘制各种图形和图像。
Canvas提供了脚本(JavaScript)应用接口,我们可以使用JS代码来操作画布,添加各种图形以及实现用户交互。这些特性使得HTML5在开发网页游戏和一些复杂的网页动画上变得更加方便。

(3)创作理念

在生活中,绘画有着非常广泛的应用,绘图软件,简言之即用来作图的软件,通常是指计算机用于绘图的一组程序,软件程序按功能可分为三类,并且程序的设计有一定的准则,常用的绘图软件有很多,例如Photoshop、Adobe image 、AutoCAD等。多个程序的汇集,组成功能齐全、能够绘制基本地图图形和各类常用地图的程序组,称为绘图软件系统,或称为绘图软件包。绘图软件通常用高级算法语言编写,以子程序的方式表示,每个子程序具有某种独立的绘图功能。绘图软件包是绘图子程序的汇集,可包括几十个至几百个子程序。用户根据需要,调用其中一部分子程序,绘制某种图形或一幅地图。

(4)创作体验

不要拿着笔就开始写代码。对一个系统进行编写前。首先应该大体上构思好系统的框架,做到心中有数,能够合理安排布局后才开始写代码。否则编写途中可能会遇到很多意想不到的问题,由于之前的考虑不周而出现细节上的错乱,我们不是大师,可以窥一发而知全身。我们当前要做的就是慢慢一步一个脚印的走。编写代码时,你会发现可能就是一个简单的扇形,你可能绘制都要花一番功夫,但好在前辈们已经打好了基础,你可以通过调用不同的函数库,加以修改和补充,就能绘制很多图案出来。对于不了解编程这方面的朋友们来说,也许你看到的只是一副简单的图画,但是其中包含的代码和心血超出你的想象,或许你用手绘几分钟就能搞定,但在写代码时,代码的逻辑性需要十分的严谨。

(5)呈现效果

在呈现效果上,此绘画系统本身与普通的绘画系统是有一定的差异的,比如动图的绘制,笔刷的改变,发光效果的呈现,使得画面更具有感染力和张力,你可以通过画笔表达你所想,将情感寄托于你自己的作品上,给人以触发。

(6)交互性

在网络传播中,受者能够通过多种输入输出方式与系统或者其他受者在一定程度上进行直接双向交流的特性被称为网络交互性。从传播的基本模式来看它是这样的一个过程,传者发出讯息,并通过受者的反馈来确认传播的效果;而受者不但接收讯息,而且也会根据自己的理解做出相应的反馈。在绘画系统中,用户通过鼠标进行交互,可改变画笔的类型以及画笔参数,从而更好地作画。

(7)局限性

绘画中的光线是非常重要的,只有通过光影,才能产生体感,产生空间感,并且光影也是烘托某种气氛的重要元素,光影对于画面来说是非常重要的,真实的反应我们肉眼所能看到的实物,并用绘画手段将其本身在有光线情况下,将他固有的质感,形体表现出来。西方画家多采用光影画法来作为画面表达技法,利用光影来突出主体物,而中国画家又采用水彩光影表现技法这种技法也要求绘画者不能单纯从表象观察到光,而要在实际的构思中去灵活运用光。而码绘在光影效果的实现上比较复杂,不容易表现,实现需要较高的技术。

体会

电脑设计效果图尽管有很多的优势,但在作品表现上存在模式化、雷同化的问题,与现代设计中越来越注重艺术风格的个性化、多样化,注重人情味的表现不相符合。
电脑设计效果图与手绘效果图相比,由于作者大都在同一个软件平台上通过程序完成设计,风格表现上显得单一、乏味二而手绘表现效果图因为直接由作者手绘操作,在表现形式、色彩运用、技法选择等方面与电脑软件相比更具有灵活性,能更好地体现出作者不同的审美风格,在手绘过程中作者往往有一些随意性的技法表现,而这是电脑设计效果图所不能达到的。
手绘效果图和电脑画图都是表现设计师的创造设计理念,手绘效果图是最快速的表现形式,最大的优势在于能够激发设计师的灵感,且显得生动形象,适合创意;而电脑绘图却更加真实准确,但是速度比较慢,需要反复修改,且不适合创意,但两者都非常重要。
从今后表现效果图的发展来看,电脑设计软件肯定会不断地得到开发,并不断解决各种不足之处,而手绘表现效果图的技法、工具、材料也在不断的推陈出新。因此,鉴于二者各有特点,因而可使其互相借鉴、结合,突出各自的优势,通过各种绘制技法的合理运用,使表现效果图更加准确、生动富有艺术感染力,更好地为设计和工程的实施服务。

参考资料

1.HTML5 Canvas 学习笔记
链接:https://blog.csdn.net/zhangwx6/article/details/58671045

2.以编程的思想来理解绘画—— (一)用”一笔画“表现“过程美”
链接: https://blog.csdn.net/magicbrushlv/article/details/82634189

3.浅谈HTML5 canvas
链接:https://blog.csdn.net/zhouziyu2011/article/details/65682406

4.学习HTML5 Canvas这一篇文章就够了
链接:https://blog.csdn.net/u012468376/article/details/73350998

5.HTML 5 Canvas 参考手册
链接:http://www.w3school.com.cn/tags/html_ref_canvas.asp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值