HTML canvas recolour/edit a shape or array? - javascript

I am building a real-time canvas clicking game, and am almost complete.
I need to change the colour of a canvas drawn element. I hear this cannot be done.
I have a variable holding these properties of the clicked shape for use on both clients:
{ x: 446.48232363630086,
y: 279.37327971844934,
dx: 2.829614687943831,
dy: -3.0215198849327862,
rad: 26,
color: 'rgb(146,25,122)' }
And I have another variable holding a new colour, if it is not possible to change the colour of a something drawn on the canvas, can I edit the object in the array which would make my current drawShape function redraw the changed shape? This is my old single player code for some reference.
https://jsfiddle.net/a9b3rm5u/5/ Thank you

I figured it out:
var i = data.shapeRemoval;//object data
var c = data.colours; // colour data
var r = c;
shapes.splice(i,1); // removes old object from array
i.color = c; // replaces the color in the object for the variable C
shapes.push(i)// pushes to array

Related

I cant update my object value , for my Java script game (canvas)

This is my Constructor for game enemy:
enter code here:
/// my constructor for enemy
function masinaCon(x,y,width,height,color){
this.x=x;
this.y=y;
this.width=width;
this.height=height;
this.color=color;
this.draw=function(){
ctx.fillStyle=color;
ctx.fillRect(x,y,width,height);
};
}
// color of contsructor
function color(){
return 'rgb('+Math.floor(Math.random()*1000)+','+Math.floor(Math.random()*100)+','+Math.floor(Math.random()*180)+')';
}
// array of enemy
var niz=[];
///////////////////////////// end of code
i filled the array(var niz=[]) with 10 objects and i wanted to move the third object 2pixels down, so that repeats in every frame, in order for it to look like a game(falling effect => niz[2].y+=2;)
And when i print, the cordinates in the object are increasing but, when i print them(the objects), there is no change(visually), could someone help me out with this.
It simple. The x and y references the original ones from the constructor. Just update the x and y inside the draw function to reference the object ones using this
this.draw=function(){
ctx.fillStyle=color;
ctx.fillRect(this.x,this.y,this.width,this.height); // x->this.x etc
};

Getting the RGB values for a CSS/HTML named color in JavaScript

