任何人都可以给我一个提示,告诉我如何使用javascript创建类似的东西:
要求是我可以设置薄片的密度。并添加多达5种不同的颜色。
我确实知道如何创建画布并在其中放置像素,但是我不知道如何创建“薄片”。
有没有办法创建这样的随机形状?
答案 0 :(得分:3)
您可以细分简单的形状并在任意点绘制它。
下面的示例将创建一个3边的点,将其随机测试到大约2像素的细节级别,然后将其添加到路径。
然后用一种颜色填充路径,并添加另一组形状。
function testate(amp, points) {
const p = [];
var i = points.length - 2, x1, y1, x2, y2;
p.push(x1 = points[i++]);
p.push(y1 = points[i]);
i = 0;
while (i < points.length) {
x2 = points[i++];
y2 = points[i++];
const dx = x2 - x1;
const dy = y2 - y1;
const r = (Math.random() - 0.5) * 2 * amp;
p.push(x1 + dx / 2 - dy * r);
p.push(y1 + dy / 2 + dx * r);
p.push(x1 = x2);
p.push(y1 = y2);
}
return p;
}
function drawFlake(ctx, size, x, y, noise) {
const a = Math.random() * Math.PI;
var points = [];
const step = Math.PI * (2/3);
var i = 0;
while (i < 3) {
const r = (Math.random() * size + size) / 2;
points.push(Math.cos(a + i * step) * r);
points.push(Math.sin(a + i * step) * r);
i++;
}
while (size > 2) {
points = testate(noise, points);
size >>= 1;
}
i = 0;
ctx.setTransform(1,0,0,1,x,y);
ctx.moveTo(points[i++], points[i++]);
while (i < points.length) {
ctx.lineTo(points[i++], points[i++]);
}
}
function drawRandomFlakes(ctx, count, col, min, max, noise) {
ctx.fillStyle = col;
ctx.beginPath();
while (count-- > 0) {
const x = Math.random() * ctx.canvas.width;
const y = Math.random() * ctx.canvas.height;
const size = min + Math.random() * (max- min);
drawFlake(ctx, size, x, y, noise);
}
ctx.fill();
}
const ctx = canvas.getContext("2d");
canvas.addEventListener("click",drawFlakes);
drawFlakes();
function drawFlakes(){
ctx.setTransform(1,0,0,1,0,0);
ctx.fillStyle = "#341";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)
const noise = Math.random() * 0.3 + 0.3;
drawRandomFlakes(ctx, 500, "#572", 5, 10, noise)
drawRandomFlakes(ctx, 200, "#421", 10, 15, noise)
drawRandomFlakes(ctx, 25, "#257", 15, 30, noise)
}
body { background: #341 }
div {
position: absolute;
top: 20px;
left: 20px;
color: white;
}
<canvas id="canvas" width = "600" height = "512"></canvas>
<div>Click to redraw</div>
答案 1 :(得分:2)
您将需要某种噪声算法。
在此示例中,我使用了Perlin noise,但是您可以使用任何适合您的噪声算法。通过使用Perlin噪声,我们可以将blob定义为噪声值高于某个阈值的区域。
我使用了一个发现的库{strong> ,并将代码基于示例代码。压缩后的代码只是其中的一小部分(我剪下了simplex和perlin 3D)。
您可以通过更改以下参数来进行调整
Math.abs(noise.perlin2(x / 25, y / 25))
将25
更改为较高的值将放大,将if (value > 0.4){
更改为较小的值
0.4
将!function(n){var t=n.noise={};function e(n,t,e){this.x=n,this.y=t,this.z=e}e.prototype.dot2=function(n,t){return this.x*n+this.y*t},e.prototype.dot3=function(n,t,e){return this.x*n+this.y*t+this.z*e};var r=[new e(1,1,0),new e(-1,1,0),new e(1,-1,0),new e(-1,-1,0),new e(1,0,1),new e(-1,0,1),new e(1,0,-1),new e(-1,0,-1),new e(0,1,1),new e(0,-1,1),new e(0,1,-1),new e(0,-1,-1)],o=[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180],i=new Array(512),w=new Array(512);function u(n){return n*n*n*(n*(6*n-15)+10)}function f(n,t,e){return(1-e)*n+e*t}t.seed=function(n){n>0&&n<1&&(n*=65536),(n=Math.floor(n))<256&&(n|=n<<8);for(var t=0;t<256;t++){var e;e=1&t?o[t]^255&n:o[t]^n>>8&255,i[t]=i[t+256]=e,w[t]=w[t+256]=r[e%12]}},t.seed(0),t.perlin2=function(n,t){var e=Math.floor(n),r=Math.floor(t);n-=e,t-=r;var o=w[(e&=255)+i[r&=255]].dot2(n,t),h=w[e+i[r+1]].dot2(n,t-1),s=w[e+1+i[r]].dot2(n-1,t),a=w[e+1+i[r+1]].dot2(n-1,t-1),c=u(n);return f(f(o,s,c),f(h,a,c),u(t))}}(this);
const c = document.getElementById("canvas");
const cc = c.getContext("2d");
noise.seed(Math.random());
let image = cc.createImageData(canvas.width, canvas.height);
let data = image.data;
for (let x = 0; x < c.width; x++){
for (let y = 0; y < c.height; y++){
const value = Math.abs(noise.perlin2(x / 25, y / 25));
const cell = (x + y * c.width) * 4;
if (value > 0.4){
data[cell] = 256;
data[cell + 1] = 0;
data[cell + 2] = 0;
data[cell + 3] = 256;
}
else {
data[cell] = 0;
data[cell + 1] = 0;
data[cell + 2] = 0;
data[cell + 3] = 0;
}
}
}
cc.putImageData(image, 0, 0);
更改为较小的值会增加blob的大小,而将其增大则会减小blob的大小。
<canvas id="canvas" width=500 height=500></canvas>
?.