利用Html 5的canvas标签绘制水流和水池动画

在利用HTML 5的canvas进行动画绘制之前,首先先介绍一下基本知识,包括canvas(如果对canvas比较熟悉的可以直接跳过该节)、oCanvas框架、精灵动画。在了解了以上的基本知识后,就可以开始利用canvas做动画了。

canvas标签简介

在这部分,东西比较多,比较杂,各个网站上都可以找到相关的简介,在此我就不造轮子了,菜鸟上的教程就挺不错的,另外推荐一个相当好的博文玩转html 5 canvas画图,这篇文章介绍的非常详细,推荐好好看看。

canvas框架oCanvas简介

canvas标签功能非常强大,既可以处理图片,又可以进行像素级的处理,完全可以取代浏览器端的flash,但是由于canvas发展还未完善,API还不是太全,元素的事件处理功能等还没有提供接口,在实现一些复杂功能时,尚需耗费许多精力,于是出现了许多第三方的基于canvas 的框架,这些框架相比于原生的canvas标签,有了更多简单易用的API,大大提高了我们编码的效率,在这里我选用的是oCanvas框架,相关的使用文档和demo都可以去上面的链接中查看。

精灵动画简介

精灵动画一般由一组自定义的属性值和3个子函数组成(init、advance、draw)。

三个函数的作用分别如下:

init:初始化精灵动画的属性值

advance:再画下一帧之前首先更新下一帧的状态值

draw:将advance函数中更新的状态值绘制到画布中

以上三个函数的执行顺序是:init->advance->draw->advance->draw->…..一直循环下去。下面我以一个随机产生上升气泡的例子说明一下上面的执行过程。var constructor_bubble = function (settings, core) {

return oCanvas.extend({

core: core,

shapeType: "rectangular",//下面定义了上面我们提到的三个函数:init(),advance(),draw()//在init中,我们map对象组、一个空的数组和一个代表高度的属性值

init: function () {

this.map=[

{r:2,speed:3},

{r:3,speed:3},

{r:4,speed:3},

{r:5,speed:3},

{r:6,speed:3},

{r:7,speed:3},

{r:8,speed:3},

{r:9,speed:3},

{r:10,speed:3}

]; this.points=[]; this.height=this.container.height_now;

},//下面是advance函数,在函数中我们利用if逻辑判断是否添加新的气泡以及进行气泡的位置更新,points数组利用队列的先进先出来存储气泡的

advance: function () {

this.height=this.container.height_now; if(Math.random()>0.95){ var new_point={

x:this.start.x+this.offset*2*(Math.random()-0.5),

y:this.start.y-this.map[0].r,

r:this.map[0].r

}; this.points.push(new_point);

} if(this.points.length>0){ for(var i=0;ithis.height-this.points[i].r-33){ this.points.shift();

}

}

}

},//draw函数中,利用canvas的圆弧绘制指令,将points数组中存储的气泡依次画出

draw: function () {

var canvas = this.core.canvas;

canvas.lineJoin = 'round';

canvas.lineWidth = this.GDwidth;

canvas.strokeStyle = "#fff"; if(this.points.length>0){ for(var i=0;i

canvas.beginPath();

canvas.arc(this.points[i].x,this.points[i].y,5,0,2*Math.PI);

canvas.stroke();

canvas.closePath();

}

}

}

}, settings);

};

oCanvas.registerDisplayObject("bubble", constructor_bubble, "init");//下面是在应用中定义和添加上面定义的精灵动画,其中:start数组代表了气泡的产生点,container代表了气泡的存在区域var pp1=canvas.display.bubble({

start:{x:425,y:566},

container:SC02,

width:50,

offset:1,

speed:5

}).add();

水流和水池动画实现

下面详细介绍一下,项目中如何实现水流动画和水池动画的详细步骤:

