2015-10-28 3 views

ответ

2

Ну, я не знаю, какой язык вам нужен, поэтому Javascript это, но принципы одинаковы для любого SDK или языка, который вы используете.

Прост в использовании. Используйте requestAnimationFrame, чтобы сделать его гладким. Создайте набор фигур, из которых вы можете анимировать каждый, и просто нарисуйте их в контексте canvas как обычно, используя moveTo, lineTo или любую необходимую вам функцию пути. Вместо того, чтобы называть позывной или штрих-вызов ctx.clip(), затем нарисуйте изображение, и оно будет отображаться только в областях отсечения.

Ниже приведен пример довольно утомительный, но он даст вам основы, вы можете улучшить его в соответствии с вашими потребностями.

var canvas = document.getElementById("canV"); // get the canvas 
 
var ctx = canvas.getContext("2d"); // get the context 
 
var blobs = []; // array to hold blobs 
 
var width = canvas.width; 
 
var height = canvas.height; 
 
var blobPCount = 16; // how bumpy the blobs are 
 
var wobbla = 0; // adds a bit of a wobble 
 
var growSpeed = 2; // grow speed 0.1 very slow 10 mega fast 
 
var cludgeFactor = 0.25; // used to work out when its all done 
 
var cludgeFactorA = 1-cludgeFactor; // its a bit of a cludge hence the name 
 
// a wiki commons image 
 
var imageURL = "https://upload.wikimedia.org/wikipedia/commons/e/ee/Baby_Cuttlefish2_%285589806913%29.jpg"; 
 
var image = new Image(); // create the image 
 
image.src = imageURL; // load it 
 
var done = false; // flag is true when done 
 

 

 
function addBlob(){ // adds a blob 
 
    var b = {}; 
 
    b.x = Math.random()*width; // find a random pos for it 
 
    b.y = Math.random()*height; 
 
    b.points = [];  // create a set of pointy in a circle that will grow outward 
 
    for(var i = 0; i < Math.PI*2;i+= (Math.PI*2)/blobPCount){ 
 
     var p = {}; 
 
     // mess up the perfection a little 
 
     var dir= (i+((Math.PI*2)/(blobPCount*3))*(Math.random()-0.5))*(1+2/blobPCount); 
 
     p.dx = Math.cos(dir); // the delta x and y 
 
     p.dy = Math.sin(dir); 
 
     p.x = p.dx * 5;  // the starting size 
 
     p.y = p.dy * 5; 
 
     p.dx *= growSpeed; // set the speed 
 
     p.dy *= growSpeed; 
 
     b.points.push(p); // add the point 
 

 
    } 
 
    blobs.push(b); // and the blob 
 
} 
 

 
function growBlobs(){ // grows the blob 
 
    var i; 
 
    for(i = 0; i < blobs.length; i++){ // for each blob 
 
     var b = blobs[i]; 
 
     var pc = b.points.length; 
 
     for(var j = 0; j < pc; j++){ // grow the points 
 
      var p = b.points[j]; 
 
      p.x += p.dx+p.dx*Math.random()*0.2; // move the point with a liitle random 
 
      p.y += p.dy+p.dy*Math.random()*0.2; 
 
     } 
 
    } 
 
} 
 

 
// creates the clipping mask 
 
function createClipMask(){ 
 
    var i; 
 
    ctx.beginPath(); // begin a path 
 
    wobbla += 0.2; // add some wobbla 
 
    var inside = false; // the flag to test done 
 
    
 
    for(i = 0; i < blobs.length; i++){ // for each blob 
 
     var b = blobs[i]; 
 
     var pc = b.points.length;  // get len 
 
     for(var j = 0; j < pc-1; j++){ // do eacj point 
 
      var p = b.points[j]; 
 
      var x = b.x+p.x + Math.sin(wobbla+i+j*0.2)*10; // get a point 
 
      var y = b.y+p.y + Math.cos(wobbla+i+j*0.2)*10; 
 
      if(j === 0){ 
 
       ctx.moveTo(x,y); // move to the first point 
 
      }else{ 
 
       j ++; // all other points as a second order bexier 
 
       p = b.points[j]; 
 
       var x1 = b.x +p.x*0.75 + Math.sin(wobbla+i+j*0.2)*10; // add the wobble 
 
       var y1 = b.y +p.y*0.75 + Math.cos(wobbla+i+j*0.2)*10; 
 
       ctx.quadraticCurveTo(x,y,x1,y1); // create tke bezier path 
 
       // test if the points are inside the screen by cludge factor 
 
       if(!inside && x > width*cludgeFactor && x < width*cludgeFactorA && 
 
        y > height*cludgeFactor && y < height*cludgeFactorA){ 
 
        inside = true; 
 

 
       } 
 
       
 
      } 
 
     } 
 
     ctx.closePath(); // done with this blob close the path 
 
    } 
 
    // all blobs done so set the clip 
 
    ctx.clip(); 
 
    if(!inside){ // if no points inside the cludge area the we are done 
 
     done = true; 
 
    } 
 
    
 
} 
 

 
// make a semi random number of blobs 
 
var numberBlobs = Math.ceil(Math.random()^5) +3; 
 
for(var i = 0; i < numberBlobs; i++){ 
 
    addBlob(); 
 
} 
 
// do the update 
 
function update(){ 
 
    if(done){ // if done draw the image 
 
     ctx.drawImage(image,0,0,width,height); 
 
     return; // return stops the rendering 
 
    } 
 
    ctx.fillStyle = "white"; // draw the white 
 
    ctx.fillRect(0,0,width,height); 
 
    ctx.save(); // save the current ctx state 
 
    if(image.complete){ // has the image loaded 
 
     growBlobs(); // yes so grow blobs 
 
     createClipMask(); // create the clip 
 
     ctx.drawImage(image,0,0,width,height); //draw the clipped image 
 
    } 
 
    ctx.restore(); // dont need the clip anymore so restore the ctx state 
 
    window.requestAnimationFrame (update); //request a new anim frame 
 

 
} 
 
update(); // start it all going
.canC { 
 
    width:500px; 
 
    height:400px; 
 
}
<canvas class="canC" id="canV" width=500 height=400></canvas>

Кроме того, я должен был догадаться, что вы хотели, так надеюсь, что я угадал. Любой вопрос, пожалуйста, спросите.

+1

Приятное прикосновение с колебанием! :-) – markE

+0

спасибо. –

Смежные вопросы