Вот ответ, который вы хотели о выращивании волос.
Здесь также есть информация, которую вы хотели, о том, как создать «объект» для волос.
Код и скрипка: http://jsfiddle.net/m1erickson/8K825/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
window.requestAnimationFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
// the Hair "object"
// Hair is a containing object that hosts a user-specified # of hairs
var Hair = (function () {
// constructor
function Hair(x,y,width,height,haircount) {
this.x=x;
this.y=y;
this.width=width;
this.height=height;
this.right=this.x+this.width;
this.bottom=this.y+this.height;
this.hairCount=haircount;
this.startX=x+20;
this.startY=y+height-3; //235;
this.hairHeight=25;
this.hairGrowth=0;
this.lastEndX=[];
for(var i=0;i<haircount;i++){
this.lastEndX[i]= x+20+(i*15);
}
}
// grows the hair
// works by changing the Y value of the end & control points
Hair.prototype.grow = function(increment){
this.hairGrowth+=increment;
return(this.hairGrowth);
}
// draw all the hairs
Hair.prototype.draw = function(mouseX){
// clear this object's space on the canvas
// and set its styles
ctx.clearRect(this.x,this.y,this.width,this.height);
ctx.beginPath();
ctx.strokeStyle="grey";
ctx.lineWidth=7;
ctx.lineCap = 'round';
ctx.beginPath();
for(var i=0;i<this.hairCount;i++){
// straight hair
var sx=cp1x=cp2x= this.startX+(i*15);
var sy= this.startY;
var cp1y = cp2y = (this.startY-(this.hairHeight+this.hairGrowth)/2);
var endy = this.startY-this.hairHeight-this.hairGrowth;
var endx = this.lastEndX[i];
// create bend, if any
if(Math.abs(mouseX-sx)<=10){
endx = sx+(mouseX-sx)*1.1;
this.lastEndX[i]=endx;
};
// draw this curve
ctx.moveTo(sx,sy);
ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,endx,endy);
}
// stroke
ctx.stroke();
// temp outline
ctx.lineWidth=1;
ctx.beginPath();
ctx.rect(this.x,this.y,this.width,this.height);
ctx.stroke();
}
//
return Hair;
})();
var direction=1;
var fps = 3;
function animate() {
setTimeout(function() {
// change hair length
var hairLength=hair.grow(direction);
if(hairLength<1 || hairLength>10){ direction=(-direction); }
// draw
hair.draw();
// request next frame
requestAnimationFrame(animate);
}, 1000 / fps);
}
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
$("#movelog").html("Move: "+ mouseX + " / " + mouseY);
// Put your mousemove stuff here
if(mouseX>=hair.x && mouseX<=hair.right && mouseY>=hair.y && mouseY<=hair.bottom){
hair.draw(mouseX);
}
}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#grow").click(function(e){ animate(); });
// create a new patch of hair
var hair=new Hair(25,50,150,50,8);
hair.draw(225);
}); // end $(function(){});
</script>
</head>
<body>
<p id="movelog">Move</p>
<canvas id="canvas" width=300 height=200></canvas><br>
<button id="grow">Grow Hair</button>
</body>
</html>
[Добавлено: объяснение «Класса» и создания экземпляра объекта из класса]
var Hair=(function(){ …; return Hair; })()
создает «класс» Hair.
var hair = new Hair(…)
создает настоящий, пригодный для использования «объект» Hair.
Думайте о классе Hair как о шаблоне (или чертеже, или шаблоне). Весь код внутри класса Hair определяет только свойства и методы класса. На самом деле вы не вызываете какой-либо код в классе Hair. Вы просто используете его как шаблон для создания реальных объектов волос.
Вы можете использовать класс Hair для создания любого количества реальных объектов волос — его можно использовать повторно. Акт создания объекта волос известен как «создание экземпляра класса Hair».
Кстати, в javascript на самом деле нет классов, так что это просто псевдокласс. Но это совсем другое объяснение!
Вы спросите: какая польза от direction=0,25?
Переменная направления используется для постепенного увеличения высоты волос, когда волосы «растут» во время анимации. .25 сообщает контрольным/конечным точкам волос подняться на 0,25 пикселя за кадр анимации.
Вы спросите: какое значение имеет функция обратного вызова и этот settimeout?
setTimeout
оборачивает requestAnimationFrame
, так что анимация происходит с фиксированной частотой кадров в секунду.
RequestAnimationFrame (RAF) отлично справляется с оптимизацией производительности, но вы не можете контролировать количество кадров в секунду только с помощью RAF. Если вы оберните RAF внутри setTimeout, вы сможете контролировать количество кадров в секунду. Например, setTimeout(anyFunction,1000/fps) будет запускать anyFunction примерно 3 раза в секунду, когда fps==3. См. эту замечательную статью о RAF+setTimeout: http://creativejs.com/resources/requestanimationframe/
Как вы обнаружили, RAF без setTimeout все равно будет работать, но RAF будет стараться отрастить ваши волосы как можно быстрее, а не с интервалом fps.
person
markE
schedule
14.06.2013