动画是将静止的画面变为动态的艺术.实现由静止到动态,主要是靠人眼的视觉残留效应。视觉残留也叫视觉暂留现象,物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像0.1~0.4秒左右的图像,这种现象被称为视觉暂留现象。利用人的这种视觉生理特性可制作出具有高度想象力和表现力的动画影片。

电影的拍摄和放映就是视觉残留效应的具体应用。

大家可能看过组成电影的实际胶片。从表面上看,它们像一堆画面串在一条塑料胶片上。每一个画面称为一帧,代表电影中的一个时间片段。这些帧的内容总比前一帧有稍微的变化,这样,当电影胶片在投影机上放映时就产生了运动的错觉:每一帧都很短并且很快被另一个帧所代替,这样就产生了运动。

通过循环绘制各帧的图像就可以实现动画的效果。

在Canvas画布中制作动画相对来说很简单,实际上就是绘制帧(图形或图像)、擦除、重绘的过程。也就是说,在Canvas中模拟一个动画过程就是每隔一定时间绘制图形并且清除图形,通过定时循环操作实现。

1.定时循环操作的三个函数

对于动画,需要在一段时间内渲染不同的帧,各帧间隔一定的时间在画布中依次被绘制。为完成定时循环操作帧,可以利用etInterval()、setTimeout()和requestAnimationFrame()这三个函数之一。

(1)setTimeout()方法。

setTimeout() 方法是HTML DOM Window对象的一个方法,它用于在指定的毫秒数后调用函数或计算表达式。其调用格式为:

setTimeout(code,millisec);

其中,参数code表示要调用的函数或要执行的代码串,millisec表示在执行代码前需等待的毫秒数。

例如,setTimeout(“draw()”,1000)表示延时1秒后执行函数draw中的代码。

编写如下的HTML文件。

<!DOCTYPE html>

<html>

<head>

<title>setTimeout方法的应用</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

function draw(x,y,len,color)

{

ctx.fillStyle = color;

ctx.fillRect(x,y,len,len);

}

setTimeout("draw(10,10,100,'red')",1000);

setTimeout("draw(110,110,200,'blue')",5000);

</script>

</body>

</html>

在浏览器中打开保存这段HTML代码的html文件,则等待1秒后,会绘制一个边长为100的红色正方形,再等待5秒,绘制一个边长为200的蓝色正方形。

通过这个例子可以知道:(1)setTimeout()方法可以用于延时;(2)setTimeout()方法只执行code一次。如果要多次调用,则需要让code 自身再次调用 setTimeout()。

为产生动画效果,显然得让setTimeout()方法多次执行。修改上面的HTML代码如下。

<!DOCTYPE html>

<html>

<head>

<title>setTimeout方法的应用</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var i=0;

function move()

{

ctx.fillStyle = 'red';

ctx.fillRect(i,i,50,50);

i++;

if (i==350)

{

i=0;

ctx.clearRect(0,0,400,400);

}

setTimeout("move()",10);

}

move();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到一个简单的箭头伸出动画,如图1所示。

图1  简单的动画

(2)setInterval() 方法。

setInterval()也是HTML DOM Window对象的一个方法,它可按照指定的周期(以毫秒计)来调用函数或计算表达式。其调用格式为:

setInterval(code,millisec);

其中,参数code表示要调用的函数或要执行的代码串, millisec表示周期性执行或调用 code 之间的时间间隔(以毫秒计)。

setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

clearInterval() 方法可取消由 setInterval() 设置的 timeout。其调用形式为:

clearInterval(id_of_setinterval);

其中参数id_of_setinterval必须是由 setInterval() 返回的 ID 值。

若用setInterval() 方法实现图1所示的动画,则编写的HTML文件如下。

<!DOCTYPE html>

<html>

<head>

<title>setInterval()方法的应用</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var i=0;

function move()

{

ctx.fillStyle = 'red';

ctx.fillRect(i,i,50,50);

i++;

if (i==350)

{

i=0;

ctx.clearRect(0,0,400,400);

}

}

setInterval("move()",10);

</script>

</body>

</html>