水池动画的绘制var constructor_show = function (settings, core) {

return oCanvas.extend({

core: core,

shapeType: "rectangular",//上面四行都是oCanvas框架的结构语法/*下面init()、advance()、draw()分别是上节中说的动画精灵三元素,第一个用来初始化,第二个用来

更新操作,第三个用来绘制图像/动画在管道对象中,定义了一些属性,包括:x、y、height、width、start、

height_now、full、speed、fill、trail_flag、[trail]。其中x、y分别代表水池参考点相对画布左

上角的位置,height、width是水池的宽高属性,start表征了动画是否开始,height_now代表了水池中水

位的高度,full表征了水池是否填满,speed水池上涨的速度,fill水的颜色,trail_flag表征了该水池

是否是一个标准的矩形,如果不是的话,配合trail属性,指定水池的轮廓*/

init: function () {

//默认动画关闭,水池full为0,当前高度为0

this.start=0; this.full=0; this.height_now=0;

},

advance: function () {

//如果水池未满并且是开启状态,水位未满就更新当前高度,否则将full置为1

if(this.start==1&&this.full!=1){ if (this.height_now < this.Height) { this.height_now += this.speed;

} else { this.full = 1;

}

}

},

draw: function () {

var canvas = this.core.canvas, //先获得水池的位置

origin = this.getOrigin(),

x = this.abs_x - origin.x,

y = this.abs_y - origin.y; //开始绘制

canvas.beginPath();

canvas.strokeStyle = "#000"; if (this.trail_flag == 1) { //如果是不规则图形,描出轮廓

canvas.moveTo(this.trail[0].x_t, this.trail[0].y_t); for (var i = 1; i < this.trail.length; i++) {

canvas.lineTo(this.trail[i].x_t, this.trail[i].y_t);

}

canvas.lineTo(this.trail[0].x_t, this.trail[0].y_t);

canvas.clip();

} if (this.fill !== "") { //设置颜色,绘制矩形水池

canvas.fillStyle = this.fill;

canvas.fillRect(x, y + this.Height - this.height_now, this.Width, this.height_now);

}

canvas.closePath();

}

}, settings);

};//将上面的动画精灵注册进oCanvas的display图形库中oCanvas.registerDisplayObject("SC_show", constructor_show, "init");

管道水流动画的绘制

在管道水流模型中,定义了以下的属性:

destination: 当前水流最前端的位置

cells: 管道路径数组

deta: 方向斜边长

deta_x: 方向x边长

deta_y: 方向y边长

flag_x: 余弦值

flag_y:正弦值

cellIndex: 当前绘制边的index

Speed: 水流速度

GDwidth:水流宽度

LineHeight:水流长度

x_now: 当前绘制点x坐标

y_now: 当前绘制点y坐标

firstX: 管道第一个点坐标x

firstY: 管道第一个点坐标y

beginHeight: 第一段水流的起点位置

endHeight: 上一段管道遗留未画完的水线

legacyHeight: 最前端点在上一个管道留下的长度

paused: 是否开始

fill:水流颜色

full:是否填满

init函数//init函数主要完成初始化工作init: function () {

this.x_now = this.cells[0].x_cell;

this.y_now = this.cells[0].y_cell;

this.firstX = this.x_now;

this.firstY = this.y_now;

this.endHeight = 0;

this.beginHeight = 0;

this.paused=0;

this.full=0;

this.cellIndex = 0;

this.destination.x_d = this.cells[0].x_cell;

this.destination.y_d = this.cells[0].y_cell;

this.legacyHeight = -1;

this.LineHeight=10;

this.Speed=2*this.LineHeight/20;

}

advance函数//advance函数主要实现每次动画的刷新步进操作