I've built a name-[rgb] Javascript object. Your basic:
namedColors = {
AliceBlue: [240, 248, 255],
AntiqueWhite: [250, 235, 215],
...
object. But it occurred to me that I should be able to take a name string, "AliceBlue", say .. and have JavaScript find some sort of RGB representation of it (hex is fine). I know there are at least 140 named colors tucked away in the browser, but I can't seem to find them.
Is there a CSS or "style=..." stunt that lets me look up an RGB representation of a color name?
Minimal JavaScript function:
function nameToRgba(name) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.fillStyle = name;
context.fillRect(0,0,1,1);
return context.getImageData(0,0,1,1).data;
}
This is the solution I ended up with. I realized that colors came in two types: css strings and webgl typed arrays (usually 4 floats or ints, depending).
Hell with it, let the browser figure it: create a 1x1 canvas, fill it with any string color, grab the pixel, and destructure into an rgba array. There are two utilities below that create the 1x1 2d canvas ctx, attached.
# Return an RGB array given any legal CSS color, null otherwise.
# http://www.w3schools.com/cssref/css_colors_legal.asp
# The string can be CadetBlue, #0f0, rgb(255,0,0), hsl(120,100%,50%)
# The rgba/hsla forms ok too, but we don't return the a.
# Note: The browser speaks for itself: we simply set a 1x1 canvas fillStyle
# to the string and create a pixel, returning the r,g,b values.
# Warning: r=g=b=0 can indicate an illegal string. We test
# for a few obvious cases but beware of unexpected [0,0,0] results.
ctx1x1: u.createCtx 1, 1 # share across calls. closure wrapper better?
stringToRGB: (string) ->
#ctx1x1.fillStyle = string
#ctx1x1.fillRect 0, 0, 1, 1
[r, g, b, a] = #ctx1x1.getImageData(0, 0, 1, 1).data
return [r, g, b] if (r+g+b isnt 0) or
(string.match(/^black$/i)) or
(string in ["#000","#000000"]) or
(string.match(/rgba{0,1}\(0,0,0/i)) or
(string.match(/hsla{0,1}\(0,0%,0%/i))
null
What I love about it is that The Browser Speaks For Itself. Any legal string works just fine. Only downside is that if the string is illegal you get black, so need to do a few checks. The error checking is not great, but I don't need it in my usage.
The utility functions:
# Create a new canvas of given width/height
createCanvas: (width, height) ->
can = document.createElement 'canvas'
can.width = width; can.height = height
can
# As above, but returing the context object.
# Note ctx.canvas is the canvas for the ctx, and can be use as an image.
createCtx: (width, height) ->
can = #createCanvas width, height
can.getContext "2d"
Have a look into Colors.js with the functions "name2hex" and "name2rgb" this libary returns the hex or rgb values of your color name.
You can use a canvas to get the RGBA color from a name.
Please look at this fiddle: https://jsfiddle.net/AaronWatters/p1y298zk/19/
// We want to know the rgba values for this color name:
var testColor = "salmon"
// make a canvas
var canvas = $('<canvas width="100px" height="100px">');
// optional: display the canvas
var body = $(document.body);
canvas.appendTo(body);
// draw a rectangle on the canvas
var context = canvas[0].getContext("2d");
context.beginPath();
context.rect(0,0,100,100);
context.fillStyle = testColor;
context.fill();
// get the canvas image as an array
var imgData = context.getImageData(0, 0, 10, 10);
// rbga values for the element in the middle
var array = imgData.data.slice(50*4, 50*4+4);
// convert the opacity to 0..1
array[3] = array[3] / 255.0;
$("<div>The rgba for " + testColor + " is " + array + "</div>").appendTo(body);
This is how jp_doodle does color interpolation in transitions: https://aaronwatters.github.io/jp_doodle/080_transitions.html
Other approaches on this page use HTML5 Canvas.
But a straightforward alternative would be to derive the rgb() value from any color keyword using:
window.getComputedStyle()
Working Example:
const colorKeywordToRGB = (colorKeyword) => {
// CREATE TEMPORARY ELEMENT
let el = document.createElement('div');
// APPLY COLOR TO TEMPORARY ELEMENT
el.style.color = colorKeyword;
// APPEND TEMPORARY ELEMENT
document.body.appendChild(el);
// RESOLVE COLOR AS RGB() VALUE
let rgbValue = window.getComputedStyle(el).color;
// REMOVE TEMPORARY ELEMENT
document.body.removeChild(el);
return rgbValue;
}
// BASIC COLORS
console.log('red:', colorKeywordToRGB('red'));
console.log('green:', colorKeywordToRGB('green'));
console.log('yellow:', colorKeywordToRGB('yellow'));
console.log('blue:', colorKeywordToRGB('blue'));
// SIMPLE COLORS
console.log('fuchsia:', colorKeywordToRGB('fuchsia'));
console.log('lime:', colorKeywordToRGB('lime'));
console.log('maroon:', colorKeywordToRGB('maroon'));
console.log('navy:', colorKeywordToRGB('navy'));
console.log('olive:', colorKeywordToRGB('olive'));
console.log('purple:', colorKeywordToRGB('purple'));
console.log('teal:', colorKeywordToRGB('teal'));
console.log('transparent:', colorKeywordToRGB('transparent'));
// ADVANCED COLORS
console.log('blanchedalmond:', colorKeywordToRGB('blanchedalmond'));
console.log('coral:', colorKeywordToRGB('coral'));
console.log('darkorchid:', colorKeywordToRGB('darkorchid'));
console.log('firebrick:', colorKeywordToRGB('firebrick'));
console.log('gainsboro:', colorKeywordToRGB('gainsboro'));
console.log('honeydew:', colorKeywordToRGB('honeydew'));
console.log('papayawhip:', colorKeywordToRGB('papayawhip'));
console.log('seashell:', colorKeywordToRGB('seashell'));
console.log('thistle:', colorKeywordToRGB('thistle'));
console.log('wheat:', colorKeywordToRGB('wheat'));
Further Reading:
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

Need a solid way to set relational indices for object polygons drawn in a canvas element

Okay this is going to be hard to explain. So bear with me.
Im having less of a problem with the programming, and more a problem with the idea behind what Im trying to do.
I have a grid of triangles. Ref: http://i.imgur.com/08BPHiD.png [1]
Each triangle is it's own polygon on a canvas element that I have set as an object within the code. The only difference between the objects is the coordinates that I pass through as parameters of a function like so:
var triCoordX = [1, 2, 3, ...];
var triCoordY = [1, 2, 3, ...];
var triCoordFlipX = [1, 2, 3, ...];
var triCoordFlipY = [1, 2, 3, ...];
var createTri = function(x, y, z) {
return {
x: x,
y: y,
sides: 3,
radius: 15,
rotation: z,
fillRed: 17,
fillGreen: 17,
fillBlue: 17,
closed: true,
shadowColor: '#5febff',
shadowBlur: 5,
shadowOpacity: 0.18
}
};
for (i = 0; i < triCoordX.length; i++){
var tri = new Kinetic.RegularPolygon(createTri(triCoordX[i], triCoordY[i], 0));
}
for (i = 0; i < triCoordFlipX.length; i++){
var triFlip = new Kinetic.RegularPolygon(createTri(triCoordFlipX[i], triCoordFlipY[i], 180));
}
Now what Im trying to do exactly is have each object polygon be able to 'recognise' its neighbors for various graphical effects.
How I propose to do this is pass a 4th parameter into the function that I push from another array using the for loop that sets a kind of "index" for each polygon. Also in the for loop I will define a function that points to the index 'neighbors' of the object polygon.
So for instance, if I want to select a random triangle from the grid and make it glow, and on completion of a tween want to make one of it's neighbors glow I will have the original triangle use it's object function to identify a 'neighbor' index and pick at random one of its 3 'neighbors'.
The problem is with this model, Im not entirely sure how to do it without large amounts of bloat in my programming, or when I set the function for the loop, to set a way for the loop to intuitively pick the correct index numbers for what are actually the triangle's neighbors.
If all of that made sense, Im looking for any and all suggestions.
Think of your triangles as being laid out in a grid with the triangle in the top left corner being col==0, row==0.
Then you can find the row/col coordinates of the 3 neighbors of any triangle with the following function.
Ignore any neighbors with the following coordinates because the neighbors would be off the grid.
col<0
row<0
col>ColumnCount-1
row>RowCount-1
Example code (warning...untested code--you may have to tweak it):
function findNeighbors(t){
// determine if this triangle's row/col are even or odd
var evenRow=(t.col%2==0);
var evenCol=(t.row%2==0;
// left neighbor is always the same
n1={ col:t.col-1, row:t.row };
// right neighbor is always the same
n2={ col:t.col+1, row:t.row };
// third neighbor depends on row/col being even or odd
if(evenRow && evenCol){
n3={ col:t.col, row:t.row+1 };
}
if(evenRow && !evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && evenCol){
n3={ col:t.col, row:t.row-1 };
}
if(!evenRow && !evenCol){
n3={ col:t.col, row:t.row+1 };
}
// return an array with the 3 neighbors
return([n1,n2,n3]);
}

Trouble in writing a small library in JavaScript

I'd been trying to write a small library in Javascript mainly for Canvas drawImage() method.
The main purpose of the library is to pass array values instead of passing single values such as :
// srcPos=[0,0] , size=[90,90], dstPos=[50,50]
function draw_image(context, image, srcPos, size, dstPos, size) {
context.drawImage(image, srcPos[0], srcPos[1], size[0], size[1], dstPos[0], dstPos[1], size[0], size[1]);
}
but when i called this function jzz like this, I'm getting Uncaught ReferenceError :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
var shipInfo = { center:[45, 45], size:[90, 90], radius: 35, angle:45 },
shipImage = new Image(),
pos = [40, 70];
shipImage.src = "ship.png";
function draw() {
draw_image(frame, shipImage, shipInfo.size, pos, shipInfo.size);
}
window.onload = function() {
draw();
}
And Is it possible to implement a method overriding the default drawImage() like this:
frame.draw_image(shipImage, srcPos, shipInfo.size, dstPos, shipInfo.size);
If you want to add a function to the 2d context, javascript makes this easy thanks to the prototype inheritance : You can inject the Context2D object to add or change its function as you wish.
You might want to look at a few addings i made to the context in a small canvas lib i made here : https://github.com/gamealchemist/CanvasLib
Some will tell that injecting is evil, but unless you're on a huge boat i would just say : If you use some graphic library, respect the semantic of existing functions and everything should be fine. If you don't use libs : do whatever it takes !
So, to answer more specifically to your question, your shorter drawImage would give :
CanvasRenderingContext2D.prototype.draw_image = function ( image,
srcPos, size,
dstPos, size) {
this.drawImage(image, srcPos[0], srcPos[1], size[0], size[1],
dstPos[0], dstPos[1], size[0], size[1]);
};
Then you can use the new function on all your contexts :
var canvas = document.getElementById("display"),
frame = canvas.getContext("2d");
frame.draw_image( ... ) ;
Notice that you could use 'rect' objects, which would be arrays with 4 elements, x, y, w, h, and lead to an even shorter syntax.
Edit : i see in your lib that you want to rotate your rect.
First thing is that you don't want to reset the transform. Just save it then restore it.
I would try something closer to this :
var x = dstPos[0],
y = dstPos[1],
halfWidth = dstSize[0]*0.5, // !! not src use >>1 if you know it's an int.
halfHeight = dstSize[1]*0.5, // !! not src ...
angleInRads = angle * Math.PI / 180;
this.save();
this.translate(x+halfWidth,y+halfHeight);
this.rotate(angleInRads);
this.drawImage(image
, center[0], center[1], srcSize[0], srcSize[1]
, -halfWidth, -halfHeight, dstSize[0],dstSize[1]);
this.restore();
Your small image library would fit well inside a javascript object.
A Demo: http://jsfiddle.net/m1erickson/7pZJw/
A javascript object can hold information about your image:
the image itself
the image size (can be automatically calculated for you)
the image centerpoint (can be automatically calculated for you)
Example:
// create a new object
// fill it with the info about the image
var object={
image:shipImage,
width:shipImage.width,
height:shipImage.height,
centerOffsetX:shipImage.width/2,
centerOffsetY:shipImage.height/2,
radius:35,
angle:45,
};
A javascript object can also hold functions that draws the image (as you've done in your code)
Example:
// when you call object.draw the image will be drawn by this function
// which is added to the object itself
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
A function to create your small image library inside a javascript object might look like this:
function createImageObject(image,radius,angle){
// create a new object
// fill it with the info about the image
var object={
image:image,
width:image.width,
height:image.height,
centerOffsetX:image.width/2,
centerOffsetY:image.height/2,
radius:radius,
angle:angle,
draw:function(context,atX,atY,newWidth,newHeight){
context.drawImage(
this.image,
0,0,this.width,this.height,
atX,atY,newWidth,newHeight);
},
};
return(object);
}
And you can use your ship object library like this:
// create a new ship object
var shipObject=createImageObject(img,35,45);
// draw the ship image using the ship object
// draw at 20,20 with size 75,75
shipObject.draw(frame,20,20,75,75);
BTW, I see you're using the version of drawImage that will scale/clip the source image.
If you just want to draw the full image at its original size you can do this shortcut:
// draw the image full-sized at x,y
context.drawImage(image,x,y);

Working with Objects in Javascript

I am Currently Trying to work with JavaScript in a cleaner object orientated way, So Please excuse me if I'm doing this entirely incorrectly I am using this previous questions answer as a general reference, but Here's my 'test' code:
//Create some sample objects to play with.
var testJSON = {
"rectangle": [
{ "id":3 , "x":5, "y":10, "width":10, "height":50
}
]
};
//Create Rectangle Constructor
var rectangle = {
init: function( i, x, y, width, height ) {
this.id = i,
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.fields = []
},
move: function( x, y ) {
this.x += x;
this.y += y;
}
};
//Create test array to hold all the objects
var test = [];
//Create a new rectangle object
var myRectangle = Object.create( rectangle );
myRectangle.init( 1, 0, 0, 2, 4 );
myRectangle.move( 3, 5 );
//put rectangle object in array associated with id
test[myRectangle.id] = myRectangle;
//Create a new rectangle object with the same variable name as it will all be in an array anyway.
var myRectangle = Object.create( rectangle );
myRectangle.init( 2, 0, 0, 2, 4 );
myRectangle.move( 0, 0 );
//put rectangle object in array associated with id
test[myRectangle.id] = myRectangle;
//put JSON result in
test[testJSON.rectangle[0].id] = testJSON.rectangle[0];
//No Longer need this variable, is it worth getting rid of.. i dont know
myRectangle =null;
//Try and use methods created in the constructor.
test[2].move(4,8);
console.log(test);
Okay, Now the actual questions, The Application I am trying to create, has both json data and it will have users that create data, so for example: the application will generate a bunch of 'rectangles' and then the user can also create rectangles.
So the first question would be, 'Is this the correct approach' and then secondly how would i get the json data to also have the method defined in the rectangle constructor (move)?
Any Help Greatly Appreciated.
This an extension of what #Marc B and #Ray Toal mentioned...
You have created javascript functions - which is not at all that bad - but not JSON. To create graphics, you could use the canvas tag as, in effect, a "drawing div" and use the object's x and y positions to constantly update them - if you were considering doing 2d animation. If so, I would recommend CreateJs as a starting block before hard-coding JAVASCRIPT animations. Again, you're code is just fine, but having users create this data - if you were considering a server application would involve using real JSON or perhaps Node.js - but for now I'd focus on single player aspect and setting up you're objects on a graphical 'interface' like <canvas>

Categories