(3)requestAnimationFrame()方法。

requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。

编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能保证不同的动画效果显得更平滑流畅;另一方面,循环间隔还要足够长,这样才能保证浏览器有能力渲染产生的变化。大多数显示器的刷新频率是60Hz,相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过了这个频率,用户体验也不会有提升。

因此,最平滑动画的最佳循环间隔是1000ms/60,约等于17ms。以这个循环间隔重绘的动画是平滑的,因为这个速度最接近浏览器的最高限速。为了适应17ms的循环间隔,多重动画可能需要加以节制,以便不会完成得太快。

虽然setTimeout()方法和setInterval()方法均可完成定时循环操作,但setTimeout()和setInterval() 都不十分精确。为它们传入的第二个参数millisec,实际上只是指定了把动画代码添加到浏览器UI线程队列以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务执行完成后再执行。如果UI线程繁忙,比如忙于处理用户操作,那么即使把代码加入队列也不会立即执行。

确定什么时候绘制下一帧是保证动画平滑的关键。然而,面对不十分精确的 setTimeout()和setInterval(),开发人员至今都没有办法确保浏览器按时绘制下一帧。因此,采用setTimeout()和setInterval(),即使优化了循环间隔,可能仍然只能接近想要的效果。

引入requestAnimationFrame()方法的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。代码中使用requestAnimationFrame()方法,就是告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘。

requestAnimationFrame的优势在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。

不过有一点需要注意,requestAnimationFrame是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。

requestAnimationFrame使用一个回调函数作为参数。这个回调函数会在浏览器重绘之前调用。其调用格式为:

requestID = window.requestAnimationFrame(callback);

目前,主流浏览器(Firefox 23 / IE 10 / Chrome / Safari)都支持这个方法。可以用下面的方法,检查浏览器是否支持requestAnimationFrame。如果不支持,则自行模拟部署该方法。

window.requestAnimFrame = (function(){

return  window.requestAnimationFrame        ||

window.webkitRequestAnimationFrame  ||

window.mozRequestAnimationFrame    ||

window.oRequestAnimationFrame      ||

window.msRequestAnimationFrame     ||

function( callback ){

window.setTimeout(callback, 1000 / 60);

};

})();

上面的代码按照1秒钟60次(大约每16.7毫秒一次),来模拟requestAnimationFrame。

与 setTimeout() 和 setInterval() 方法不同,requestAnimationFrame( )不需要调用者指定帧速率,浏览器会自行决定最佳的帧效率。也就是说浏览器页面每次要重绘,就会通知requestAnimationFrame。如果浏览器绘制间隔是16.7ms,它就按这个间隔绘制;如果浏览器绘制间隔是10ms,它就按10ms绘制。这样就不会存在过度绘制的问题,动画不会丢帧。

另外,使用requestAnimationFrame()方法,一旦页面不处于浏览器的当前标签,就会自动停止刷新。例如,页面最小化了,页面是不会进行重绘的,requestAnimationFrame自然也不会触发(因为没有通知)。页面绘制全部停止,资源高效利用,节省了CPU、GPU和电力。

和setTimeout类似,requestAnimationFrame的回调函数只能被调用一次,并不能被重复调用(这点和setInterval不同)。因此,使用requestAnimationFrame的时候,同样需要反复调用它。

由于setTimeout可以自定义调用时间, requestAnimationFrame的调用时间则是跟着系统的刷新频率走的,所以在实现动画的时候,setTimeout比requestAnimationFrame更加灵活, requestAnimationFrame比setTimeout表现效果更加优秀。

若用requestAnimationFrame() 方法实现图1所示的动画,则编写的HTML文件如下。

<!DOCTYPE html>

<html>

<head>

<title>requestAnimationFrame方法的应用</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var i=0;

function move()

{

ctx.fillStyle = 'blue';

ctx.fillRect(i,i,50,50);

i++;

if (i==350)

{

i=0;

ctx.clearRect(0,0,400,400);

}

requestAnimationFrame(move);

}

move();

</script>

</body>

</html>

2.绘制简单图形实现动画