advance: function () {

if(this.paused==1){

if (this.cellIndex < this.cells.length - 1) {

this.deta_x = this.cells[this.cellIndex + 1].x_cell - this.cells[this.cellIndex].x_cell;

this.deta_y = this.cells[this.cellIndex + 1].y_cell - this.cells[this.cellIndex].y_cell;

this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y);

this.flag_x = this.deta_x / this.deta;

this.flag_y = this.deta_y / this.deta;

if (this.legacyHeight >= 0) {

this.cellIndex++;

if (this.cellIndex < this.cells.length - 1) {

this.deta_x = this.cells[this.cellIndex + 1].x_cell - this.cells[this.cellIndex].x_cell;

this.deta_y = this.cells[this.cellIndex + 1].y_cell - this.cells[this.cellIndex].y_cell;

this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y);

this.flag_x = this.deta_x / this.deta;

this.flag_y = this.deta_y / this.deta;

this.destination.x_d = this.cells[this.cellIndex].x_cell + this.flag_x * this.legacyHeight;

this.destination.y_d = this.cells[this.cellIndex].y_cell + this.flag_y * this.legacyHeight;

if (Math.abs(this.destination.x_d - this.cells[this.cellIndex + 1].x_cell) > this.Speed * Math.abs(this.flag_x) || Math.abs(this.destination.y_d - this.cells[this.cellIndex + 1].y_cell) > this.Speed * Math.abs(this.flag_y)) {

this.legacyHeight = -1;

this.destination.x_d += this.flag_x * this.Speed;

this.destination.y_d += this.flag_y * this.Speed;

}

else {

if (this.flag_x == 0) {

this.legacyHeight = this.Speed - Math.abs(this.destination.y_d - this.cells[this.cellIndex + 1].y_cell) / Math.abs(this.flag_y);

}

else {

this.legacyHeight = this.Speed - Math.abs(this.destination.x_d - this.cells[this.cellIndex + 1].x_cell) / Math.abs(this.flag_x);

}

}

}

}

else {

this.destination.x_d += this.flag_x * this.Speed;

this.destination.y_d += this.flag_y * this.Speed;

if (Math.abs(this.destination.x_d - this.cells[this.cellIndex + 1].x_cell) >= this.Speed * Math.abs(this.flag_x) && Math.abs(this.destination.y_d - this.cells[this.cellIndex + 1].y_cell) >= this.Speed * Math.abs(this.flag_y)) {

this.legacyHeight = -1;

}

else {

if (this.flag_x == 0) {

this.legacyHeight = this.Speed - Math.abs(this.destination.y_d - this.cells[this.cellIndex + 1].y_cell) / Math.abs(this.flag_y);

}

else {

this.legacyHeight = this.Speed - Math.abs(this.destination.x_d - this.cells[this.cellIndex + 1].x_cell) / Math.abs(this.flag_x);

}

}

}

}else{

this.full=1;

}

this.deta_x = this.cells[1].x_cell - this.cells[0].x_cell;

this.deta_y = this.cells[1].y_cell - this.cells[0].y_cell;

this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y);

this.flag_x = this.deta_x / this.deta;

this.flag_y = this.deta_y / this.deta;

if (this.paused == 1) {

if (Math.abs(this.firstX - this.cells[0].x_cell) >= this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.firstY - this.cells[0].y_cell) >= this.LineHeight * Math.abs(this.flag_y)) {

this.firstX = this.cells[0].x_cell;

this.firstY = this.cells[0].y_cell;

this.beginHeight = 0;

}

else {

if (this.beginHeight < this.LineHeight) {

if (this.beginHeight + this.Speed >= this.LineHeight) {

this.beginHeight = this.LineHeight;

}

else {

this.beginHeight += this.Speed;

}

this.firstX = this.cells[0].x_cell;

this.firstY = this.cells[0].y_cell;

}

else if (this.beginHeight == this.LineHeight) {

this.firstX += this.flag_x * this.Speed;

this.firstY += this.flag_y * this.Speed;

}

}

}

}

}

draw函数//draw函数在每次advance之后执行,将每次的步进更新重新绘制到画布上

draw: function () {

var canvas = this.core.canvas; this.x_now = this.firstX; this.y_now = this.firstY; this.deta_x = this.cells[1].x_cell - this.cells[0].x_cell; this.deta_y = this.cells[1].y_cell - this.cells[0].y_cell; this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y); var myEnd = false; this.flag_x = this.deta_x / this.deta; this.flag_y = this.deta_y / this.deta;

canvas.beginPath();

canvas.lineJoin = 'round';

canvas.lineCap="round"; this.endHeight = 0;

canvas.lineWidth = this.GDwidth / 4;

