如何解决画布-在图像上创建随机薄片
任何人都可以给我一个提示,告诉我如何使用javascript创建类似的东西:
要求是我可以设置薄片的密度。并添加多达5种不同的颜色。
我确实知道如何创建画布并在其中放置像素,但是我不知道如何创建“薄片”。
有没有办法创建这样的随机形状?
解决方法
您可以细分简单的形状并在任意点绘制它。
下面的示例将创建一个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,1,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,noise);
}
ctx.fill();
}
const ctx = canvas.getContext("2d");
canvas.addEventListener("click",drawFlakes);
drawFlakes();
function drawFlakes(){
ctx.setTransform(1,0);
ctx.fillStyle = "#341";
ctx.fillRect(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",15,25,"#257",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>
,
您将需要某种噪声算法。
在此示例中,我使用了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,e){return this.x*n+this.y*t+this.z*e};var r=[new e(1,0),new e(-1,new e(1,-1,1),-1),new e(0,-1)],o=[151,160,137,91,90,131,13,201,95,96,53,194,233,7,225,140,36,103,69,142,8,99,37,240,21,23,190,6,148,247,120,234,75,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,63,161,216,80,73,209,76,132,187,208,89,18,169,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,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,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,a=w[e+1+i[r+1]].dot2(n-1,c=u(n);return f(f(o,s,c),f(h,a,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);
更改为较小的值会增加blob的大小,而将其增大则会减小blob的大小。
<canvas id="canvas" width=500 height=500></canvas>
?.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。