图1的动画就是从左上角坐标位置(0,0)开始,绘制一个边长为50的红色正方形,之后每隔10毫秒后将左上角坐标位置的水平和垂直坐标均增加1,再绘制一个正方形,从而得到一个简单的箭头伸出动画效果。

通过在画布中绘制简单图形,达到时间间隔后,擦除(有时候也可暂时不擦除)前次绘制的图形,重新绘制一个位置或大小略有变化的图形,这样就可得到动画效果。

例1  向中心交汇的箭头。

仿照图1动画思想略作变化,编写如下的HTML代码。

<!DOCTYPE html>

<html>

<head>

<title>向中心交汇的箭头</title>

<script type="text/javascript">

var i=0;

function draw(id)

{

var canvas = document.getElementById(id);

ctx = canvas.getContext('2d');

setInterval(painting,10);

}

function painting()

{

ctx.fillStyle = "green";

ctx.fillRect(i,i,10,10);

ctx.fillRect(400-i,400-i,10,10);

ctx.fillRect(i,400-i,10,10);

ctx.fillRect(400-i,i,10,10);

i++;

if (i==200)

{

ctx.clearRect(0,0,400,400);

i=0;

}

}

</script>

</head>

<body onload="draw('myCanvas')">

<canvas id="myCanvas" width="400" height="400"  style="border:3px double #996633;">

</canvas>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图2所示的动画。

图2  向中心交汇的箭头

例2  逐层向里绘制的圆。

<!DOCTYPE html>

<html>

<head>

<title>层层向内画的圆</title>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;"></canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var context = canvas.getContext('2d');

var flag=1;

var i=0;

var r=180;

function animate() {

window.requestAnimationFrame(animate);

draw();

}

function draw() {

var dig=Math.PI/120;

var x = Math.sin(i*dig)*r+200;

var y = Math.cos(i*dig)*r+200;

context.fillStyle = flag ? 'rgb(10,255,255)' : 'rgb(255,100,0)';

context.beginPath();

context.arc(x, y, 3, 0, Math.PI*2, true);

context.closePath();

context.fill();

i++;

if (i>240) {

i=0;

r=r-20;

flag = !flag;

if (r<=0) {

context.clearRect(0,0,canvas.width,canvas.height);

r=180;

}

}

}

animate();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图3所示的动画。

图3  层层向内画的圆

3.通过图形变换实现动画效果

在Canvas中,可以绘制一个基本图形,然后通过对这个基本图形使用平移、缩放和旋转等图形变换的方法实现动画效果。

例3  放大缩小的五角星。

<!DOCTYPE html>

<html>

<head>

<title>放大缩小的五角星</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

var x=200;

var y=200;

var radius=30;

var rot=0;

var dr=5;

function draw()

{

ctx.clearRect(0,0,canvas.width,canvas.height);

ctx.save();

ctx.translate(x,y);

ctx.rotate(rot/180*Math.PI);

ctx.scale(radius,radius);

ctx.beginPath();

for(var i=0;i<5;i++)   // 绘制标准五角星

{

ctx.lineTo(Math.cos((18+i*72)/180*Math.PI),-Math.sin((18+i*72)/180*Math.PI));

ctx.lineTo(Math.cos((54+i*72)/180*Math.PI)*0.5,-Math.sin((54+i*72)/180*Math.PI)*0.5);

}

ctx.closePath();

ctx.fillStyle="red";

ctx.fill();

ctx.restore();

radius+=dr;

if (radius>200 || radius<30)

dr=-dr;

}

setInterval("draw()",60);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图4所示的动画。这个动画效果的变化核心是语句“ctx.scale(radius,radius);”在起作用。

图4  放大缩小的五角星

若将上面程序段中,radius固定取值120,再修改变化语句

radius+=dr;

if (radius>200 || radius<30)

dr=-dr;

rot=(rot+2)%360;

则五角星会进行旋转,呈现出如图5所示的动画效果。

图5  旋转的五角星

4.遮罩动画

利用Canvas API提供的裁切方法clip(),可以用来实现遮罩动画。

例4  图片圆形展开后收缩。