canvas.strokeStyle = this.fill; if (this.beginHeight > 0) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.x_now + this.flag_x * this.beginHeight, this.y_now + this.flag_y * this.beginHeight);

} this.x_now += this.flag_x * (this.beginHeight + this.LineHeight); this.y_now += this.flag_y * (this.beginHeight + this.LineHeight); for (var i = 1; i <= this.cellIndex; i++) {

myEnd = false; this.deta_x = this.cells[i].x_cell - this.cells[i - 1].x_cell; this.deta_y = this.cells[i].y_cell - this.cells[i - 1].y_cell; this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y); this.flag_x = this.deta_x / this.deta; this.flag_y = this.deta_y / this.deta; if (this.endHeight > 0) {

canvas.moveTo(this.cells[i - 1].x_cell, this.cells[i - 1].y_cell);

canvas.lineTo(this.cells[i - 1].x_cell + this.flag_x * (this.endHeight ), this.cells[i - 1].y_cell + this.flag_y * this.endHeight); this.x_now = this.cells[i - 1].x_cell + this.flag_x * (this.LineHeight + this.endHeight); this.y_now = this.cells[i - 1].y_cell + this.flag_y * (this.LineHeight + this.endHeight);

} if (this.endHeight < 0) { this.endHeight = Math.abs(this.endHeight); this.x_now = this.cells[i - 1].x_cell + this.flag_x * (this.endHeight); this.y_now = this.cells[i - 1].y_cell + this.flag_y * (this.endHeight);

} if (this.endHeight == 0 && i != 1) { this.x_now = this.cells[i - 1].x_cell; this.y_now = this.cells[i - 1].y_cell;

} while (Math.abs(this.x_now - this.cells[i].x_cell) >= this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.y_now - this.cells[i].y_cell) >= this.LineHeight * Math.abs(this.flag_y)) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.x_now + this.flag_x * this.LineHeight, this.y_now + this.flag_y * this.LineHeight); this.x_now += this.flag_x * this.LineHeight; this.y_now += this.flag_y * this.LineHeight; if (Math.abs(this.x_now - this.cells[i].x_cell) <= this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.y_now - this.cells[i].y_cell) <= this.LineHeight * Math.abs(this.flag_y)) { if (this.flag_x == 0) { this.endHeight = Math.abs(this.y_now - this.cells[i].y_cell) / Math.abs(this.flag_y) - this.LineHeight;

} else { this.endHeight = Math.abs(this.x_now - this.cells[i].x_cell) / Math.abs(this.flag_x) - this.LineHeight;

} //this.endHeight = (Math.abs(this.y_now - this.cells[i].y_cell) + Math.abs(this.x_now - this.cells[i].x_cell) - this.LineHeight * (Math.abs(this.flag_y) + Math.abs(this.flag_x)))/2;

myEnd = true; break;

} else { this.x_now += this.flag_x * this.LineHeight; this.y_now += this.flag_y * this.LineHeight;

}

} if (myEnd == false && Math.abs(this.x_now - this.cells[i].x_cell) <= this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.y_now - this.cells[i].y_cell) <= this.LineHeight * Math.abs(this.flag_y)) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.cells[i].x_cell, this.cells[i].y_cell); //this.endHeight = this.LineHeight - Math.abs(this.x_now - this.cells[i].x_cell)*flag.x_flag - Math.abs(this.y_now - this.cells[i].y_cell)*flag.y_flag;

if (this.flag_x == 0) { this.endHeight = this.LineHeight - Math.abs(this.y_now - this.cells[i].y_cell) / Math.abs(this.flag_y);

} else { this.endHeight = this.LineHeight - Math.abs(this.x_now - this.cells[i].x_cell) / Math.abs(this.flag_x);

} //this.endHeight = ( this.LineHeight * (Math.abs(this.flag_y) + Math.abs(this.flag_x)) - Math.abs(this.y_now - this.cells[i].y_cell) + Math.abs(this.x_now - this.cells[i].x_cell)) / 2;

}

} if (this.cellIndex < this.cells.length - 1) {

myEnd = false; this.deta_x = this.cells[this.cellIndex+1].x_cell-this.destination.x_d; this.deta_y = this.cells[this.cellIndex+1].y_cell-this.destination.y_d; this.deta = Math.sqrt(this.deta_x * this.deta_x + this.deta_y * this.deta_y); if (this.deta > 0) { this.flag_x = this.deta_x / this.deta; this.flag_y = this.deta_y / this.deta; if (this.endHeight > 0) {

canvas.moveTo(this.cells[this.cellIndex].x_cell, this.cells[this.cellIndex].y_cell);

canvas.lineTo(this.cells[this.cellIndex].x_cell + this.flag_x * (this.endHeight ), this.cells[this.cellIndex].y_cell + this.flag_y * this.endHeight); this.x_now = this.cells[this.cellIndex].x_cell + this.flag_x * ( this.endHeight); this.y_now = this.cells[this.cellIndex].y_cell + this.flag_y * ( this.endHeight); if(Math.abs(this.destination.x_d-this.x_now)>this.LineHeight*Math.abs(this.flag_x)||Math.abs(this.destination.y_d-this.y_now)>this.LineHeight*Math.abs(this.flag_y)){ this.x_now+=this.LineHeight*this.flag_x; this.y_now+=this.LineHeight*this.flag_y;

} else{ this.x_now=this.destination.x_d; this.y_now=this.destination.y_d;

} if (this.endHeight < 0) { this.endHeight = Math.abs(this.endHeight); this.x_now = this.cells[this.cellIndex].x_cell + this.flag_x * (this.endHeight); this.y_now = this.cells[this.cellIndex].y_cell + this.flag_y * (this.endHeight);

} if (this.endHeight == 0 && this.cellIndex > 0) { this.x_now = this.cells[this.cellIndex].x_cell; this.y_now = this.cells[this.cellIndex].y_cell;

} if (this.cellIndex == 0) { this.x_now = this.firstX; this.y_now = this.firstY; if (this.beginHeight > 0) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.x_now + this.flag_x * this.beginHeight, this.y_now + this.flag_y * this.beginHeight);

} this.x_now += this.flag_x * (this.beginHeight + this.LineHeight); this.y_now += this.flag_y * (this.beginHeight + this.LineHeight);

} while ((Math.abs(this.x_now - this.destination.x_d) >= this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.y_now - this.destination.y_d) >this.LineHeight * Math.abs(this.flag_y))||(Math.abs(this.x_now - this.destination.x_d) > this.LineHeight * Math.abs(this.flag_x) && Math.abs(this.y_now - this.destination.y_d) >=this.LineHeight * Math.abs(this.flag_y))) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.x_now + this.flag_x * this.LineHeight, this.y_now + this.flag_y * this.LineHeight); this.x_now += this.flag_x * this.LineHeight; this.y_now += this.flag_y * this.LineHeight; if (Math.abs(this.x_now - this.destination.x_d)<= this.LineHeight * Math.abs(this.flag_x)&&Math.abs(this.y_now - this.destination.y_d) <= this.LineHeight * Math.abs(this.flag_y)) {

myEnd = true; break;

} else { this.x_now += this.flag_x * this.LineHeight; this.y_now += this.flag_y * this.LineHeight;

}

} if (myEnd == false && Math.abs(this.x_now - this.destination.x_d) < this.LineHeight * Math.abs(this.flag_x) || Math.abs(this.y_now - this.destination.y_d) < this.LineHeight * Math.abs(this.flag_y)) {

canvas.moveTo(this.x_now, this.y_now);

canvas.lineTo(this.destination.x_d, this.destination.y_d);

}

}

}

