在很多网站上我们都可以看到一些动态的图片,比如水的滴落,风的流动,树的摇曳,花瓣的飘散,等等,比如这样的:

这样的:

挺唯美的是不是?
这些图片是怎么做出来的,笔者也不是很清楚,不过笔者最近正好在学习p5.js,里面的有些技术正好可以实现这种效果,让我们一起来看看吧;
其实笔者一开始想做的并不是花瓣,而是雪花,首先通过p5.js,绘制出雪花的一部分:

       var width;
function draw(){width=5;background(0);translate(300, 400);stroke(0, 153, 255);strokeWeight(width);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);
}

运行一下

还行,让我们旋转一下,一朵完整的雪花就出来了:

我们将绘制雪花的代码放入函数中,附上完整代码:

    function snowflake(x, y, width) {//绘制雪花,参数分别为雪花的x坐标,y坐标和宽度stroke(0, 153, 255);//设置颜色strokeWeight(width);//设置雪花线宽translate(x, y);//转化坐标系到x,yline(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);//旋转60度,绘制下一片雪花(注意旋转的是坐标系,为了避免影响其他代码,最后需要旋转回去/或旋转一周)line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);translate(-x, -y);//切换回原坐标系(左上角0.0为圆点)}

很好,一片雪花已经绘制出来了,接下来我们要让他动起来
在draw设置一个参数i,i的初值设置为0,然后将i放入调用的雪花函数中,并在每次绘制后让i++:`

var i=0;
function draw(){
background(0);
snowflake(400,500+i,5);
i++;
}

效果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181124164107440.gif)一朵雪花缓慢的下落,很简单是不是?让我们多加一些东西:在雪花的绘制中加入参数angle,每次绘制时,先将坐标系旋转angle后,再绘制:

var i=0;
var angle=0;
function draw() {
background(0);
snowflake(400, 100 + i, 5, angle);
i++;
angle = angle + 0.02;
}

function snowflake(x, y, width, angle) {stroke(0, 153, 255);strokeWeight(width);translate(x, y);rotate(angle);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);rotate(-angle);translate(-x, -y);
}
运行:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181124164917478.gif)
雪花自己转起来了;
然后我们再用这些方法做多个雪花,具体就不多说了,直接上代码:
var num = 20;
var mixnum;
var gravity = 0.05;
var snows = [];
var i=0;function setup() {mixnum=num;createCanvas(windowWidth, windowHeight);createObject();var int=self.setInterval("createObject()",2500);
}
function createObject() {for (i; i < mixnum; i++) {snows[i] = new Snow(random(0, windowWidth),random(0, 200),random(1, 5),random(1, 3),random(1, 3),0);}mixnum=mixnum+num;
}function draw() {background(240);snows.forEach(snow => {snow.move();snow.display();snow.delete();});
}function Snow(x, y, width, dx, dy,angle) {this.x = x;//落点横坐标this.y = y;//落点纵坐标this.move = function () {this.x += dx;this.y += dy;angle=angle+random(0,0.02);};this.display = function () {snowflake(this.x, this.y, width,angle);};this.delete=function () {if(this.y>=windowHeight){snows.splice(this,1);}}
}function snowflake(x, y, width,angle) {stroke(0, 153, 255);strokeWeight(width);translate(x, y);rotate(angle);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);line(0, 0, 0, 10 * width);line(-3 * width, 7.5 * width, 0, 5 * width);line(3 * width, 7.5 * width, 0, 5 * width);line(-2.5 * width, 5 * width, 0, 3 * width);line(-1 * width, 3.8 * width, -2 * width, 3 * width);rotate(PI / 3);rotate(-angle);translate(-x, -y);
}

最终效果:

不知道会不会有点卡,我传的时候好像挺卡的。
好了,雪花飞舞的感觉做出来了(虽然有点简陋),那让我们把雪花换成花瓣:

在插入背景图片:


是不是有点感觉了?第一张图原本的比例不太够,所以小姐姐的脸被我拉长了,不过能看效果就好了。
附上完整代码:

   var num = 20;var mixnum;var gravity = 0.05;var follows = [];var i=0;var img;function preload(){//加载图片文件img = loadImage("3.jpg");}function setup() {mixnum=num;createCanvas(windowWidth, windowHeight);createObject();var int=self.setInterval("createObject()",2500);}function createObject() {for (i; i < mixnum; i++) {follows[i] = new Follow(random(-500,windowWidth),random(-200,0),random(1, 3),random(1, 3));}mixnum=mixnum+num;}function draw() {background(255);image(img, 0, 0,windowWidth, windowHeight);follows.forEach(follow => {follow.move();follow.display();follow.delete();});}function Follow(x, y, dx, dy) {this.x = x;//落点横坐标this.y = y;//落点纵坐标var randomNum = Math.ceil(Math.random()*3);this.move = function () {this.x += dx;this.y += dy;};this.display = function () {follow(this.x, this.y, randomNum);};this.delete=function () {if(this.y>=windowHeight){follows.splice(this,1);}}}function follow(x, y, flag) {noStroke();translate(x, y);rotate(PI/3);if(flag==1) {fill(255,192,203);arc(0, 0, 40, 20, 0, PI);arc(0, 0, 40, 20, PI, 2 * PI);}if(flag==2) {fill(249,204,226);arc(0, 0, 30, 15, 0, PI / 3);}if(flag==3) {fill(242,156,177);ellipse(0, 0, 20, 8);}if(flag==4){}rotate(-PI/3);translate(-x, -y);}

我在follow函数中绘制了三种不同形状大小颜色的樱花,然后用随机数来决定生成哪种樱花,这样看起来更好看一些,当然樱花的形状越多越好,这里笔者只是展示一种效果,就不绘制太多的樱花了;
OK,以上就是码绘的代码和效果,那么接下来是手绘。。
手绘的雪花:

手绘的花雨:

不擅长手绘,见谅一下;

手绘与码绘的对比:
从笔者这个例子来看,手绘和码绘都各有各的优点:

码绘的优点:
表现力:码绘可以通过代码控制物体的旋转,运动,用动态的场景更形象的表现出花雨的姿态;
可量产:码绘可以通过循环、递归等方式大量的调用函数,绘制大量对象,并且可以控制对象的大小、宽度等,这是码绘较难做到的;
可套用:就像花瓣飞舞这个效果,可以将做好的动态效果,套用在不同的背景图片中,做出不同的图片;
准确性:在一些单纯由线条组成的,具有固定形态的物体(如雪花),码绘可以更精确的控制旋转的角度,每片雪花每个方向的长度,等等,这是手绘比较难做到的。

手绘的优点:
直观:可以很轻松的画出来,而不需要像码绘一样,确定各点坐标、旋转;
随机性:手绘可以很轻松的绘制出不同形态、不同大小的花瓣,而码绘只能在原本已经绘制好的花瓣中挑选(没有合适的智能绘制算法)。

创作体验:
作为一个灵魂画手,手绘基本断手的笔者,码绘自然是最佳选择。在码绘的过程中,经常会产生没想到的效果,比如一开始绘制雪花的时候,想着通过旋转花瓣来绘制整朵雪花,结果尝试了半天都没成功,结果从网上早了挺久才知道了可以通过操作坐标系来旋转绘制这种方法,经常会有“哦,原来如此”“还能这样”的感慨,算是一种比较开心的体验吧。而且通过自己的学习,去实现一些原来不会的事情,也是一种快乐呢。

参考资料:
p5.js官方案例:https://p5js.org/examples/motion-bouncy-bubbles.html
p5.js入门教程:https://blog.csdn.net/qq_27534999/article/details/75151515
用p5.js绘制毕达哥拉斯树:https://www.jb51.net/article/136944.htm

手绘与码绘————用代码表现出花瓣飞舞的效果相关推荐

  1. 【用代码画画】手绘vs码绘

    [用代码画画]手绘vs码绘 主题 手绘展示 码绘展示 码绘代码 总结 思路 技术 创作体验 创作偏好 相关资源 主题 展示如何将一幅手绘作品,用代码绘制出来. 通过手绘与码绘过程及结果的比对,探究手绘 ...

  2. 手绘vs码绘 动态对比

    用手绘和码绘两种方式创作"运动"主题的作品,并作出对比 手绘图: 码绘图: 比较 技法:不考虑美观的话手绘比较方便,可以怎么想怎么做,而码绘却比较复杂,需要转换为代码. 工具:手绘 ...

  3. 手绘vs码绘2——动态弓箭

    手绘与码绘动态对比 前言 在上一次博客中,我们已经成功用代码重现了手绘的Q版小人,对手绘和码绘进行了几个方面的对比分析.不得不承认,码绘由于形状和编写时间的限制,在绘制静态图像的方面和手绘还是有很大差 ...

  4. 手绘和码绘的对比(2)——动态比较

    码绘 手绘 代码实现过程 var numBalls = 30; var spring = 0.05; var gravity = 0.01; var friction = -0.9; var ball ...

  5. 手绘与码绘————趣味交互式绘画系统的实现

    简介 上一篇博文我主要写了用向量来实现笛卡尔之心的形态变化.这一次我们以此为基础,把这种向量变化作为"颜料"来制作一个非常有趣的交互式绘画系统. 另外,这次我还使用了一种新的充满艺 ...

  6. 手绘vs码绘1——Q版小人

    手绘与码绘静态对比 前言 在互动媒体的课程上,我了解了P5.js这项技术,并且学会了运用它进行简单的网页绘图.可能有很多人认为,绘画是一种艺术形式,必须要拿起画笔才能产生好的作品,而代码听起来和绘画毫 ...

  7. 手绘与码绘的比较---模拟风吹树动

    手绘与码绘的比较-模拟风吹树动 一.内容介绍 本文主要介绍用手绘和码绘两种方式模仿一种自然现象–风吹树动的过程,以及在实现过程对这两种方式的比较和思考.之所以选择风吹树动,是因为每次速写画一些场景时( ...

  8. 手绘VS码绘——动态篇(视觉错觉)

    前言 在介绍这次的实验前,先让我们看看一组图片: 相信大家看完这组图片已经有点难受的想点一下右上角的X了,其实不止你们,我在写这篇文章的时候也想关掉它-- 接下来我就按照正常的介绍流程告诉大家,这些图 ...

  9. 手绘与码绘对比(一)

    最近在老师的带领深入学习研究了手绘与码绘啊. 话不多说,直接上图. enmmm.....我知道这图不怎么样,有点沙地奥,但我们的主要目的是感受手绘与码绘的不同创作体验啊! 码绘我这次用的是p5.js ...

  10. 手绘与码绘的比较——实战之梵高《星空》

    手绘与码绘的比较--实战之梵高<星空> 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近博主的老师在交互媒体设计课上布置了一个作业,是关于"运动"主题的作品创 ...

最新文章

  1. 修改can接口波特率_CAN总线分析仪使用
  2. 泛型技巧系列:简单类型选择器
  3. GD32F207移植FreeRtos,程序运行vTaskStartScheduler后进入HardFault_Handler死循环解决方法
  4. 深入解析 C# 的 String.Create 方法
  5. 现代软件工程 作业 原型设计
  6. 【Java从入门到头秃专栏 4】语法篇(三) :字符串 数组
  7. windosw7 Hosts文件的位置
  8. 如何在C++中嵌入JAVA程序
  9. C ++ 指针 | 指针与函数 实际运用_8
  10. 精雕道路怎么遍弧形_有网友私信我问郑州融信奥体世纪这个楼盘怎么样他今天来...
  11. pycharm不认识numpy?_深度学习(CV方向)入坑不完全指南
  12. apache缺省banner_NSFOCUS建议您采取以下措施以降低威胁: * 修改源代码或者配置文件改变SSH服务的缺省banner。...
  13. Bootstrap教程:[4]栅格系统详解
  14. 前端调试debugf_前端应该掌握的这些Debug技巧,能够快速提升你的前端开发能力...
  15. 2021五一数学建模B题思路
  16. 解决:error: (-215) size.width>0 size.height>0 in function cv::imshow
  17. 程序员不能说自己不行啊
  18. STM32网络之DMA控制器
  19. 根据时间排序(collection.sort())
  20. c#如何使用webservice、存储过程及存储过程的创建(简单模仿类似QQ统计用户在线时间为例)

热门文章

  1. QML快捷键(Shortcut、Keys)
  2. 三角网格库Triangle的使用
  3. js 对象拼接的方法 数组 Map Set
  4. 《一只特立独行的猪》摘抄笔记
  5. 服务器系统文件sam在哪里,SAM文件介绍
  6. java modifier access_Java中的默认访问修饰符是什么? (What is the default access modifier in Java?)...
  7. Linux下实现双机互信
  8. 暴雪:一心想要发财,注定无法诞生伟大的游戏,但是一旦伟大的游戏诞生,发财是一定的。
  9. 测试世界各地打开网站的速度
  10. [iOS] 浅析排序规则描述类: NSSortDescriptor