<!DOCTYPE html>

<head>

<title>圆形展开后收缩</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var r=10;

var dr=5;

var canvas=document.getElementById('myCanvas');

var ctx=canvas.getContext('2d');

var image = new Image();

image.src = 'aaa.jpg';

image.onload=function(){

ctx.drawImage(image,0,0);

}

setInterval("draw()",100);

function draw()

{

ctx.clearRect(0,0,400,400);

ctx.save();

ctx.beginPath();

ctx.arc(200,200,r,0,Math.PI*2,true);

ctx.closePath();

ctx.fillStyle="white";

ctx.fill();

ctx.clip();

ctx.drawImage(image,0,0);

ctx.restore();

r=r+dr;

if (r>280) dr=-5;

else if (r<=0) dr=5;

}

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图6所示的动画。

图6  圆形展开后收缩

5.多个同类物体同时运动实现动画

有时候设计动画时,画布中会有多个同类物体按各自的规律进行运动,这时将各物体抽象为对象数组比较方便处理。

例3中我们通过图形变换的方法实现了五角星的放大和旋转。下面我们绘制60个五角星在画布上进行移动的动画效果。

例5  60个五角星随机移动。

为了描述60个五角星,抽象一个星星对象Star。为该对象定义五角星中心位置坐标(x,y)、五角星外接圆半径radius、水平方向移动速度speedX、垂直方向移动速度speedY和五角星旋转角度deg等6个属性。具体定义如下:

function Star()

{

this.x = randomNum(30,canvas.width-30);

this.y = randomNum(30,canvas.height-30);

this.radius=randomNum(8,12);

this.speedX = randomNum(-5,5);

this.speedY=randomNum(-5,5);

this.deg = randomNum(0,180);

}

为五角星对象定义两个方法,一个是update方法,更新五角星的坐标位置(x,y)并进行边界碰撞检查;一个方法是draw方法,按属性设置绘制出五角星。具体定义如下:

Star.prototype.update = function()

{

this.x += this.speedX;

this.y += this.speedY;

if (this.x-this.radius<=0)

{

this.speedX=-this.speedX;

this.x=this.radius;

}

if (this.x+this.radius>canvas.width)

{

this.speedX=-this.speedX;

this.x=canvas.width-this.radius;

}

if (this.y-this.radius<=0)

{

this.speedY=-this.speedY;

this.y=this.radius;

}

if (this.y+this.radius>canvas.height)

{

this.speedY=-this.speedY;

this.y=canvas.height-this.radius;

}

}

Star.prototype.draw = function()

{

ctx.beginPath();

for (var i = 0; i < 5; i ++)

{

ctx.lineTo( Math.cos( (18 + i*72 - this.deg)/180 * Math.PI) *this.radius + this.x,

-Math.sin( (18 + i*72 - this.deg)/180 * Math.PI) * this.radius + this.y)

ctx.lineTo( Math.cos( (54 + i*72 - this.deg)/180 * Math.PI) * this.radius/2+ this.x,

-Math.sin( (54 + i*72 - this.deg)/180 * Math.PI) * this.radius/2 + this.y)

}

ctx.closePath();

ctx.lineWidth = 3;

ctx.fillStyle = "#ff0000";

ctx.strokeStyle = "#ffff00";

ctx.lineJoin = "round";

ctx.fill();

ctx.stroke();

}

定义好五角星对象后,定义一个数组stars,保存60个五角星并设置动画过程。编写完整的HTML文件如下。

<!DOCTYPE html>

<html>

<head>

<title>满天都是小星星</title>

</head>

<body>

<canvas id="myCanvas" width="500" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

var canvas = document.getElementById('myCanvas');

var ctx = canvas.getContext('2d');

function Star()

{

this.x = randomNum(30,canvas.width-30);

this.y = randomNum(30,canvas.height-30);

this.radius=randomNum(8,12);

this.speedX = randomNum(-5,5);

this.speedY=randomNum(-5,5);

this.deg = randomNum(0,180);

}

Star.prototype.update = function()

