基于HTML5+js的自画像码绘

mac2026-06-15  17

目录

成果展示设计规划代码展示知识点介绍总结与反思

成果展示

设计规划

不太擅长原创自画像,于是尝试了一下先在Ai软件里手绘。(如果是男生,可能还会好看一点) 基本上就是通过曲线、圆弧、椭圆圆弧来构成,再搭配一下色彩。最好再加一点交互互动?那么咱们开始吧!

代码展示

<canvas id="face" width="1600" height="800">不支持Canvas!</canvas> <script type="text/javascript"> var canvas = document.getElementById("face"); var c1 = canvas.getContext("2d"); </script> //背景 function background() { c1.fillStyle = '#a1afc9'; c1.fillRect(0,0,1600,800); } //脸和头发 function faceandhairs() { //底色 /*c1.fillStyle = '#a1afc9'; c1.fillRect(0,0,1600,800);*/ //大面积头发 c1.lineWidth = "10"; c1.fillStyle = '#ffa07a';//填充 c1.strokeStyle="#dc143c";//边 c1.beginPath(); c1.ellipse(700,300,300,200,0,0,Math.PI*2); c1.fill(); c1.stroke(); //头发凸出来的左边 c1.lineWidth = "10"; c1.fillStyle = '#ffa07a';//填充 c1.strokeStyle="#dc143c";//边 c1.beginPath(); c1.ellipse(550,200,200,100,Math.PI*1.75,0,Math.PI*2); c1.fill(); c1.stroke(); //头发凸出来的右边 //省略 //遮盖物 c1.lineWidth = "10"; c1.fillStyle = '#ffa07a'; c1.beginPath(); c1.ellipse(700,160,200,100,0,0,Math.PI*2); c1.ellipse(700,352,285,30,0,0,Math.PI*2); c1.fill(); //白白的脸、眼睛、腮红、眉毛、鼻子、嘴巴 //省略 } //蝴蝶结 function butterfly() { c1.lineWidth = "30";//直线 c1.fillStyle = '#ffa07a';//填充 c1.strokeStyle="#ffa07a"; c1.beginPath(); c1.moveTo(50,70); c1.lineTo(200,150); c1.lineTo(200,70); c1.lineTo(50,150); c1.lineTo(50,70); c1.lineTo(125,110); c1.fill(); c1.stroke(); c1.lineWidth = "6";//直线 c1.strokeStyle="#ffffff"; c1.beginPath(); c1.moveTo(75,100); c1.lineTo(125,110); c1.lineTo(75,120); c1.moveTo(175,100); c1.lineTo(125,110); c1.lineTo(175,120); c1.stroke(); c1.lineWidth = "30";//直线 c1.strokeStyle="#ffffff"; c1.beginPath(); c1.moveTo(125,90); c1.lineTo(125,130); c1.stroke(); } //铺就蝴蝶结 function manybutterfly() { for(var i=0;i<1500;i+=300) { for(var j=0;j<800;j+=160) { c1.translate(i,j); butterfly(); c1.translate(-i,-j); } } } //调用 background(); manybutterfly(); faceandhairs(); //手势 function hand() { //食指 c1.lineWidth = "6"; c1.fillStyle = '#ffffff';//填充 c1.strokeStyle="#cb3a56";//边 c1.beginPath(); c1.moveTo(70,128); c1.lineTo(52,55); c1.ellipse(70,50,20,20,0,Math.PI*0.85,0); c1.moveTo(90,50); c1.lineTo(110,200); c1.fill(); c1.stroke(); //大拇指 c1.lineWidth = "6"; c1.fillStyle = '#ffffff';//填充 c1.strokeStyle="#cb3a56";//边 c1.beginPath(); c1.ellipse(100,150,30,20,0,0,Math.PI*2); c1.fill(); c1.stroke(); //中指无名指、小拇指 //省略 } //鼠标决定手势的位置 window.οnlοad=function(){ document.οnmοusedοwn=function(ev){ var oEvent=ev||event; c1.translate(oEvent.clientX-100,oEvent.clientY-100); //c1.save(); hand(); c1.translate(-oEvent.clientX+100,-oEvent.clientY+100); //c1.translate(0,0); //c1.restore(); } }

知识点介绍

