gpt4 book ai didi

javascript - HTML5 Canvas - 用随机像素颜色填充形状?

转载 作者:搜寻专家 更新时间:2023-10-31 22:46:32 25 4
gpt4 key购买 nike

我有一个形状,比方说:

var context = canvas.getContext();
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.quadraticCurveTo(300, 100, 260, 170);
context.closePath();
canvas.fillStroke(this);

形状可能每次都不一样。

我有 10 个蓝色渐变,并且想随着时间的推移随机绘制形状中包含的像素。


我什至不知道如何获取形状中包含的像素列表,以便我可以编辑它们。

此外,我认为每帧重绘它可能会影响性能。


有什么想法可以继续吗?谢谢! :)

最佳答案

由于以下问题,您的解决方案实际上有点复杂!

问题:

  • 您需要一个 KineticJS 形状对象来绘制您的自定义形状。
  • Shape 在其 drawFunc 中只允许 1 个 context.beginPath。
  • Html Canvas 只允许您为每个 beginPath 设置 1 个 fillStyle(填充颜色)。
  • 这意味着您只能使用 1 种蓝色填充,而不是 10 种蓝色阴影。

解决方法:

  • 您可以将形状设为剪裁区域。
  • 然后使用另一个背景 Canvas 显示您剪裁后的形状。
  • 背景 Canvas 将用于有效地绘制所有蓝色阴影中的单个像素!

enter image description here

要绘制随机像素并仍然覆盖所有像素,请创建一个“ map ”数组:

  • 用舞台上每个像素的索引号创建一个数组。 ( 随机像素[] )
  • 随机排列数组。
  • 使用包含每个像素索引的随机数组一次绘制一个随机像素。

这是创建映射数组的函数:

  // make an array with elements from 0 to shapeWidth*shapeHeight in random order

function initPixelArray(shapeWidth,shapeHeight){
var array=[];
var i;
var countdown;
var temp;

// Must be a better way to fill an array with
// a sequential group of numbers, just in random order
// Anyone got some magic for this ????????????

// fill array with sequential numbers representing each pixel;
for(var i=0;i<shapeWidth*shapeHeight;i++){ array.push(i); }
// randomize the array
countdown=array.length;
while (countdown > 0) {
i = (Math.random() * countdown--) | 0;
temp = array[countdown];
array[countdown] = array[i];
array[i] = temp;
}
//
return array;
}

接下来创建自定义 KineticJS 形状:

  • 将您的自定义形状定义为剪裁区域(在 drawFunc 中)
  • DrawImage 背景 Canvas (将包含不断更新的像素)
  • 由于它被剪裁,背景 Canvas 将仅在您的自定义形状内可见。

这将使用您的形状作为 Canvas 背景的剪切路径来创建自定义动力学形状

        var shape = new Kinetic.Shape({
drawFunc: function(canvas){
var context = canvas.getContext();
context.beginPath();
context.moveTo(0, 50);
context.lineTo(220, 80);
context.quadraticCurveTo(100, 100, 60, 170);
context.closePath();
context.clip();
context.drawImage(this.backgroundCanvas,0,0);
canvas.fillStroke(this);
},
x: x,
y: y,
stroke: "lightgray",
strokeWidth: 8,
draggable:true
});

将 10 种颜色逐像素动画化到形状中

  • 逐渐用彩色像素填充背景 Canvas 。
  • 由于背景 Canvas 是“内置”在动力学形状中的,您所要做的就是在 Canvas 上绘制一个像素,然后调用 layer.draw 以使更改在您的形状中可见。

此函数使用 10 种蓝色将成批随机放置的像素添加到背景

  // add pixels to the background canvas
// after layer.draw the new pixels will be visible in the shape
function updatePattern(){

// add 10 pixels of each type of blue (100px total)
for(var n=0;n<shapeWidth/8;n++){

// set a blue color
tempCtx.fillStyle=color[n];
tempCtx.beginPath();

// draw 10 random pixels in that blue
for(var b=0;b<10;b++){

// get next random pixel
var i=randomPixels[nextPixel]
// calculate x/y from i
var y=Math.floor(i/shapeWidth);
var x=(i-y*shapeWidth)-1;
// draw
tempCtx.rect(x,y,1,1);
// increment array index and do bounds check
if(++nextPixel>=randomPixels.length){return;}

}
// done filling with this blue--do the fill()
tempCtx.fill();
}
}