{

this.x += this.speedX;

this.y += this.speedY;

if (this.x-this.radius<=0)

{

this.speedX=-this.speedX;

this.x=this.radius;

}

if (this.x+this.radius>canvas.width)

{

this.speedX=-this.speedX;

this.x=canvas.width-this.radius;

}

if (this.y-this.radius<=0)

{

this.speedY=-this.speedY;

this.y=this.radius;

}

if (this.y+this.radius>canvas.height)

{

this.speedY=-this.speedY;

this.y=canvas.height-this.radius;

}

}

Star.prototype.draw = function()

{

ctx.beginPath();

for (var i = 0; i < 5; i ++)

{

ctx.lineTo( Math.cos( (18 + i*72 - this.deg)/180 * Math.PI) *this.radius + this.x,

-Math.sin( (18 + i*72 - this.deg)/180 * Math.PI) * this.radius + this.y)

ctx.lineTo( Math.cos( (54 + i*72 - this.deg)/180 * Math.PI) * this.radius/2+ this.x,

-Math.sin( (54 + i*72 - this.deg)/180 * Math.PI) * this.radius/2 + this.y)

}

ctx.closePath();

ctx.lineWidth = 1;

ctx.fillStyle = "white";

ctx.strokeStyle = "#ffff00";

ctx.lineJoin = "round";

ctx.fill();

ctx.stroke();

}

function randomNum(min,max)

{

return Math.floor(Math.random()*(max-min+1)+min);

}

var stars = [];

for (var i = 0; i < 60; i++)

{

stars.push(new Star());

if (stars[i].speedX==0 && stars[i].speedY==0)

stars[i].speedX=stars[i].speedY=1;

}

function move()

{

ctx.clearRect(0,0,canvas.width,canvas.height);

ctx.fillStyle="blue";

ctx.fillRect(0,0,canvas.width,canvas.height);

for (var i = 0; i <60; i++)

{

stars[i].draw();

stars[i].update();

}

}

setInterval("move()",10);

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图7所示的动画。

图7  星星在运动

例6  下雪了。

简单模拟下雪场景,编写如下的HTML文件。在屏幕中最多有100片雪花,每片雪花绘制一个小圆表示,从画布顶端开始往下落。由于动画过程一直在循环,因此每当一片雪花落出画布之外后,随机为其赋予水平坐标、置垂直坐标置为0、并随机设置其圆半径和下落速度,表示这是一片新雪花。这样,用一个具有100个元素的数组即可保存屏幕中下落雪花的信息。

<!DOCTYPE html>

<html>

<head>

<title>下雪了</title>

</head>

<body>

<canvas id="myCanvas" width="300" height="300" style="border:3px double #996633;">

</canvas>

<script>

var canvas=document.getElementById('myCanvas');

var ctx=canvas.getContext('2d');

var particles = [];

function loop()

{

createParticles();

downParticles();

drawParticles();

window.requestAnimationFrame(loop);

}

window.requestAnimationFrame(loop);

function createParticles()

{

if(particles.length <100)

{

particles.push({

x: Math.random()*canvas.width,

y: 0,

speed: 2+Math.random()*3,

radius: 3+Math.random()*4,

});

}

}

function downParticles()

{

for(var i in particles)

{

var part = particles[i];

part.y += part.speed;

if(part.y > canvas.height)

{

part.x=Math.random()*canvas.width;

part.y=0;

part.speed=2+Math.random()*3;

part.radius=3+Math.random()*4;

}

}

}

function drawParticles()

{

ctx.fillStyle = "black";

ctx.fillRect(0,0,canvas.width,canvas.height);

for(var i in particles)

{

var part = particles[i];

ctx.beginPath();

ctx.arc(part.x,part.y, part.radius, 0, Math.PI*2);

ctx.closePath();

ctx.fillStyle = "white";

ctx.fill();

}

}

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中看到如图8所示的动画。

图8  下雪了