canvas.stroke();

canvas.closePath();

}

取水泵房的实例

下面代码在定义了一个水池对象,并赋予了相应的属性值,最后将定义的对象添加到canvas画布中。var SC01 = canvas.display.SC_show({ x: 326, y: 200,

Width: 181,

Height: 438,

height_now: 0,

trail_flag: 0,

t: 0,

fill: color_SC,

speed:speed_SC,

full:0,

start:0

});canvas.addChild(SC01);

下面的代码定义了一个管道对象,并且给管道对象赋予了一些初始值,最后添加到canvas画布中。var GD01 = canvas.display.GD({ x: 0, y: 0,

destination: {

x_d: 0, y_d: 0

},

cells: [

{x_cell: 195, y_cell: 587},

{x_cell: 335, y_cell: 587}

],

deta: 1,

deta_x: 1,

deta_y: 0,

flag_x: 1,

flag_y: 0,

cellIndex: 0,

Speed: speed_all,

GDwidth: width_all,

LineHeight: 10,

x_now: 0,

y_now: 0,

firstX: 0,

firstY: 0,

beginHeight: 0,

endHeight: 0,

legacyHeight: 0,

paused: 1,

fill:color_GD,

full:0

});

canvas.addChild(GD01);

具体动画的流程控制如下:canvas.setLoop(function () {

//下面6个advance函数实现每一帧中的动画对象的更新操作

GD01.advance();

SC01.advance();

SC02.advance();

GD02.advance();

SC03.advance();

GD03.advance();

//下面几个if语句实现动画的流程控制

if(GD01.full==1){

SC01.start = 1;

SC02.start = 1;

}

if(SC02.full==1){

GD02.paused = 1;

}

if(GD02.full==1) {

SC03.start = 1;

arrow_1.start();

arrow_2.start();

}

if(SC03.full==1) {

GD03.paused = 1;

}

canvas.redraw();  //重绘画布

}).start();       //循环开始

【相关推荐】