注意:为了保持高性能——同时也为了保持观看者的耐心(!),我一次绘制了一批像素。

蓝色色调的适当混合得以保持。

当然,您可以根据自己的喜好设计风格。

这是代码和 fiddle :http://jsfiddle.net/m1erickson/zhatS/

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>

<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
canvas{border:1px solid red;}
</style>
<script>
$(function(){

var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);


// the KineticJS shape
var myShape;

//
var shapeWidth=stage.getWidth();
var shapeHeight=stage.getHeight();

// temporary canvas to create/update the pattern for the Shape
var tempCanvas=document.createElement("canvas");
var tempCtx=tempCanvas.getContext("2d");
tempCanvas.width=shapeWidth;
tempCanvas.height=shapeHeight;

// an array of pixel references from 0 to shapeWidth*shapeHeight
// used to draw individual pixels randomly
var randomPixels=initPixelArray(shapeWidth,shapeHeight);
var nextPixel=0;

// shades of colors to fill with
var color;
var colors={
blues:["#0000ff","#2b60de","#4863a0","#2554c7","#000080","#afdcec","#c6deff","#6698ff","#c2dfff","#79baec"],
reds:["#ff0000","#f4c3c2","#fd5c5c","#fe2625","#ff3030","#ff6666","#fa8072","#efc3bf","#ff6347","#ef7942"]
}

// Create a KineticJS shape
function kShape(x,y){
var shape = new Kinetic.Shape({
drawFunc: function(canvas){
var context = canvas.getContext();
context.beginPath();
context.moveTo(0, 50);
context.lineTo(220, 80);
context.quadraticCurveTo(100, 100, 60, 170);
context.closePath();
context.clip();
context.drawImage(this.backgroundCanvas,0,0);
canvas.fillStroke(this);
},
x: x,
y: y,
stroke: "lightgray",
strokeWidth: 8,
draggable:true
});
// let the shape keep a reference to the background canvas
shape.backgroundCanvas=tempCanvas;
layer.add(shape);
layer.draw();
return(shape);
}


// make an array with elements from 0 to shapeWidth*shapeHeight in random order
function initPixelArray(shapeWidth,shapeHeight){
var array=[];
var i;
var countdown;
var temp;

// Must be a better way to fill an array with
// a sequential group of numbers, just in random order
// Anyone got some magic for this ????????????

// fill array with sequential numbers representing each pixel;
for(var i=0;i<shapeWidth*shapeHeight;i++){ array.push(i); }
// randomize the array
countdown=array.length;
while (countdown > 0) {
i = (Math.random() * countdown--) | 0;
temp = array[countdown];
array[countdown] = array[i];
array[i] = temp;
}
//
return array;
}


// add pixels to the pattern
function updatePattern(){

// add 10 pixels of each type of blue (100px total)
for(var n=0;n<shapeWidth/8;n++){

// set a blue color
tempCtx.fillStyle=color[n];
tempCtx.beginPath();

// draw 10 random pixels in that blue
for(var b=0;b<10;b++){

// get next random pixel
var i=randomPixels[nextPixel]
// calculate x/y from i
var y=Math.floor(i/shapeWidth);
var x=(i-y*shapeWidth)-1;
// draw
tempCtx.rect(x,y,1,1);
// increment array index and do bounds check
if(++nextPixel>=randomPixels.length){return;}

}
// done filling with this blue--do the fill()
tempCtx.fill();
}
}


// great cross-browser animation shim by Paul Irish
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();


// animate filling of pixels
var fps = 60;
function animate() {
setTimeout(function() {
requestAnimationFrame(animate);

if(nextPixel>=randomPixels.length){return;}

updatePattern();

layer.draw();

}, 1000 / fps);
}


////////////////// ACTION STARTS HERE

var myShape=kShape(20,20);

$("#blues").click(function(){
color=colors.blues;
nextPixel=0;
animate();
});

$("#reds").click(function(){
color=colors.reds;
nextPixel=0;
animate();
});



}); // end $(function(){});

</script>
</head>

<body>
<div id="container"></div>
<button id="blues">Fill blues</button>
<button id="reds">Fill reds</button>
</body>
</html>

关于javascript - HTML5 Canvas - 用随机像素颜色填充形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17381671/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com