JavaScript动画基础:canvas绘制简单动画的更多相关文章

  1. 学习笔记:HTML5 Canvas绘制简单图形

    HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...

  2. canvas绘制简易动画

    在canvas画布中制作动画相对来说很简单,实际上就是不断变化的坐标.擦除.重绘的过程 1.使用setInterval方法设置动画的间隔时间. setInterval(code,millisec) s ...

  3. canvas制作简单动画

    在画布元素<canvas>中,除了绘制图形.图像.文字外,还可以制作一些简单的动画,制作过程十分简单,主要分为两步操作: 1.自定义一个函数,用于图形的移动或其他动作. 2.使用setIn ...

  4. 学习Canvas绘图与动画基础 canvas入门(一)

    一.创建canvas 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta char ...

  5. 使用Canvas绘制简单的时钟控件

    Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表.动画等. 没有Canvas的年代,绘图只能借助Flash插件实现,页面不得不用JavaScript和F ...

  6. canvas绘制简单的霓虹灯效果

    canvas简单动画分为三个步骤: 1.清除画布区域的内容: 2.重绘: 3.执行requestAnimationFrame(); 这个霓虹灯效果的demo,我没有用requestAnimationF ...

  7. 怎样用JavaScript和HTML5 Canvas绘制图表

    原文:https://code.tutsplus.com/zh-...原作:John Negoita翻译:Stypstive 在这篇教程中,我将展示用JavaScript和canvas作为手段,在饼状 ...

  8. canvas绘制简单图形

    canvas绘图篇: canvas绘制矩形: <!DOCTYPE html> <html> <head lang="en"> <meta ...

  9. canvas绘制简单小铅笔

    对应HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...

随机推荐

  1. 2019-02-09 python爬取mooc视频项目初级简单版

    今天花了一下午时间来做这东西,之前没有自己写过代码,50几行的代码还是查了很多东西啊,果然学起来和自己动起手来完全是两码事. 方案:requests库+正则表达式提取视频下载链接+urlretriev ...

  2. (六)TestNg中的软断言和硬断言

    原文链接:https://cloud.tencent.com/developer/article/1479172 前言 在执行自动化测试脚本的时候,我们需要自动判断测试脚本执行完成后的实际结果是否与预 ...

  3. spring Cloud网关之Spring Cloud Gateway

    Spring Cloud Gateway是什么?(官网地址:https://cloud.spring.io/spring-cloud-gateway/reference/html/) Spring C ...

  4. opencv C++矩阵操作

    int main(){ cv::Mat src1=(cv::Mat_<float>(2,3)<<1,2,3,4,5,6); cv::Mat src2=(cv::Mat_< ...

  5. 客户端软件GUI开发技术漫谈:原生与跨平台解决方案分析

    原生开发应用开发 Microsoft阵营的 Winform WinForm是·Net开发平台中对Windows Form的一种称谓. 如果你想深入的美化UI,需要耗费很大的力气,对于目前主流的CSS样 ...

  6. centos 6.5 nat方式上网络设置

    1 前提虚拟机采用nat的方式和主机进行通信,这个时候再电脑上会模拟一个vmnet8网卡,如果是host-only对应的是vmnet1,配置一样 vmnet8的虚拟网卡,虚拟机通过vmnet8和主机之 ...

  7. SSH网上商城二

    1.实现的功能如下 当用户登陆成功之后,在首页显示所有的一级分类 显示热门商品 显示最新商品 当用户点击某个一级分类的菜单选项的时候,显示当前一级分类菜单项下所有的二级分类,并且按照分页的形式显示该二 ...

  8. 恕我直言你可能真的不会java第9篇-Stream元素的匹配与查找

    在我们对数组或者集合类进行操作的时候,经常会遇到这样的需求,比如: 是否包含某一个"匹配规则"的元素 是否所有的元素都符合某一个"匹配规则" 是否所有元素都不符 ...

  9. JAVA设计模式 4【创建型】理解建造者模式

    Hello,又是拖了几天更,实在是忙的要死,有时候忙累了,真的就是倒头睡的那种,刚好今天闲下来了.今天来更新一篇建造者模式. 其实建造者模式,我们已经在上一节已经有了解过了.只不过是上一节没有提到这样 ...

  10. 数据库管理与迁移(Liquibase)

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...