背景 本来是把底色,也就是背景,和“脸和头发”放在一个方法里的。后来决定要加个蝴蝶结背景,于是就把背景单独拎出来了。头发和脸 其实头发和脸算坐标真的算是很方便简单了!有的小伙伴计算圆弧的位置和角度算了很久,我就比较方便了,我直接用了含有描边的椭圆来描绘头发的形状,然后把多出来的没用的描边覆盖掉了。(嘘,看不出来的小把戏)

ellipse()画椭圆弧函数 功能: 函数ellipse()使用当前绘图色画一椭圆弧。 用法: 该函数调用方式为void ellipse(int x,int y,int startangle,int endangle, int xradius,int yradius); 说明: 参数x,y为椭圆中心坐标,startangle和endangle为给定的起始角和终止角,xradius与yradius为椭圆的x轴半径与y轴半径,如果startangle为0 ,endangle等于360度,那么画出的是个完整的椭圆。

注意:如果不重新写beginPath,线条就会连起来,一笔画到底。不过,在需要线条连接,或者一笔画更方便的时候,就可以省略beginPath了。

蝴蝶结 绘制蝴蝶结的代码这里就不赘述了,无非是线宽的调整、moveto和lineto的使用、填充描边的技巧。

好多好多蝴蝶结 本来打算直接算坐标,画几个蝴蝶结的,后来觉得太麻烦了吧!还是批量生成吧。 先画好一个蝴蝶结,装进一个function里,然后调用。这里是顺序排版,所以可以用简单的for循环来安排。 几个注意点: ①想要排版好看,i的循环间隔是300,而j的循环间隔是160。 ②一开始不知道怎么变换蝴蝶结的位置,毕竟刚刚已经一冲动 写好了坐标,算好了位置。好吧,那就按照定好的数值吧!只要改变坐标原点,不就是改变图像位置了吗?于是查资料,果然有改变坐标原点的方法,translate!! ③先通过translate把坐标原点移动到想要绘制的地方,然后绘制。可是如果继续在这个基础上定义新的坐标原点,那么最新的坐标原点的基准就是刚刚定义的坐标原点,这样偏移的位置就会越来越大,而且无法控制。 所以应该设置translate(0,0)吗?不对,这样是不正确的。设置translate(0,0)就等于没有变化呀! 由于我们的for循环中i和j的变化间隔是固定的,所以我们需要的坐标原点必须是最最最初的原点,也就是左上角那个点。应该是translate(-i,-j)。

调用function 注意顺序就可了!

鼠标点击出现“爱你”手势 码绘就不多说了,慢慢算坐标吧!技巧?多算算就知道了。主要还是介绍“鼠标点击位置出现图案”的方法吧。

//样例示范 window.οnlοad=function(){ document.οnmοusedοwn=function(ev){ var oEvent=ev||event; var oDiv=document.createElement('div'); oDiv.style.left=oEvent.clientX+'px'; // 指定创建的DIV在文档中距离左侧的位置 oDiv.style.top=oEvent.clientY+'px'; // 指定创建的DIV在文档中距离顶部的位置 oDiv.style.border='1px solid #cb3a56'; // 设置边框 oDiv.style.position='absolute'; // 为新创建的DIV指定绝对定位 oDiv.style.width='200px'; // 指定宽度 oDiv.style.height='200px'; // 指定高度 document.body.appendChild(oDiv); }

一开始使用的是如上的方法,这个方法是简单地画默认形状的,比如矩形圆形,对于自定义的function没有作用。 灵机一动,刚刚改变坐标原点绘图的方式不是很好吗?既然手势的绘图坐标都已经固定了数值,那么很显然,改变坐标原点仍然是个不错的方法。至于交互互动、指定位置,只要获取鼠标位置就可以了呀。 正确方法如下:

window.οnlοad=function(){ document.οnmοusedοwn=function(ev){ var oEvent=ev||event; c1.translate(oEvent.clientX-100,oEvent.clientY-100); //c1.save(); hand(); c1.translate(-oEvent.clientX+100,-oEvent.clientY+100); //c1.translate(0,0); //c1.restore(); } }

总结与反思

这次的绘图,简直是“一个c1走天下”。其实也无伤大雅,但是没有弄清楚canvas的作用和方法是真的。一直没有使用processing或者p5,感觉函数、方法的使用都差不多,但是习惯了html5的界面。下次试试p5吧。

最新回复(0)