html5水池,分享用canvas实现水流和水池动画的代码相关推荐

  1. c语言烟花生日快乐图片,html5 canvas生日快乐文字烟花背景动画特效代码下载

    特效描述:生日快乐 文字烟花 背景动画.html5基于canvas绘制酷炫的烟花动画,支持文字烟花适用于生日快乐主题网页动态背景特效. 代码结构 1. 引入JS 2. HTML代码 var canva ...

  2. html5 图片弹跳,html5 canvas画布里面圆球弹跳动画效果代码

    特效描述:html5 canvas 画布 圆球弹跳动画.html5 跳动的球体 代码结构 1. HTML代码 Untitled Document body { margin: 0px; } var i ...

  3. 苹果html5跑分排行,UC浏览器HTML5跑分创新高 升全球第一

    随着移动互联网的不断发展,HTML5正以其出色的Web表现能力和强大的技术优势,逐渐成为移动互联网下一代的协议标准,而众多浏览器厂商也将HTML5评分作为旗下浏览器性能的一项重要指标.记者了解到,今天 ...

  4. html5 canvas雨点打到窗玻璃动画

    html5 canvas雨点打到窗玻璃动画 HTML5下雨效果 效果预览:http://hovertree.com/texiao/html5/4.htm 以下是代码: 1 <!doctype h ...

  5. 在HTML5中如何利用Canvas处理并存储图片

    HTML5中增加的Canvas元素,配合JS灵活的语法,处理起图片变得异常简单,不需要在客户端用C/C 写一大堆代码,对于熟悉JS的程序员来说,只需要考虑处理图片的逻辑了. canvas中如果想要处理 ...

  6. 分享用Adobe Air向iOS移植游戏的经验

    分享用Adobe Air向iOS移植游戏的经验 http://gamerboom.com/archives/47931 发布时间:2012-02-21 17:04:42 Tags:Adobe Air, ...

  7. html5两条直线,Html5新特性用canvas标签画多条直线附效果截图

    下面例子为用canvas标签画多条直线 复制代码代码如下: index_three 您的浏览器不支持canvas标签. //获取Canvas对象(画布) var canvas = document.g ...

  8. html5 canvas 椭圆,html5中怎么利用Canvas绘制椭圆

    html5中怎么利用Canvas绘制椭圆 发布时间:2021-07-08 16:32:10 来源:亿速云 阅读:58 作者:Leah html5中怎么利用Canvas绘制椭圆,针对这个问题,这篇文章详 ...

  9. HTML5教程实例-用Canvas制作线性渐变图形

    HTML5教程实例-用Canvas制作线性渐变图形 到目前为止,我们使用canvas绘制图形的基本知识已经介绍完毕,从本节开始,我们将介绍其他比较高级的绘制知识之一 - 线性渐变,首先我们来回顾一下& ...

最新文章

  1. nginx 学习笔记(5) nginx调试日志
  2. android怎么将editext的文本,android – 如何将文本添加到editext
  3. 使用RestTemplate访问restful服务时遇到的问题
  4. python哪个专业开这个课程-深圳python课程
  5. Camera Shutter Sound can't restore to default
  6. 《写给大家看的面向对象编程书》读书介绍
  7. 类数组变量定义与初始化
  8. 计算机漏洞英语怎么说,漏洞英文,漏洞英文发音bug。
  9. mysql数据库管理与开发pdf_深入浅出mysql数据库开发、优化与管理维护.pdf
  10. 海思烧录工具Hitool使用方法
  11. Oracle LOB 详解
  12. python|excel分列--部分分列(pandas,concat)
  13. python中的关系运算符可以连续室友_在Python中,关系运算符可以连续使用,例如135等价于13 and 35。...
  14. 【python】pickle
  15. 使用 Excel 和 Math.Net 进行曲线拟合和数据预测
  16. Python全栈-magedu-2018-笔记13
  17. 如何让Fresco支持HEIF/HEIC图片格式
  18. Android 忆童年 DVD 待机动画
  19. appvlv中偶有不爽
  20. 牛客算法課 (算法入門班) 二分, 三分, 01分數規劃

热门文章

  1. 【笔记】【机器学习基础】网格搜索
  2. 华为手机计算机算多少的n次方如何操作,华为手机必会的5个长按技巧,每天都要用上几次,真的太好用了!...
  3. 《麦兜故事》竟然还要插入字幕后才可以看!
  4. 避免无线路由器信道干扰 导致连接不稳定或者速度慢
  5. 今日学到:day 1
  6. 如何修改系统默认店招的背景及其样式?
  7. 软工作业4:用户体验分析:以 “师路南通网站” 为例
  8. js实现获取两个日期之间所有月份
  9. 线性插值c语言函数,CG中线性插值的基础-仿射函数(affine function)的基础知识解释...
  10. java中generics的作用,java中泛型(Generics)的一些理解