简体   繁体   English

用粒子画布填充形状

[英]Filling shape with particles canvas

Just wondering if anyone could point me in a good direction to a way I could fill an irregular shape with particles, in rows, which would then be animatable. 我只是想知道是否有人可以向我指出一个正确的方向,使我可以用粒子填充不规则形状的行,然后将其动画化。

This is the closest example i can find - http://www.wkams.com/#!/work/detail/coca-cola-music-vis 这是我能找到的最接近的示例-http://www.wkams.com/#!/work/detail/coca-cola- music - vis

The two ways I can think would work is work out the density I want, map out how many particles would be needed for each row, and position accordingly. 我认为可以工作的两种方法是计算所需的密度,绘制出每行需要多少个粒子,并相应地定位。 This way seems quite timely and not very robust. 这种方式似乎很及时,而且不是很可靠。

The second way, which I can't seem to figure out how I would do it, is draw the shape in the canvas, then generatively fill the shape with particles, keeping them in the constraints of the shape. 我似乎无法弄清楚该怎么做的第二种方法是在画布上绘制形状,然后用粒子生成填充形状,使它们处于形状约束中。

Any general concept of how this could be done would be greatly appreciated. 任何可以实现的一般概念将不胜感激。

Let me know if it doesn't make sense. 让我知道这是否没有道理。

Cheers 干杯

You can use compositing to restrict your particles inside an irregular shape 您可以使用合成将粒子限制为不规则形状

在此处输入图片说明在此处输入图片说明

For each loop of your animation: 对于动画的每个循环:

  • Clear the canvas. 清除画布。

  • Draw your irregular shape on the canvas. 在画布上绘制不规则形状。

  • Set compositing to 'source-atop'. 将合成设置为“源优先”。 This will cause any new drawings to appear only if any newly drawn pixel is over an existing opaque pixel . 仅当任何新绘制的像素位于现有不透明像素之上时,这才会导致出现任何新绘制 This is the secret to restricting your particles to be drawn only inside your irregular shape. 这是限制仅在不规则形状内绘制粒子的秘密。

  • Draw your rows of particles. 绘制一排粒子。 All particles will appear only inside the shape. 所有粒子只会出现在形状内部。

Here's example code and a Demo. 这是示例代码和演示。 My example just animates the size of each particle row. 我的示例只是为每个粒子行的大小设置动画。 You can apply your design requirements to change the size & position of each row. 您可以应用设计要求来更改每行的大小和位置。

 var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var cw=canvas.width; var ch=canvas.height; // ctx.fillStyle='skyblue'; var PI2=Math.PI*2; // var w=132; var h=479; // var x1=29; var x2=177; var x3=327; // var nextTime=0; var delay=16*2; var isFading=true; var isComplete=false; var opacity=100; var imgCount=2; var img=new Image();img.onload=start;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/coke.png"; var label=new Image();label.onload=start;label.src="https://dl.dropboxusercontent.com/u/139992952/multple/label.png"; function start(){ console.log(imgCount); if(--imgCount>0){return;} requestAnimationFrame(animate); $('#again').click(function(){ nextTime=0; delay=16*2; opacity=100; isFading=true; }); } function overlay(clipX,x,alpha){ ctx.globalAlpha=alpha; ctx.drawImage(img,clipX,0,w,h,x,0,w,h); } function fillParticles(radius,margin){ var rr=radius*2+margin; ctx.save(); ctx.clearRect(0,0,cw,ch); overlay(x3,50,1.00); ctx.globalCompositeOperation='source-atop'; ctx.beginPath(); var rows=parseInt(ch/(rr))-2; var cols=parseInt(cw/rr); for(var r=0;r<rows;r++){ for(var c=0;c<cols;c++){ ctx.arc(c*rr,h-(r*rr),radius,0,PI2); ctx.closePath(); }} ctx.fill(); ctx.restore(); overlay(x2,50,1.00); } function animate(time){ if(!isComplete){ requestAnimationFrame(animate); } if(time<nextTime){return;} if(isFading){ if(--opacity>0){ ctx.clearRect(0,0,cw,ch); overlay(x1,50,opacity/100); overlay(x2,50,1.00); }else{ isFading=false; overlay(x2,50,1.00); ctx.drawImage(label,70,210); nextTime=time+1000; } }else{ delay=1000; fillParticles(parseInt(Math.random()*8)+2,3); ctx.drawImage(label,70,210); nextTime=time+delay; } } 
 body{ background-color:white; padding:10px; } #canvas{border:1px solid red;} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <button id=again>Again</button> <br> <canvas id="canvas" width=250 height=500></canvas> 

If I were to approach this problem, I would go about it in this way: 如果我要解决此问题,我将以这种方式进行处理:

  1. Create an object that can be used to "create" particles. 创建一个可用于“创建”粒子的对象。
  2. Create as many new instances of that object as is needed for the required density. 根据所需密度创建该对象的尽可能多的新实例。

So, basically, all the work is done by one function constructor/object. 因此,基本上,所有工作都是由一个函数构造函数/对象完成的。

You want this object to provide methods to draw itself to the canvas, store its x and y coordinates, its velocity and direction. 您希望该对象提供一些方法以将自身绘制到画布上,存储其x和y坐标,其速度和方向。

Then you can create instances of this object with the new keyword and set their x and y coordinates to spread them across a grid. 然后,您可以使用new关键字创建该对象的实例,并设置其x和y坐标以将它们分布在整个网格中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM