Generate color palette using JavaScript - javascript

I want to generate a color palette of every 5th, 15th,17th or 51th RGB-value.
Something like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Color Palette</title>
<style type="text/css">
div{margin:0;width:20px;height:20px;float:left}
.clear{clear:both}
</style>
</head>
<body>
<script>
var r = 0,
g = 0,
b = 0;
function createBr() {
var b = document.createElement('br');
b.style.clear = 'both';
document.body.appendChild(b);
}
function createDiv(r,g,b) {
var a = document.createElement('div');
a.style.background = 'rgb(' + r + ',' + g + ',' + b + ')';
document.body.appendChild(a);
}
function createColorPalette(value) {
var v = 255/value;
for(i = 0; i < v; i++) {
r = r + value;
g = g + value;
b = b + value;
createDiv(r,g,b);
}
createBr();
}
// put in 5,15,17 or 51 as value below
window.onload = createColorPalette(17);
</script>
</body>
</html>
I'm not smart enough to figure out how to generate all the 3375 colors with a small script. Any ideas how to do that?

Cycle through the fractions for each color like so:
function createColorPalette(value) {
var v = 255/value;
for( var rStep = 0, r = 0; rStep < v; rStep++) {
for( var gStep = 0, g = 0; gStep < v; gStep++ ) {
for( var bStep = 0, b = 0; bStep < v; bStep++ ) {
createDiv(r,g,b);
b += value;
}
g += value;
}
r += value;
}
createBr();
}

Related

js chrome graphics problem: data is correct, render is wrong

I am a beginner at JS so I hope this problem is not too ridiculous. I want to render a white square 6x6 with a blue square 2x2 in the centre, using Canvas. When I print out the data I generate, it seems ok. But when it renders, all I get is a blue square 6x6. This is part of a larger file but I have simplified it to concentrate on this one problem. Using chrome devtools. Thanks.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>obstacleTest</title>
</head>
<body>
<script>
let _data;
let gridLength = 6;
let grid = [];
let tempGrid = [];
function drawGrid (data) {
let width = 600;
let height = 600;
let gridLength = data.length;
let widthCell = width / gridLength;
let heightCell = height / gridLength;
let canvas = document.getElementById("grid");
if (canvas == null) {
canvas = document.createElement("canvas");
canvas.id = "grid";
canvas.width = width;
canvas.height = height;
document.getElementsByTagName("body")[0].appendChild(canvas);
}
let context = canvas.getContext("2d");
function drawCells () {
for (let i = 0; i < gridLength; i++) {
for (let j = 0; j < gridLength; j++) {
if (_data && _data[i][j] === cellColor(data[i][j])) {
continue;
}
context.clearRect(
i * widthCell,
j * heightCell,
widthCell,
heightCell
);
context.fillStyle = cellColor(data[i][j]);
context.fillRect(
i * widthCell,
j * heightCell,
widthCell,
heightCell
);
}
}
}
drawCells();
if (!_data) {
_data = [];
}
for (let i = 0; i < gridLength; i++) {
_data[i] = [];
for (let j = 0; j < gridLength; j++) {
_data[i][j] = cellColor(data[i][j]);
}
}
}
function updateGrid (data) {
drawGrid(data);
}
let cellColor = function (cell) {
return cell.obstacle = true ? "rgb(0,0,250)" : "rgb(125, 125, 125)"; //blue or grey
};
function Cell (i, j) {
this.i = i;
this.j = j;
this.obstacle = false;
}
function initGrids () {
for (let i = 0; i < gridLength; i = i + 1) {
grid[i] = [];
tempGrid[i] = [];
for (let j = 0; j < gridLength; j = j + 1) {
grid[i][j] = new Cell(i, j);
tempGrid[i][j] = new Cell(i, j);
}
}
}
function setObstacle () {
let xmin = 2;
let xmax = 3;
let ymin = 2;
let ymax = 3;
console.log("xmin, xmax, ymin, ymax ; " + xmin, xmax, ymin, ymax);
for (let i = xmin; i <= xmax; i++) {
for (let j = ymin; j <= ymax; j++) {
grid[i][j].obstacle = true; // implies blue
console.log(i, j, grid[i][j].obstacle);
}
console.log("________________");
}
}
//___________________________________________________________________________
initGrids();
for (let i = 0; i < gridLength; i++) {
for (let j = 0; j < gridLength; j++) {
grid[i][j].obstacle = false;
console.log(i, j, grid[i][j].obstacle);
}
console.log("_______");
}
setObstacle();
drawGrid(
grid.map(function (row) {
return row.map(function (cell) {
return cell;
});
})
);
//____________________________________________________________________________
</script>
</body>
</html>
There is a really tiny error in your code which causes your issue.
Let's have a look at the function returning the appropriate color based on the obstacle property:
let cellColor = function (cell) {
return cell.obstacle = true ? "rgb(0,0,250)" : "rgb(125, 125, 125)"; //blue or grey
};
If obstacle is true it should return blue and if not gray. The problem is that
return cell.obstacle = true
is not a comparison it's an assignment. So as you always assign true to obstacle, all you get is the blue color.
Try changing it to this:
return cell.obstacle === true

