Related
I am making canvas creation by for loop.
Each 20 circles wihch has each different size shows up every second.
I need to stop/escape loop when the total of circles becomes 100.
I tried to stop interval like below. However, it continues looping in console even though the shape of circle stops showing up.
if (circles.length > 100) {
console.log('STOP');
return;
}
Is there any way?
Thank you.
class circle {
constructor() {
this.x = 0;
this.y = 0;
this.r = 0;
}
}
const canvas = document.getElementById('canvas');
const context = canvas.getContext("2d");
let colors = ["#96ceb4","#ffeead","#ff6f69","#ffcc5c","#88d8b0"];
let circles = new Array();
window.addEventListener('load', function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context.clearRect( 0, 0, canvas.width, canvas.height );
function draw() {
for (let i=0; i < 20; i++) { //20 blocks at a time
const item = new circle();
item.x = Math.floor(Math.random()*canvas.width);
item.y = Math.floor(Math.random()*canvas.height);
item.r = Math.floor(Math.random()*50);
circles.push(item);
console.log(circles.length);
if (circles.length > 100) {
console.log('STOP');
return;
}
context.beginPath();
context.fillStyle=colors[Math.floor(Math.random()*colors.length)];
context.globalAlpha=0.5;
context.arc(item.x, item.y, item.r, 0, Math.PI*2, true);
context.fill();
};
};
setInterval(draw, 1000);
});
body {overflow: hidden;}
<canvas id="canvas"></canvas>
You need to use the setInterval return to get the id to clear.
class circle {
constructor() {
this.x = 0;
this.y = 0;
this.r = 0;
}
}
var timer;
function stopTimer(){
clearInterval(timer);
}
const canvas = document.getElementById('canvas');
const context = canvas.getContext("2d");
let colors = ["#96ceb4","#ffeead","#ff6f69","#ffcc5c","#88d8b0"];
let circles = new Array();
window.addEventListener('load', function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context.clearRect( 0, 0, canvas.width, canvas.height );
function draw() {
for (let i=0; i < 20; i++) { //20 blocks at a time
const item = new circle();
item.x = Math.floor(Math.random()*canvas.width);
item.y = Math.floor(Math.random()*canvas.height);
item.r = Math.floor(Math.random()*50);
circles.push(item);
console.log(circles.length);
if (circles.length > 100) {
console.log('STOP');
stopTimer();
return;
}
context.beginPath();
context.fillStyle=colors[Math.floor(Math.random()*colors.length)];
context.globalAlpha=0.5;
context.arc(item.x, item.y, item.r, 0, Math.PI*2, true);
context.fill();
};
};
timer = setInterval(draw, 1000);
});
body {overflow: hidden;}
<canvas id="canvas"></canvas>
How do I make the shape disappear like the text does? I've gone through the code and they're practically identical except that one is created when the user spins the mouse wheel and the other is created when the user clicks on the screen, but the text disappears after time and the triangle does not. I feel like there's something small I must be missing. Here's the code:
<html>
<head>
<script>
var canvas;
var context;
var triangles = [];
var texts = [];
var timer;
var textSayings = ['Cool!', 'Nice!', 'Awesome!', 'Wow!', 'Whoa!', 'Super!', 'Woohoo!', 'Yay!', 'Yeah!', ':)', ':D'];
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext("2d");
//resize canvas to fit the window
resizeCanvas();
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
canvas.onwheel = function(event) {
handleWheel(event.clientX, event.clientY);
};
canvas.onclick = function(event) {
handleClick(event.clientX, event.clientY);
}
var timer = setInterval(resizeCanvas, 30);
}
function Triangle(x,y,triangleColor) {
this.x = x;
this.y = y;
this.triangleColor = triangleColor;
this.vx = Math.random() * 80 - 40;
this.vy = Math.random() * 80 - 40;
this.time = 250;
}
function Text(x,y,textColor,word) {
this.x = x;
this.y = y;
this.word = word;
this.textColor = textColor;
this.vx = Math.random() * 20 - 10;
this.vy = Math.random() * 20 - 10;
this.time = 300;
}
function handleWheel(x,y) {
var colors = [[255,0,0],[255,255,255],[0,0,255]];
var triangleColor = colors[Math.floor(Math.random()*colors.length)];
triangles.push(new Triangle(x,y,triangleColor));
for (var i=0; i<triangles.length; i++) {
drawTriangle(triangles[i]);
}
}
function handleClick(x,y) {
var colors = [[255,0,0],[255,255,0],[0,0,255]];
var textColor = colors[Math.floor(Math.random()*colors.length)];
texts.push(new Text(x,y,textColor,pickWord()));
for (var i=0; i<texts.length; i++) {
drawText(texts[i]);
}
}
function timeToFade(time) {
if(time > 100) {
return 1;
}
else {
return time / 100;
}
}
function pickWord() {
return textSayings[Math.floor(Math.random() * textSayings.length)];
}
function drawText(text) {
context.font = "bold 80px Verdana";
var gradient=context.createLinearGradient(0,0,canvas.width,0);
gradient.addColorStop("0","magenta");
gradient.addColorStop("0.25","yellow");
gradient.addColorStop("0.5","lime");
gradient.addColorStop("0.75","aqua");
gradient.addColorStop("1.0","magenta");
context.fillStyle = gradient;
context.fillText(text.word,text.x,text.y);
}
function drawTriangle(triangle) {
context.beginPath();
context.moveTo(triangle.x,triangle.y);
context.lineTo(triangle.x+25,triangle.y+25);
context.lineTo(triangle.x+25,triangle.y-25);
var gradient = context.createLinearGradient(0,0,canvas.width,0);
gradient.addColorStop("0","red");
gradient.addColorStop("0.25","salmon");
gradient.addColorStop("0.5","aqua");
gradient.addColorStop("0.75","lime");
gradient.addColorStop("1.0","orange");
context.fillStyle = gradient;
context.fill();
}
function resizeCanvas() {
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
fillBackgroundColor();
for (var i=0; i<triangles.length; i++) {
var t = triangles[i];
drawTriangle(t);
if (t.x + t.vx > canvas.width || t.x + t.vx < 0)
t.vx = -t.vx
if (t.y + t.vy > canvas.height || t.y + t.vy < 0)
t.vy = -t.vy
if (t.time === 0) {
triangles.splice(i,1);
}
t.time -= 3;
t.x += t.vx;
t.y += t.vy;
}
for (var i=0; i<texts.length; i++) {
var te = texts[i];
drawText(te);
if (te.x + te.vx > canvas.width || te.x + te.vx < 0)
te.vx = -te.vx
if (te.y + te.vy > canvas.height || te.y + te.vy < 0)
te.vy = -te.vy
if (te.time === 0) {
texts.splice(i,1);
}
te.time -= 3;
te.x += te.vx;
te.y += te.vy;
}
}
function fillBackgroundColor() {
context.globalCompositeOperation = 'source-over';
context.fillStyle = 'rgba(0, 0, 0, 1)';
context.fillRect(0,0,canvas.width,canvas.height);
context.globalCompositeOperation = 'lighter';
}
window.onload = init;
</script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>
It's because the triangle time isn't a multiple of 3, while the text time is so when you check this if statement:
if (t.time === 0) {
triangles.splice(i,1);
}
It's never true.
You can fix this by changing the if statement to:
if (t.time <= 0) {
triangles.splice(i,1);
}
This is actually my fault since it's a bug that was in my previous answer. Sorry about that.
jsfiddle:
https://jsfiddle.net/0rst8def/
I work with this code for show HTML5 canvas animated in over my div:
HTML:
<div class="ls-slide" id="asb">
<div id="smile" style="width:100%;height:359px;">
<canvas style="position: absolute; width: 100%; z-index: 3; display: block;" height="359" width="2111">
</canvas>
</div>
</div>
JS:
window.onload = function() {
travers();
var lastHeight = $("#asb").height();
var canvas = document.querySelector('canvas');
ctx = canvas.getContext('2d');
color = '#aaa';
var check = respondCanvas();
canvas.width = check[1];
canvas.height = lastHeight;
canvas.style.display = 'block';
ctx.fillStyle = color;
ctx.lineWidth = .1;
ctx.strokeStyle = color;
function respondCanvas() {
var width = [];
width[0] = $('#smile').width(); //max width
width[1] = $('canvas').width(); //max width
return width;
//Call a function to redraw other content (texts, images etc)
}
function checkheight() {
var height = $('#asb').height(); //max width
//console.log(height);
// return height;
}
var mousePosition = {
x: 30 * canvas.width / 100,
y: 30 * canvas.height / 100
};
if (canvas.width <= 1000) {
var numdot = 100;
} else if (canvas.width <= 800) {
var numdot = 80;
} else if (canvas.width <= 500) {
var numdot = 35;
} else {
var numdot = 300;
}
var dots = {
nb: numdot,
distance: 70,
d_radius: 50,
array: []
};
function Dot() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.vx = -.5 + Math.random();
this.vy = -.5 + Math.random();
this.radius = Math.random();
}
Dot.prototype = {
create: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
ctx.fill();
},
animate: function() {
for (i = 0; i < dots.nb; i++) {
var dot = dots.array[i];
if (dot.y < 0 || dot.y > canvas.height) {
dot.vx = dot.vx;
dot.vy = -dot.vy;
} else if (dot.x < 0 || dot.x > canvas.width) {
dot.vx = -dot.vx;
dot.vy = dot.vy;
}
dot.x += dot.vx;
dot.y += dot.vy;
}
},
line: function() {
for (i = 0; i < dots.nb; i++) {
for (j = 0; j < dots.nb; j++) {
i_dot = dots.array[i];
j_dot = dots.array[j];
if ((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > -dots.distance && (i_dot.y - j_dot.y) > -dots.distance) {
if ((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > -dots.d_radius && (i_dot.y - mousePosition.y) > -dots.d_radius) {
ctx.beginPath();
ctx.moveTo(i_dot.x, i_dot.y);
ctx.lineTo(j_dot.x, j_dot.y);
ctx.stroke();
ctx.closePath();
}
}
}
}
}
};
function createDots() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (i = 0; i < dots.nb; i++) {
dots.array.push(new Dot());
dot = dots.array[i];
dot.create();
}
dot.line();
dot.animate();
}
$("canvas").mousemove(function(parameter) {
mousePosition.x = parameter.pageX - 0;
mousePosition.y = parameter.pageY - 300;
});
setInterval(createDots, 1000 / 30);
};
But, In action not work and I can't see dotted animation(I checked in chrome,ff). How do fix this?!
demo : https://jsfiddle.net/5pzvh8ko/
You can try it better by giving an ID to you canvas tag, and then use "document.getElementById()", to access your canvas tag, i think it is a better method and even simpler.here is an example:
canvas tag with id:
<canvas ID="canvas_id" style="position: absolute; width: 100%; z-index:3; display: block;" height="359" width="2111">
then use JavaScript to access it this way:
var canvas = document.getElementById("canvas_id");
This might not be all you need but you can at least try it that way.
I want to animate 2 figures on my page. Therefore I use Javascript. The problem is that I can't define which "sprite" he has to take. Because I can't add some Parameters like the object "animation" to the gameLoop()-method, because of the requestAnimationFrame. Any idea how I can solve this?
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);
In this example I pretend that my spritesheets are the same size and columns, just to test the code.
This doesn't work of course, but this is what I need:
function gameLoop (animation) {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
window.requestAnimationFrame(gameLoop(animation));
animation.update();
animation.render();
}
}
requestAnimationFrame function is not allowed to pass your own parameter, one solution/trick is bound that gameLoop function to sprite object, so that we can access this as sprite object.
as example: http://jsfiddle.net/XQpzU/6110/
Your code can be modified as:
var animation,
image,
canvas,
stopAtLastFrame = false,
amountAnimation = 0,
amountAnimated = 1;
image = new Image();
function sprite (options) {
var that = {},
frameIndex = 0,
currentRow = 0,
currentColumn = 0,
tickCount = 0,
rowOfLastFrame = 0,
columnOfLastFrame = 0,
ticksPerFrame = options.ticksPerFrame,
numberOfFrames = options.numberOfFrames,
numberOfColumns = options.totalColumns,
numberOfRows = options.totalRows,
widthOfOneFrame = options.width/numberOfColumns,
heightOfOneFrame = options.height/numberOfRows;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
rowOfLastFrame = numberOfRows-1;
columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);
that.render = function () {
that.context.save();
that.context.scale(0.5,0.5);
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
currentColumn * widthOfOneFrame,
currentRow * heightOfOneFrame,
widthOfOneFrame,
heightOfOneFrame,
0,
0,
widthOfOneFrame,
heightOfOneFrame);
that.context.restore();
if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
{
stopAtLastFrame=true;
}
};
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
if (frameIndex < numberOfFrames-1) {
frameIndex++;
currentColumn++;
if (currentColumn == numberOfColumns) {
currentRow++;
currentColumn = 0;
}
}else{
amountAnimated++;
frameIndex=0;
currentColumn=0;
currentRow=0;
}
}
};
that.gameLoop = gameLoop.bind(that);
return that;
}
function gameLoop () {
if(stopAtLastFrame==true)
{
stopAtLastFrame=false;
}
else
{
// this will be your sprite
window.requestAnimationFrame(this.gameLoop);
animation.update();
animation.render();
}
}
function startAnimation(canvas, imageUrl, amount){
canvas = document.getElementById(canvas);
canvas.width = 7680/4;
canvas.height = 2880/4;
image.src = imageUrl;
amountAnimation=amount;
animation = sprite({
context: canvas.getContext("2d"),
width: 7684,
height: 2880,
image: image,
numberOfFrames:16,
totalRows : 4,
totalColumns: 4,
ticksPerFrame: 5
});
animation.gameLoop();
}
startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);
I have an image drawn on a canvas. The image for now is doing a simple circular rotation on each frame.
The image scaling is based on the value entered in the text box.
I put the jsfiddle as suggested below
var canvas = null;
var ctx = null;
var image = null;
var slider = null;
var vBox = null;
var x = 50;
var y = 50;
var scaleX;
var scaleY;
var center = {
x: 0,
y: 0
};
var radius = 50.0;
var angle = 0;
var result = false;
var textActive = false;
var imgArr = null;
var imageData;
var data;
function start() {
ctx = getCtxReference();
image = getImageReference();
result = setOtherReferences();
imgArr = getStarImages();
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
data = imageData.data;
for (var i = 0; i < imgArr.length; i++) {
imgArr[i].addEventListener('load', drawBackgroundStar)
}
if (image != null && result && imgArr != null) {
Loop();
}
}
function checkKeyPressed(e) {
if (e.keyCode == "65") {
changeImgColorToBlue();
}
}
function getCtxReference() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
return ctx;
}
function getImageReference() {
image = new Image();
image.src = "star.png";
image.addEventListener('load', drawImg);
return image;
}
function setOtherReferences() {
slider = document.getElementById("rangeInput");
vBox = document.getElementById("textbox");
scaleX = 100;
scaleY = 100;
center.x = canvas.width / 3;
center.y = canvas.height / 3;
return true;
}
function getStarImages() {
var arr = new Array();
for (var i = 0; i < 500; i++) {
var img = new Image();
img.src = "star.png";
arr.push(img);
}
return arr;
}
function drawImg() {
ctx.drawImage(image, x, y, scaleX, scaleY);
return true;
}
function drawBackgroundStar() {
for (var i = 0; i < imgArr.length; i++) {
ctx.drawImage(imgArr[i], getRandomArbitrary(0, canvas.width), getRandomArbitrary(0, canvas.height), getRandomArbitrary(5, 15), getRandomArbitrary(5, 15));
}
}
function Loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
window.setTimeout(Loop, 100);
angle += Math.PI * 0.05;
x = center.x + radius * Math.cos(angle);
y = center.y + radius * Math.sin(angle);
vBox.value = slider.value;
updateStarScale();
drawImg();
//drawBackgroundStar();
}
function updateStarScale() {
if (vBox.value > 0) {
scaleX += vBox.value / 10;
scaleY += vBox.value / 10;
changeImgColorToBlue();
} else if (vBox.value < 0) {
scaleX -= Math.abs(vBox.value / 10);
scaleY -= Math.abs(vBox.value / 10);
changeImgColorToRed();
}
if (scaleX > 600 || scaleY > 600) {
scaleX = 600;
scaleY = 600;
} else if (scaleX < 50 || scaleY < 50) {
scaleX = 50;
scaleY = 50;
}
}
function changeImgColorToBlue() {
for (var i = 0; i < data.length; i += 4) {
data[i] = 0; // red
data[i + 1] = 0; // green
data[i + 2] = 255; // blue
}
ctx.putImageData(imageData, 0, 0);
}
function changeImgColorToRed() {
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
<html>
<style type="text/css">
body {
text-align: center;
background-image: url("stars.png");
}
#container {
position: fixed;
color: red;
top: 0px;
left: 0px;
}
#textBox {
position: absolute;
top: 25px;
left: 5px;
}
#slider {
position: absolute;
top: 25px;
left: 200px;
}
</style>
<body onload="start()">
<canvas id="canvas" width="1024" height="768"></canvas>
<div id="container">
<div id="textBox">
Velocity:
<input type="text" id="textbox" value="0">
</div>
<div id="slider">
Slider:
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" min="-100" max="100" step="3" value="">
<output name="amount" for="rangeInput">0</output>
</form>
</div>
</div>
<script type="text/javascript" src="main.js">
</script>
</body>
</html>
So in my Loop(), I am updating the position of my image. In the updateStarScale() I am scaling the image size based on the value given in the text box by the user. All of this works fine. My only concern is the changeImgColorToBlue() which does nothing to the image color. I want the image color to be changed to blue but this doesn't work. What am I doing wrong?
**
UPDATE 1.0:
**
After suggestions from the last post, I changed the code to below. There are two yellow stars on the screen now and they scale up based on the sliders but alongside scaling I want their colors to change ie when they are scaled up they turn blue and when they are scaled down they turn red but the colors don't change.
//Create the images(Using a canvas for CORS issues)
function createStars() {
var imgCanvas = document.createElement('canvas');
imgCanvas.height = "500";
imgCanvas.width = "500";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle = 'black';
imgCtx.fillRect(0, 0, 500, 500)
imgCtx.fillStyle = '#FF0';
for (i = 0; i < Math.floor(Math.random() * 500) + 250; i++) {
imgCtx.fillRect(Math.random() * 500, Math.random() * 500, 1, 1)
}
document.body.style.backgroundImage = 'url(' + imgCanvas.toDataURL() + ')';
}
createStars();
var canvas = null;
var ctx = null;
var image = null;
var slider = null;
var vBox = null;
var x = 50;
var y = 50;
var scaleX;
var scaleY;
var center = {
x: 0,
y: 0
};
var radius = 50.0;
var angle = 0;
var result = false;
var imageData;
var data;
var backgroundImg = null;
function start() {
ctx = getCtxReference();
result = setOtherReferences();
image = getStarImages();
if (image != null)
image.addEventListener('load', Loop);
}
function getCtxReference() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
return ctx;
}
function setOtherReferences() {
slider = document.getElementById("rangeInput");
vBox = document.getElementById("textbox");
scaleX = 150;
scaleY = 150;
center.x = canvas.width / 3;
center.y = canvas.height / 3;
return true;
}
function getStarImages() {
var img = new Image();
img.src = createStar();
return img;
}
function createStar() {
ctx.fillStyle = '#FF0';
ctx.fillRect(Math.random() * 45, Math.random() * 45, scaleX, scaleY);
return canvas.toDataURL();
}
function drawImg() {
ctx.drawImage(image, x, y, scaleX, scaleY);
}
function Loop() {
window.setTimeout(Loop, 100);
ctx.clearRect(0, 0, canvas.width, canvas.height);
angle += Math.PI * 0.05;
x = center.x + radius * Math.cos(angle);
y = center.y + radius * Math.sin(angle);
vBox.value = slider.value;
updateStarScale();
drawImg();
}
function updateStarScale() {
if (vBox.value > 0) {
scaleX += vBox.value / 10;
scaleY += vBox.value / 10;
changeImgColorToBlue();
} else if (vBox.value < 0) {
scaleX -= Math.abs(vBox.value / 10);
scaleY -= Math.abs(vBox.value / 10);
changeImgColorToRed();
}
if (scaleX > 600 || scaleY > 600) {
scaleX = 600;
scaleY = 600;
} else if (scaleX < 50 || scaleY < 50) {
scaleX = 50;
scaleY = 50;
}
}
function changeImgColorToBlue() {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
//is our data black?
if (data[i] > 0 || data[i + 1] > 0 || data[i + 2] > 0) {
data[i] = 0; // red
data[i + 1] = 0; // green
data[i + 2] = 255; // blue
}
}
ctx.putImageData(imageData, 0, 0);
}
function changeImgColorToRed() {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
if (data[i] > 0 || data[i + 1] > 0 || data[i + 2] > 0) {
data[i] = 255; // red
data[i + 1] = 0; // green
data[i + 2] = 0; // blue
}
}
ctx.putImageData(imageData, 0, 0);
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
start();
Edit
Ok, so if you only need to draw those moving stars, you can simplify a lot your code, especially about the changing color :
As each star is only a colored rectangle, you only have to store a color value (i.e hex) and update it when you want to the desired color. No bitmap calculation needed.
However, as your code is right now, if you try to create new stars, they will all follow the same path and scale update.
I think that you will have to rethink the way you update the position.
Here is an update, with simplification of the code and example showing the issue
function createStars() {
var imgCanvas = document.createElement('canvas');
imgCanvas.height = "500";
imgCanvas.width = "500";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle = 'black';
imgCtx.fillRect(0, 0, 500, 500)
imgCtx.fillStyle = '#FF0';
for (i = 0; i < Math.floor(Math.random() * 500) + 250; i++) {
imgCtx.fillRect(Math.random() * 500, Math.random() * 500, 1, 1)
}
document.body.style.backgroundImage = 'url(' + imgCanvas.toDataURL() + ')';
}
createStars();
var canvas = null;
var ctx = null;
var slider = null;
var vBox = null;
var x = 50;
var y = 50;
var center = {
x: 0,
y: 0
};
var radius = 50.0;
var angle = 0;
var result = false;
var color = "FF0"; // set the color as a global variable, avoiding a function to set it
var stars = []; // set an array that will contain all our moving stars
function start() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
result = setOtherReferences();
// append new stars to our array
stars.push(createStar());
stars.push(createStar());
stars.push(createStar());
// start the Loop()
Loop();
}
function setOtherReferences() {
slider = document.getElementById("rangeInput");
vBox = document.getElementById("textbox");
center.x = canvas.width / 3;
center.y = canvas.height / 3;
return true;
}
function createStar() {
// set moving stars as object, with their own x,y,width and height properties.
var star = {
xStart: Math.random() * 150, // used in order to avoid the exact
yStart: Math.random() * 150, // same position of your stars
x: this.xStart,
y: this.yStart,
w: 50,
h: 50
}
return star;
}
function drawImg() {
// set the moving stars color to the actual growing/shrinking state
ctx.fillStyle = color;
// for each of our moving stars, draw a rect
for (i = 0; i < stars.length; i++) {
ctx.fillRect(stars[i].x, stars[i].y, stars[i].w, stars[i].h);
}
}
function Loop() {
window.setTimeout(Loop, 100);
ctx.clearRect(0, 0, canvas.width, canvas.height);
angle += Math.PI * 0.05;
/*
Here is the main issue
as each of our stars x/y pos are updated with the same function,
they will follow each others.
I added the xStart property so they're not
exactly at the same position for you beeing able to see it.
*/
for (i = 0; i < stars.length; i++) {
stars[i].x = center.x + radius * Math.cos(angle) + stars[i].xStart;
stars[i].y = center.y + radius * Math.sin(angle) + stars[i].yStart;
}
vBox.value = slider.value;
updateStarScale();
drawImg();
}
function updateStarScale() {
//same as above, each of our stars will have the same scale update
for (i = 0; i < stars.length; i++) {
if (vBox.value > 0) {
stars[i].w += vBox.value / 10;
stars[i].h += vBox.value / 10;
color = "#00F";
} else if (vBox.value < 0) {
stars[i].w -= Math.abs(vBox.value / 10);
stars[i].h -= Math.abs(vBox.value / 10);
color = "#F00";
}
if (stars[i].w > 600 || stars[i].h > 600) {
stars[i].w = 600;
stars[i].h = 600;
} else if (stars[i].w < 5 || stars[i].h < 5) {
stars[i].w = 5;
stars[i].h = 5;
}
}
}
// Only call it if you haven't already done (i.e in a load event)
start();
body {
text-align: center;
background-image: url("stars.png");
}
#container {
position: fixed;
color: red;
top: 0px;
left: 0px;
}
#textBox {
position: absolute;
top: 25px;
left: 5px;
}
#slider {
position: absolute;
top: 25px;
left: 200px;
}
<canvas id="canvas" width="1024" height="768"></canvas>
<div id="container">
<div id="textBox">
Velocity:
<input type="text" id="textbox" value="0">
</div>
<div id="slider">
Slider:
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" min="-100" max="100" step="3" value="0">
<output name="amount" for="rangeInput">0</output>
</form>
</div>
</div>
Original answer
First, You will need to update your imageData each time you call changeImgColorToBlue.
Secondly, in order to not change all your pixels into blue, you will have to check if each pixel is in some range of color.
Assuming your star.png does look like a black background with colored dots over it, you can do:
for (var i = 0; i < data.length; i += 4) {
if( data[i]>0 || data[i+1]>0 || data[i+2]>0 ){
//is our pixel black?
data[i] = 0;// red
data[i + 1] = 0; // green
data[i + 2] = 255; // blue
}
}
Of course, you can change those conditions to match for the actual color of your dots with more precision by using e.g if your dots are yellow
if( data[i]>=200 && data[i+1]>=200 && data[i+2]<100 )
Also, I did some changes in your code as you had redundant calls to some functions.
//Create the images(Using a canvas for CORS issues)
function createStars(){
var imgCanvas = document.createElement('canvas');
imgCanvas.height="500";
imgCanvas.width="500";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle= 'black';
imgCtx.fillRect(0,0,500,500)
imgCtx.fillStyle= '#FF0';
for(i=0; i<Math.floor(Math.random()*500)+250; i++){
imgCtx.fillRect(Math.random()*500, Math.random()*500, 1,1)
}
document.body.style.backgroundImage='url('+imgCanvas.toDataURL()+')';
}
createStars();
function createStar(){
var imgCanvas = document.createElement('canvas');
imgCanvas.height="50";
imgCanvas.width="50";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle= '#FF0';
imgCtx.fillRect(Math.random()*45,Math.random()*45, 5,5);
return imgCanvas.toDataURL();
}
var canvas = null;
var ctx = null;
var image = null;
var slider = null;
var vBox = null;
var x = 50;
var y = 50;
var scaleX;
var scaleY;
var center = {
x: 0,
y: 0
};
var radius = 50.0;
var angle = 0;
var result = false;
var textActive = false;
var imgArr = null;
var imageData;
var data;
var backgroundImg = null;
function start() {
ctx = getCtxReference();
result = setOtherReferences();
image = getStarImages();
if (image != null && result && imgArr != null) {
Loop();
}
}
function getCtxReference() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
return ctx;
}
function setOtherReferences() {
slider = document.getElementById("rangeInput");
vBox = document.getElementById("textbox");
scaleX = 100;
scaleY = 100;
center.x = canvas.width / 3;
center.y = canvas.height / 3;
return true;
}
function drawImg() {
ctx.drawImage(image, x, y, scaleX, scaleY);
return true;
}
function Loop() {
window.setTimeout(Loop, 100);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(backgroundImg, 0,0);
angle += Math.PI * 0.05;
x = center.x + radius * Math.cos(angle);
y = center.y + radius * Math.sin(angle);
vBox.value = slider.value;
updateStarScale();
drawImg();
}
function getStarImages() {
//as they're all the same image, you don't need to make an array of them, simply make a loop below
var img = new Image();
img.addEventListener('load', drawBackgroundStar)
img.src = createStar();
return img;
}
function drawBackgroundStar() {
for (var i=0; i<500; i++) {
ctx.drawImage(image, getRandomArbitrary(0, canvas.width), getRandomArbitrary(0, canvas.height), getRandomArbitrary(5, 15), getRandomArbitrary(5, 15));
}
backgroundImg = new Image();
backgroundImg.addEventListener('load', Loop);
backgroundImg.src = canvas.toDataURL();
}
function updateStarScale() {
if (vBox.value > 0) {
scaleX += vBox.value / 10;
scaleY += vBox.value / 10;
changeImgColorToBlue();
} else if (vBox.value < 0) {
scaleX -= Math.abs(vBox.value / 10);
scaleY -= Math.abs(vBox.value / 10);
changeImgColorToRed();
}
if (scaleX > 600 || scaleY > 600) {
scaleX = 600;
scaleY = 600;
} else if (scaleX < 50 || scaleY < 50) {
scaleX = 50;
scaleY = 50;
}
}
function changeImgColorToBlue() {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
//is our data black?
if(data[i]>0||data[i+1]>0||data[i+2]>0){
data[i] = 0;// red
data[i + 1] = 0; // green
data[i + 2] = 255; // blue
}
}
ctx.putImageData(imageData, 0, 0);
}
function changeImgColorToRed() {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
if(data[i]>0||data[i+1]>0||data[i+2]>0){
data[i] = 255;// red
data[i + 1] = 0; // green
data[i + 2] = 0; // blue
}
}
ctx.putImageData(imageData, 0, 0);
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
start();
body {
text-align: center;
}
#container {
position: fixed;
color: red;
top: 0px;
left: 0px;
}
#textBox {
position: absolute;
top: 25px;
left: 5px;
}
#slider {
position: absolute;
top: 25px;
left: 200px;
}
<canvas id="canvas" width="1024" height="768"></canvas>
<div id="container">
<div id="textBox">
Velocity:
<input type="text" id="textbox" value="0">
</div>
<div id="slider">
Slider:
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" min="-100" max="100" step="3" value="">
<output name="amount" for="rangeInput">0</output>
</form>
</div>
</div>
As you wrote it, the changeImgColorToBlue functions are only changing the background stars of your canvas. I'm not sure it is what you want to achieve so here is a way to only change this one dot :
function createStars(){
var imgCanvas = document.createElement('canvas');
imgCanvas.height="500";
imgCanvas.width="500";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle= 'black';
imgCtx.fillRect(0,0,500,500)
imgCtx.fillStyle= '#FF0';
for(i=0; i<Math.floor(Math.random()*500)+250; i++){
imgCtx.fillRect(Math.random()*500, Math.random()*500, 1,1)
}
document.body.style.backgroundImage='url('+imgCanvas.toDataURL()+')';
}
createStars();
function createStar(){
var imgCanvas = document.createElement('canvas');
imgCanvas.height="50";
imgCanvas.width="50";
var imgCtx = imgCanvas.getContext('2d');
imgCtx.fillStyle= '#FF0';
imgCtx.fillRect(Math.random()*45,Math.random()*45, 5,5);
return imgCanvas.toDataURL();
}
var canvas = null;
var ctx = null;
var starCanvas = null;
var starCtx = null;
var image = null;
var slider = null;
var vBox = null;
var x = 50;
var y = 50;
var scaleX;
var scaleY;
var center = {
x: 0,
y: 0
};
var radius = 50.0;
var angle = 0;
var result = false;
var textActive = false;
var imgArr = null;
var imageData;
var data;
var backgroundImg = null;
function start() {
ctx = getCtxReference();
starCtx = getStarReference();
result = setOtherReferences();
image = getStarImages();
if (image != null && result && imgArr != null && backgroundImg != null) {
Loop();
}
}
function getCtxReference() {
canvas = document.getElementById("canvas");
return canvas.getContext('2d');
}
function getStarReference() {
starCanvas = document.createElement("canvas");
starCanvas.height = 50;
starCanvas.width = 50;
starCanvas.id=('star');
document.body.appendChild(starCanvas);
return starCanvas.getContext('2d');
}
function setOtherReferences() {
slider = document.getElementById("rangeInput");
vBox = document.getElementById("textbox");
scaleX = 100;
scaleY = 100;
center.x = canvas.width / 3;
center.y = canvas.height / 3;
return true;
}
function drawImg() {
ctx.drawImage(starCanvas, x, y, scaleX, scaleY);
return true;
}
function Loop() {
window.setTimeout(Loop, 100);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(backgroundImg, 0,0);
angle += Math.PI * 0.05;
x = center.x + radius * Math.cos(angle);
y = center.y + radius * Math.sin(angle);
vBox.value = slider.value;
updateStarScale();
drawImg();
}
function getStarImages() {
//as they're all the same image, you don't need to make an array of them, simply make a loop below
var img = new Image();
img.addEventListener('load', drawBackgroundStar)
img.src = createStar();
return img;
}
function drawBackgroundStar() {
for (var i=0; i<500; i++) {
ctx.drawImage(image, getRandomArbitrary(0, canvas.width), getRandomArbitrary(0, canvas.height), getRandomArbitrary(5, 15), getRandomArbitrary(5, 15));
}
backgroundImg = new Image();
backgroundImg.addEventListener('load', Loop);
backgroundImg.src = canvas.toDataURL();
starCtx.drawImage(image, 0,0,50,50)
}
function updateStarScale() {
if (vBox.value > 0) {
scaleX += vBox.value / 10;
scaleY += vBox.value / 10;
changeImgColorToBlue();
} else if (vBox.value < 0) {
scaleX -= Math.abs(vBox.value / 10);
scaleY -= Math.abs(vBox.value / 10);
changeImgColorToRed();
}
if (scaleX > 600 || scaleY > 600) {
scaleX = 600;
scaleY = 600;
} else if (scaleX < 50 || scaleY < 50) {
scaleX = 50;
scaleY = 50;
}
}
function changeImgColorToBlue() {
imageData = starCtx.getImageData(0, 0, 50, 50);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
//is our data black?
if(data[i]>0||data[i+1]>0||data[i+2]>0){
data[i] = 0;// red
data[i + 1] = 0; // green
data[i + 2] = 255; // blue
}
}
starCtx.putImageData(imageData, 0, 0);
}
function changeImgColorToRed() {
imageData = starCtx.getImageData(0, 0, 50, 50);
data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
if(data[i]>0||data[i+1]>0||data[i+2]>0){
data[i] = 255;// red
data[i + 1] = 0; // green
data[i + 2] = 0; // blue
}
}
starCtx.putImageData(imageData, 0, 0);
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
start();
body {
text-align: center;
}
#container {
position: fixed;
color: red;
top: 0px;
left: 0px;
}
#textBox {
position: absolute;
top: 25px;
left: 5px;
}
#slider {
position: absolute;
top: 25px;
left: 200px;
}
<canvas id="canvas" width="1024" height="768"></canvas>
<div id="container">
<div id="textBox">
Velocity:
<input type="text" id="textbox" value="0">
</div>
<div id="slider">
Slider:
<form oninput="amount.value=rangeInput.value">
<input type="range" id="rangeInput" name="rangeInput" min="-100" max="100" step="3" value="">
<output name="amount" for="rangeInput">0</output>
</form>
</div>
</div>