用canvas畫一顆花心

jopen 8年前發布 | 9K 次閱讀 前端技術

一、心形函數

function getHeartPoint(angle) {/*agnle=10*/
    var t = angle / Math.PI;
    var x = 19.5 * (16 * Math.pow(Math.sin(t), 3))*chen;
    var y = - 20 * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t))*chen;
    return {x:offsetX + x, y:offsetY + y};
}

二、用貝葉斯曲線畫出花朵

function Vector(x,y){
    this.x=x;
    this.y=y;
}
Vector.prototype={
    rotate:function(theta){
        var x = this.x;
        var y = this.y;
        this.x = Math.cos(theta) * x - Math.sin(theta) * y;
        this.y = Math.sin(theta) * x + Math.cos(theta) * y;
        return this;
    },
    mult:function(f){
        this.x *= f;
        this.y *= f;
        return this;
    },
    clone:function(){
        return new Vector(this.x,this.y);
    }
}

function Petal(xadd,yadd,startAngle,angle,grow){
    this.xadd=xadd;
    this.yadd=yadd;
    this.startAngle=startAngle;
    this.angle=angle;
    this.grow=grow;
    this.r=1;
}

Petal.prototype={
    draw:function(){/*r控制里面空白的大小,angle控制花瓣的數量,startAngle控制起始花瓣的位置,mult方法用來計算出兩個控制點的位置*/
        var v1, v2, v3, v4;
        v1 = new Vector(0, this.r).rotate(this.startAngle * 2 * Math.PI /360);
        v2 = v1.clone().rotate(this.angle * 2 * Math.PI /360);
        v3 = v1.clone().mult(this.xadd); //.rotate(this.tanAngleA);
        v4 = v2.clone().mult(this.yadd); //.rotate(this.tanAngleB);

        ctx.strokeStyle = 'rgba('+getRandInt(128,255)+','+getRandInt(0,128)+','+getRandInt(0,128)+',0.1)';
        ctx.beginPath();
        ctx.lineWidth=1;
        ctx.moveTo(v1.x, v1.y);
        ctx.bezierCurveTo(v3.x, v3.y, v4.x, v4.y, v2.x, v2.y);
        ctx.stroke();
    },
    update:function(){
        if(this.r<=10){
            this.draw();
            this.r+=this.grow;
        }else{
            petals.splice(petals.indexOf(this),1);
        }
    }
}

/*頁面加載時啟動動畫*/
window.onload=function(){
    ctx.translate(200, 200);
    //ctx.globalCompositeOperation='lighter';
    for(var i=0;i<count;i++){
        var p=new Petal(getRandInt(3,8),getRandInt(3,8),startAngle,angle,getRand(0.3,0.5));
        petals.push(p);
        startAngle+=angle;
        p.update();
    }
    setInterval(function(){
        for(var i=0;i<petals.length;i++){
            petals[i].update();
        }
    },100);
}

三、把花朵繪到心形函數的路徑上,最終代碼

var cas=document.getElementById('cas'), ctx=cas.getContext('2d');
cas.width=600;
cas.height=700,
count=getRandInt(8,15),
angle=360/count,
petals=[],
startAngle=getRandInt(0,90),
chen=0.8,
offsetX=300,
offsetY=300,
dots=[],
timer1=0,
timer2=0;

window.onload=function(){

    var vector={},i=10;
    timer1=setInterval(function(){
        vector=getHeartPoint(i);
        dots.push(new Dot(vector.x,vector.y));
        if(i<30){
            i+=0.3
        }else{
            clearInterval(timer1);
        }
    },100);

    timer2=setInterval(function(){
        for(var i=0;i<dots.length;i++){
            dots[i].draw();
        }
    });
}

function Dot(x,y){
    this.transX=x;
    this.transY=y;
    this.petals=[];
    this.init();
}
Dot.prototype={
    init:function(){
        for(var i=0;i<count;i++){
            var color=getRGBA(255,128,128,0,128,0,0.1);
            var p=new Petal(getRandInt(1,5),getRandInt(1,5),startAngle,angle,getRand(0.1,0.5),color);
            this.petals.push(p);
            startAngle+=angle;
            //p.update();
        }
    },
    draw:function(){
        ctx.save();
        ctx.translate(this.transX, this.transY);
        for(var i=0;i<this.petals.length;i++){
            this.petals[i].update();
        }
        ctx.restore();
    }
}

function rgbaStr(r, g, b, a) {
        return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
    };
function getRGBA(rmin, rmax, gmin, gmax, bmin, bmax, a) {
    var r = Math.round(getRand(rmin, rmax));
    var g = Math.round(getRand(gmin, gmax));
    var b = Math.round(getRand(bmin, bmax));
    var limit = 5;
    if (Math.abs(r - g) <= limit && Math.abs(g - b) <= limit && Math.abs(b - r) <= limit) {
        return rgbaStr(rmin, rmax, gmin, gmax, bmin, bmax, a);
    } else {
        return rgbaStr(r, g, b, a);
    }
};
function getHeartPoint(angle) {/*agnle=10*/
    var t = angle / Math.PI;
    var x = 19.5 * (16 * Math.pow(Math.sin(t), 3))*chen;
    var y = - 20 * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t))*chen;
    return {x:offsetX + x, y:offsetY + y};
}
function Vector(x,y){
    this.x=x;
    this.y=y;
}
Vector.prototype={
    rotate:function(theta){
        var x = this.x;
        var y = this.y;
        this.x = Math.cos(theta) * x - Math.sin(theta) * y;
        this.y = Math.sin(theta) * x + Math.cos(theta) * y;
        return this;
    },
    mult:function(f){
        this.x *= f;
        this.y *= f;
        return this;
    },
    clone:function(){
        return new Vector(this.x,this.y);
    }
}

function Petal(xadd,yadd,startAngle,angle,grow,color){
    this.xadd=xadd;
    this.yadd=yadd;
    this.startAngle=startAngle;
    this.angle=angle;
    this.grow=grow;
    this.c=color;
    this.r=1;
}

Petal.prototype={
    draw:function(){/*r控制里面空白的大小,angle控制花瓣的數量,startAngle控制起始花瓣的位置,mult方法用來計算出兩個控制點的位置*/
        var v1, v2, v3, v4;
        v1 = new Vector(0, this.r).rotate(this.startAngle * 2 * Math.PI /360);
        v2 = v1.clone().rotate(this.angle * 2 * Math.PI /360);
        v3 = v1.clone().mult(this.xadd); //.rotate(this.tanAngleA);
        v4 = v2.clone().mult(this.yadd); //.rotate(this.tanAngleB);
        ctx.beginPath();
        ctx.strokeStyle = this.c;
        console.log(ctx.strokeStyle);

        ctx.lineWidth=1;
        ctx.moveTo(v1.x, v1.y);
        ctx.bezierCurveTo(v3.x, v3.y, v4.x, v4.y, v2.x, v2.y);
        ctx.stroke();
    },
    update:function(){
        if(this.r<8){
            this.draw();
            this.r+=this.grow;
        }else{
            petals.splice(petals.indexOf(this),1);
        }
    }
}

function getRandInt(min,max){
    return Math.floor(Math.random()*(max-min)+min);
}
function getRand(min,max){
    return Math.random()*(max-min)+min;
}


來自: http://my.oschina.net/codespring/blog/596311

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!