Paint bucket getting "Maximum Call Stack Size Exceeded" error

This is the code of the paint bucket tool in my drawing app using the p5.js library. The function self.floodFill always get "Maximum Call Stack Size Exceeded" because of recursion and I want to know the way to fix it. I am thinking if changing the function to a no recursion function would help or not. Any help would be appreciated.
function BucketTool(){
var self = this;
//set an icon and a name for the object
self.icon = "assets/bucket.jpg";
self.name = "Bucket";
var d = pixelDensity();
var oldColor;
var searchDirections = [[1,0],[-1,0],[0,1],[0,-1]];
var pixelsToFill = [];
var positionArray = new Array(2);
self.checkBoundary = function(currentX, currentY, localOldColor) {
if (self.getPixelAtXYPosition(currentX,currentY).toString() != localOldColor.toString() || currentX < 0 || currentY < 0 || currentX > width || currentY > height || pixelsToFill.indexOf(currentX+" "+currentY) != -1) {
return false;
}
return true;
};
self.floodFill = function(currentX, currentY, localOldColor, localSearchDirections) {
if (self.checkBoundary(currentX, currentY, localOldColor)){
pixelsToFill.push(currentX+" "+currentY);
} else {
return;
}
for (var i = 0; i < searchDirections.length; i++){
self.floodFill(currentX + searchDirections[i][0], currentY + searchDirections[i][1], localOldColor, localSearchDirections);
}
};
self.getPixelAtXYPosition = function(x, y) {
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
// loop over
index = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[index];
colour[1] = pixels[index+1];
colour[2] = pixels[index+2];
colour[3] = pixels[index+3];
}
}
return colour;
}
self.drawTheNeededPixels = function(){
for(var i = 0; i < pixelsToFill.length; i++){
positionArray = pixelsToFill[i].split(" ");
point(positionArray[0],positionArray[1]);
}
}
self.draw = function () {
if(mouseIsPressed){
pixelsToFill = [];
loadPixels();
oldColor = self.getPixelAtXYPosition(mouseX, mouseY);
self.floodFill(mouseX, mouseY, oldColor, searchDirections);
self.drawTheNeededPixels();
}
};
}
This problem is well documented on the wikipedia page and the shortfalls of the different types of algorithms to perform flood filling. You've gone for the stack-based recursive implementation.
To prevent a stackoverflow — Maximum Call Stack Exceeded — the first step would be to use a data structure. Using queues/stacks rather than having the function call itself.
The code below creates an empty stack where we put a new object containing the x and y where the user has chosen to fill. This is then added to the pixelsToFill array. We then loop the stack until it's completely empty, at which point we are ready to display the filled pixels.
In the while loop we pop an element off the stack and then find its children — the directions up, down, left, right denoted by the searchDirections array you created. If we've not seen the child before and it's within the boundary we add it to the pixelsToFill array and add it to the stack to repeat the process:
self.floodFill = function (currentX, currentY, localOldColor, localSearchDirections) {
let stack = [];
stack.push({ x: currentX, y: currentY });
pixelsToFill.push(currentX + " " + currentY);
while (stack.length > 0) {
let current = stack.pop();
for (var i = 0; i < searchDirections.length; i++) {
let child = {
x: current.x + searchDirections[i][0],
y: current.y + searchDirections[i][1],
localOldColor,
};
if (self.checkBoundary(child.x, child.y, localOldColor)) {
pixelsToFill.push(child.x + " " + child.y);
stack.push(child);
}
}
}
};
This code may stop the stackoverflow but there are still a lot of optimisations that can be made. Once again, it's worth checking out the Wikipedia page and potentially take a look at Span filling.
let bucketTool;
function setup() {
createCanvas(400, 400);
bucketTool = new BucketTool();
}
function draw() {
background(220);
strokeWeight(5);
circle(width / 2, height / 2, 100);
frameRate(1);
bucketTool.draw();
}
function BucketTool() {
var self = this;
//set an icon and a name for the object
// self.icon = "assets/bucket.jpg";
// self.name = "Bucket";
var d = pixelDensity();
var oldColor;
var searchDirections = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
var pixelsToFill = [];
var positionArray = new Array(2);
self.checkBoundary = function (currentX, currentY, localOldColor) {
if (
self.getPixelAtXYPosition(currentX, currentY).toString() !=
localOldColor.toString() ||
currentX < 0 ||
currentY < 0 ||
currentX > width ||
currentY > height ||
pixelsToFill.indexOf(currentX+" "+currentY) != -1
) {
return false;
}
return true;
};
self.floodFill = function (currentX, currentY, localOldColor, localSearchDirections) {
let stack = [];
stack.push({ x: currentX, y: currentY });
pixelsToFill.push(currentX + " " + currentY);
while (stack.length > 0) {
let current = stack.pop();
for (var i = 0; i < searchDirections.length; i++) {
let child = {
x: current.x + searchDirections[i][0],
y: current.y + searchDirections[i][1],
localOldColor,
};
if (self.checkBoundary(child.x, child.y, localOldColor)) {
pixelsToFill.push(child.x + " " + child.y);
stack.push(child);
}
}
}
};
self.getPixelAtXYPosition = function (x, y) {
var colour = [];
for (var i = 0; i < d; i++) {
for (var j = 0; j < d; j++) {
// loop over
index = 4 * ((y * d + j) * width * d + (x * d + i));
colour[0] = pixels[index];
colour[1] = pixels[index + 1];
colour[2] = pixels[index + 2];
colour[3] = pixels[index + 3];
}
}
return colour;
};
self.drawTheNeededPixels = function () {
for (var i = 0; i < pixelsToFill.length; i++) {
positionArray = pixelsToFill[i].split(" ");
point(positionArray[0], positionArray[1]);
}
};
self.draw = function () {
if (mouseIsPressed) {
pixelsToFill = [];
loadPixels();
oldColor = self.getPixelAtXYPosition(mouseX, mouseY);
self.floodFill(mouseX, mouseY, oldColor, searchDirections);
console.log(pixelsToFill.length);
self.drawTheNeededPixels();
}
};
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>
Shameless plug, but relevant: I've created a blog comparing the different flood fill algorithms using p5.js.

chart js graph legend colors

I have this code for chart working as fine. I can make the color background for the legend depends on the $scope.colours but for this example is I have a static of 3 datas only. But my problem here is that the data I get is from the database.
It is possible that generated color for the graph should be the background color for the legends?.
Source Link for chart
var app = angular.module('App', ['chart.js']);
app.controller('Ctrl', function ($scope) {
$scope.labels = ["A","B","C"];
$scope.data = ["1","2","3"];
$scope.colours = ['#bff0dd', '#ffa67b','#b1c2ff'];
});
<html ng-app="App" ng-controller="Ctrl">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-chart.js/0.10.2/angular-chart.js"></script>
</head>
<body>
<canvas id="doughnut" class="chart chart-doughnut doughnut-year"
chart-colours="colours"
chart-data="data" chart-labels="labels">
</canvas>
<h3>Legends</h3>
<div class="legend-item" ng-repeat="a in colours">
<label>
A
</label>
</div>
</body>
</html>
you can generate color codes as follows:
angular.forEach($scope.data , function (dataItem, index) {
var colorCode = getColorHex(index);
$scope.colours.push(colorCode);
});
var getColorHex = function (i) {
//skip black & white
i+=2;
var colorDecimal = getRGB(i);
var colorHex = decimalColorToHTMLcolor(colorDecimal);
return colorHex;
}
function decimalColorToHTMLcolor(colorDecimal) {
var intnumber = colorDecimal - 0;
var red, green, blue;
var template = "#000000";
red = (intnumber & 0x0000ff) << 16;
green = intnumber & 0x00ff00;
blue = (intnumber & 0xff0000) >>> 16;
intnumber = red | green | blue;
var HTMLcolor = intnumber.toString(16);
HTMLcolor = template.substring(0, 7 - HTMLcolor.length) + HTMLcolor;
return HTMLcolor;
}
function getRGB(index) {
var p = getPattern(index);
return getElement(p[0]) << 16 | getElement(p[1]) << 8 | getElement(p[2]);
}
function getElement(index) {
var value = index - 1;
var v = 0;
for (var i = 0; i < 8; i++) {
v = v | (value & 1);
v <<= 1;
value >>= 1;
}
v >>= 1;
return v & 0xff;
}
function getPattern(index) {
var n = parseInt(Math.cbrt(index));
index -= (n*n*n);
var p = [n, n, n];
if (index == 0) {
return p;
}
index--;
var v = index % 3;
index = parseInt(index / 3);
if (index < n) {
p[v] = index % n;
return p;
}
index -= n;
p[v] = parseInt(index / n);
p[++v % 3] = index % n;
return p;
}

How to access value of a dynamically created text node in a later click event?

I have a Javascript project. It's a multiplication table that when click on each cell it should be show the result of that cell.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<style>
.tdstyles {
width: 50px;
height: 50px;
text-align: center;
}
</style>
</head>
<body>
<div id="Holder"></div>
</body>
</html>
<script type="text/javascript">
var m;
window.onload = function () {
var table = document.createElement('table');
table.border = 1;
table.cellPadding = 0;
table.cellSpacing = 0;
for (var i = 1; i <= 10; i++) {
var tr = document.createElement('tr');
for (var j = 1; j <= 10; j++) {
m = i*j;
var td = document.createElement('td');
var newContent = document.createTextNode(m);
td.className = "tdstyles";
tr.appendChild(td);
td.appendChild(newContent);
document.getElementsByTagName("td").innerHTML = m;
td.onclick = function () {
console.log();
};
var a = Math.round(Math.random() * 255);
var b = Math.round(Math.random() * 255);
var c = Math.round(Math.random() * 255);
td.style.backgroundColor = "rgb(" + a + "," + b + "," + c + ")";
// myFunction();
}
table.appendChild(tr);
Holder.appendChild(table)
}
};
</script>
How can I save that TextNode when it is in loop and use it when click on that td?
You should save the reference to the text in a closure for each inner iteration so that it can be accessed later. Also note that it's probably a lot easier to assign to the textContent of an element if its only child is going to be a text node.
for (let j = 1; j <= 10; j++) {
const text = i * j;
const td = tr.appendChild(document.createElement('td'));
td.textContent = 'text';
td.className = "tdstyles";
td.onclick = function() {
console.log(text);
};
// ...
Do note that I'm using const and let rather than var - this is very important. var has function scope and is hoisted, which can easily result in confusion, especially when you have any asynchronous code; const and let are much more intuitive.
If you need to run the JavaScript in older browsers, you can wrap the onclick with an IIFE and send the text as an argument.
for (let j = 1; j <= 10; j++) {
var text = i * j;
var td = tr.appendChild(document.createElement('td'));
td.textContent = 'text';
td.className = "tdstyles";
!function (t) {
td.onclick = function() {
console.log(t);
}
}(text);
///...
}

Fibonacci Series with JavaScript

var var1 = 0;
var var2 = 1;
var var3;
var num = 20;
document.write(var1 + "<br />");
document.write(var2 + "<br />");
for (var i = 3; i <= num; i++) {
var3 = var1 + var2;
var1 = var2;
var2 = var3;
document.write(var3 + "<br />");
}
Best, I'm doing a Fibonacci Series, but I want to see a message with prompt comes up, so you can fill in a number, then the returns with the Fibonacci Series. Who would be able to help me? Above I have now.
I have created demo, hope it will help you.
var i;
var fib = [0, 1];
var limit = window.prompt('Enter the limit for your series:', '');
for (i = 2; i < parseInt(limit); i++) {
fib[i] = fib[i - 2] + fib[i - 1];
}
console.log(fib);
Demo Link
function myFunction() {
var n = document.getElementById("myNumber").value;
document.getElementById("demo").innerHTML = fibonacciGenerator (n);
}
var sequence = [0]; // sequence = []; if you want sequence [1] = 1;
var previousNumber = 1;
var presentNumber = 0;
var sum = 0;
function fibonacciGenerator (n) {
while (sequence.length < n) {
sum = previousNumber + presentNumber;
previousNumber = presentNumber;
presentNumber = sum;
sequence.push(sum);
}
return (sequence);
}
<!DOCTYPE html>
<html>
<body>
<h1>Fibonacci Generator </h1>
<input type="number" id="myNumber" value="0">
<p>Enter a number to generate Fibonacci array.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
</body>
</html>
Using ES6 generator
function* fiboGen(len, current = 0, next = 1) {
if (len === 0) {
return current;
}
yield current;
yield* fiboGen(len - 1, next, current + next);
}
const fibo = [...fiboGen(10)];
console.log(fibo);
//[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
you need to use a prompt box to get the number:
window.prompt("sometext","defaultText");
http://www.w3schools.com/js/js_popup.asp
I hope that this is what you are looking for.
HTML:
Which sequence of the Fibonacci pattern do you want to find?
<br><br>
<input type="text" id="inputtext">
<br><br>
<input type="button" value="Find out" id="btn">
<br><br>
<b id="ID"></b>
JS:
function add(a, b) {
while (a.length < b.length) a.unshift(0);
while (a.length > b.length) b.unshift(0);
var carry = 0,
sum = [];
for (var i = a.length - 1; i >= 0; i--) {
var s = a[i] + b[i] + carry;
if (s >= 10) {
s = s - 10;
carry = 1;
} else {
carry = 0;
}
sum.unshift(s);
}
if (carry) sum.unshift(carry);
return sum;
}
function fib(n) {
var f1 = [0];
var f2 = [1];
while (n--) {
var f3 = add(f1, f2);
f1 = f2;
f2 = f3;
}
return f1.join("");
}
document.getElementById("btn").onclick = function () {
var inputnum = parseFloat(document.getElementById("inputtext").value);
document.getElementById("ID").innerHTML = fib(inputnum).toString();
};
Fiddle.
var number = prompt("Enter number ");
....... your code ....
You can do the following:
var var1 = 0;
var var2 = 1;
var var3;
var num = window.prompt("Enter the limit for your series:","");
//var num = 20;
var str = '';
str+=var1+','+var2;
for(var i=3; i <= parseInt(num);i++)
{
var3 = var1 + var2;
var1 = var2;
var2 = var3;
str+=','+var3;
}
document.write(str);
<!doctype html>
<html lang="en">
<head>
<body>
<script type="text/javascript">
var f1=0,f2=1,f3;
var i;
alert("enter a text"+n);
var n=prompt("enter the number");
document.write("the fibonacci series is "+"<br/>");
for(i=2;i<=n;i++)
{
f3=f1+f2;
f1=f2;
f2=f3;
document.write(f3+"<br/>");
}
</script>
<style>
body {background-color:#66ff66}
</style>
</head>
</body>
i came up with this solution to get the n index Fibonacci value. you can use the findFac0(); to pass the index you need to get the Fibonacci value.
function findFac(n){
if (n===1)
{
return [0, 1];
}
else
{
var s = findFac(n - 1);
s.push(s[s.length - 1] + s[s.length - 2]);
return s;
}
}
function findFac0(n){
var vv1 = findFac(n);
return vv1[n-1];
}
console.log(findFac0(10));
I've tried this: it might work:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fibonacci</title>
<style>
* {
outline: 0px;
margin: 0px;
}
input[type="number"] {
color: blue;
border: 2px solid black;
width: 99.58vw;
}
</style>
</head>
<body>
<div id="myDiv" style="color: white;background-color: blue;">Numbers Here</div>
<input type="number" id="input1" oninput="fibonacciProgram(this.value)" placeholder="Type Some Numbers Here">
<script>
function fibonacciProgram(numberCount) {
let resultElement = document.getElementById("myDiv");
resultElement.innerHTML = " ";
if (isNaN(numberCount) || numberCount <= 0) {
resultElement.innerHTML = "please enter a number";
return;
}
let firstBox = 0;
let secondBox = 1;
let swichBox;
let entries = [];
entries.push(secondBox);
while (numberCount > 1) {
swichBox = firstBox + secondBox;
entries.push(swichBox);
firstBox = secondBox;
secondBox = swichBox;
numberCount--;
}
resultElement.innerHTML = entries.join(', ');
}
</script>
</body>
</html>

Categories