New style is not applied to element on event - javascript

I generate some squares dynamically using rahaeljs. These squares have an event handler. When I try to manipulate the style, it fails depending on the attr() I try to set:
function changeColor(obj) {
return function() {
obj.attr({cursor : 'pointer'});
}
}
var main = function () {
var width = 901;
var height = 868;
var space = 50;
var paper = Raphael('paper', width, height);
for (var y = 0; y < height; y += space) {
for (var x = 0; x < width; x += space) {
var r = paper.rect(x, y, space, space);
r.attr({fill : 'transparent'})
r.click(changeColor(r));
}
}
};
window.onload = main;
If I set the cursor to {cursor : 'pointer'}, this works fine, if I try to change the fill color with obj.attr({fill : '#ff00ff'}); in the changeColor-function, nothing happens. There is also no Error in the console.
I'm using the latest version of raphael.
Any suggestions?
Regards,
michael

You'll be either very amused or very frustrated by this answer... the problem has to do with the transparent fill attribute. SVG treats fully transparent objects as unclickable, letting click events filter down to the layer(s) beneath them. Therefore, your rectangles are not receiving click events.
If you can't set the color to a solid color, you can at least give the fill attribute a tiny, almost unnoticeable amount of alpha:
r.attr({ fill: 'rgba(255,255,255,0.001)' } );
That done, you should be back in business!

Related

How to specify color properties (fill and stroke) of a path in JS

So I'm trying to optimize some designs in my process, for this task I'm experimenting with javascripts for Illustrator and Photoshop, the issue i have right now is that for drawing, filling and changing the stroke color of my paths. So how I can an array of colors in JS for Illustrator to fill a path of one color and the stroke of another color?
Right know it just take my last declared CMYK color and ignores previous ones.
Code:
var RectangleColor = new CMYKColor();
RectangleColor.black = 0;
RectangleColor.cyan = 0;
RectangleColor.magenta = 0;
RectangleColor.yellow = 0;
var RectangleColorStroke = new CMYKColor();
RectangleColor.black = 0;
RectangleColor.cyan = 80;
RectangleColor.magenta = 80;
RectangleColor.yellow = 0;
and in the drawing method
rect.filled = true;
rect.fillColor = RectangleColor;
rect.strokeColor = RectangleColorStroke;
Note: I don't really know if exist a property named strokeColor, but since it didn't show any error then was decided to use it.
Well i know is not the most clean way but already found how.
declared this variable
var col = new GrayColor();
col.gray = 100;
have this at the code
var rect = artLayer.pathItems.rectangle (monthsCubeY,monthsCubeX,180,100); //draw rectangle at the selected coordenates
monthsCubeX = monthsCubeX + 190; //move the coordenates for the next rectangle
rect.filled = true;
rect.stroked = true;
strokeWidth = 1;
rect.fillColor = RectangleColor;
strokeColor = col;
I dont know much of coding, but this seems to work for me.

Given an input to draw a rectangle canvas with selected background

I want to make real time rendered rectange which is filled by texture of material you choose. I want to use HTML5 <canvas> and jQuery. In this fiddle http://jsfiddle.net/1fhhtev7/ is how it should looks like. when you add "a" and "b" side it will generate proportional rectangle and when you click on material it will fill the canvas by texture of material.
Here is how the preview should looks like in final:
Can you help me with this?
You should capture the values of the input elements and then set width and height properties accordingly.
$('input[name=sideA],input[name=sideB]').on('input',yourFunction())
Then you should make a function with a loop where you draw the image.
var imgPosX = 0;
var imgPosY = 0;
var img = document.getElementById(YOURIMAGEID);
while(imgPosX < canvas.width){
ctx.drawImage(img,imgPosX,imgPosY);
if(imgPosX === canvas.width){
imgPosY += 50;
imgPosX += 0;
}
if(imgPosY === canvas.height){
break;
}
imgPosX +=50;
}
you call this function in your eventlistener.
Try this,
function draw(){
$('img').click(function(){
var $img = $(this).outerHTML;
ctx.clearRect(0,0,canvas.width,canvas.height);
var pat = ctx.createPattern(this, 'repeat');
ctx.rect(40,40,width,height);
ctx.fillStyle = pat;
ctx.fill();
});
}
Working Demo
Canvas draw only to change number not keyup function

Keeping a portion of an image always visible on the canvas

I want to make sure that my instance of fabric.Image is always visible.
It doesn't need to be 100% visible, but a portion of it should always be seen. I've seen a few other questions that are similar and I've based my solution on them, but I haven't found anything that completely solves the problem.
My current solution works when no rotation (angles) have been applied to the image. If the angle is at 0 then this solution is perfect, but once the angle start changing I'm having problems.
this.canvas.on('object:moving', function (e) {
var obj = e.target;
obj.setCoords();
var boundingRect = obj.getBoundingRect();
var max_pad_left_over_width = 50;//obj.currentWidth * .08;
var max_pad_left_over_height = 50;//obj.currentHeight * .08;
var max_top_pos = -(obj.currentHeight - max_pad_left_over_height);
var max_bottom_pos = obj.canvas.height - max_pad_left_over_height;
var max_left_pos = -(obj.currentWidth - max_pad_left_over_width);
var max_right_pos = obj.canvas.width - max_pad_left_over_width;
if(boundingRect.top < max_top_pos) {
obj.setTop(max_top_pos);
}
if(boundingRect.left < max_left_pos){
obj.setLeft(max_left_pos);
}
if(boundingRect.top > max_bottom_pos) {
obj.setTop(max_bottom_pos);
}
if(boundingRect.left > max_right_pos) {
obj.setLeft(max_right_pos);
}
});
I've created an example: https://jsfiddle.net/krio/wg0aL8ef/24/
Notice how when no rotation (angle) is applied you cannot force the image to leave the visible canvas. Now, add some rotation to the image and move it around. How can I get the rotated image to also always stay within view? Thanks.
Fabric.js provides with two object properties isContainedWithinRect and intersectsWithRect which we can use to solve the problem.
An object should not be allowed to go outside the canvas boundaries. This can be achieved if we somehow manage to make sure that the object is either inside the canvas, or at least intersects with the canvas boundaries.
For this case, since you want some portion of the image inside the canvas, we will take a rect smaller than the canvas instead of canvas boundaries to be the containing rect of the image.
Using the properties mentioned to make sure that the above two conditions are satisfied after any movement. Here's how the code looks like:
var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-img');
var imgInstance = new fabric.Image(imgElement, {
top: 0,
left: 0
});
imgInstance.setScaleX(0.6);
imgInstance.setScaleY(0.6);
canvas.add(imgInstance);
var prevLeft = 0,
prevTop = 0;
var max_pad_left_over_width = imgInstance.currentWidth * .08;
var max_pad_left_over_height = imgInstance.currentHeight * .08;
var max_top_pos = max_pad_left_over_height;
var max_bottom_pos = imgInstance.canvas.height - max_pad_left_over_height;
var max_left_pos = max_pad_left_over_width;
var max_right_pos = imgInstance.canvas.width - max_pad_left_over_width;
var pointTL = new fabric.Point(max_left_pos, max_top_pos);
var pointBR = new fabric.Point(max_right_pos, max_bottom_pos);
canvas.on('object:moving', function(e) {
var obj = e.target;
obj.setCoords();
if (!obj.intersectsWithRect(pointTL, pointBR) && !obj.isContainedWithinRect(pointTL, pointBR)) {
obj.setTop(prevTop);
obj.setLeft(prevLeft);
}
prevLeft = obj.left;
prevTop = obj.top;
});
Here's the link to the fiddle: https://jsfiddle.net/1ghvjxbk/ and documentation where these properties are mentioned.

Pixel manipulation and canvas

Is there a way in javascript to change the alpha channels of each pixel into being fully transparent (a=0) while coding for pixel manipulation (meaning that you can still change the transparency in some of the alpha channels as desired)?
Basically, what I'm doing is: given some data for a specific image, I manipulate the pixel array using an algorithm so that some pixels become fully transparent unless they satisfy some certain condition. In the case of them satisfying the condition I want them to be fully opaque, aka alpha=1. However, because of a complication with the way the algorithm works, I need to have my data "reset"; meaning I want the pixel array to start off as having every alpha = 0. I can provide code if that helps in better understanding the scope of my question.
Thanks so much.
EDIT: I'm looking more for a method/one-line code. Would context.globalAlpha = 0 serve the purposes? Is there any pitfall I should be careful about?
EDIT2: This is my code. Does globalAlpha where I've put it do what I'm expecting it to do? I'm not sure how to use it...
function getBoundary(imagedata){
var imageData = new Array(imagedata.data.length);
imageData = imagedata.data;
var w = imagedata.width;
var h = imagedata.height;
var color1 = [];
var colorRight = [];
var colorDown = [];
context.globalAlpha = 0;
for (var i = 0; i < 4*w*h; i +=4) {
color1 = [imageData[i],imageData[i+1],imageData[i+2]];
colorRight = [imageData[i+4],imageData[i+5],imageData[i+6]];
colorDown = [imageData[4*w+i],imageData[4*w+i+1],imageData[4*w+i+2]];
if(colorRight = [255,255,255]){ //if right is white
if(color1 = [0,0,0]){
imageData[i+3] = 255;
}
else{
if(colorDown = [0,0,0]){
imageData[4*w+i+3] = 255;
}
}
}
else{ //colorRight = black
if(color1 = [0,0,0]){
if(colorDown = [255,255,255]){
imageData[i+3] = 255;
}
}
else if(color1 = [255,255,255]){
imageData[i+7] = 255;
if(colorDown = [0,0,0]){
imageData[4*w+i+3] = 255;
}
else{
}
}
}
}
console.log("done");
imagedata.data = imageData;
return imagedata;
}
You can use getImageData and flip all the alpha elements to zero:
You can create a function that zeros the alpha of all pixels on the canvas like this:
function zeroAllAlpha(){
var imageData=context.getImageData(0,0,canvas.width,canvas.height);
var data=imageData.data;
// set all alpha elements to zero (fully transparent);
for(var i=3;i<data.length;i+=4){
data[i]=0;
}
context.putImageData(imagedata,0,0);
}
And you can call the function with one line like this:
zeroAllAlpha();

Changing canvas drawn image on mouseover

I'm really struggling with the changing of my canvas drawn image so I thought I would see if anyone could assist me on here or offer advice.
I've drawn a static flag in canvas, and I've also drawn a waving flag. I'm trying to get this flag to wave on mouseover.
I initially thought that I was going to have to create two separate files, one for the static and one for the waving aspect. Then save each of them as a jpg/gif image using window.location = canvas.toDataURL("image/");.
But I've just discovered that you can apparently do this all in the same file via jquery/hover. Which seems a lot simpler and a more efficient way of doing it.
Here is the code for the waving flag:
window.onload = function(){
var flag = document.getElementById('banglaFlag');
banglaStatic( flag, 320 );
var timer = banglaWave( flag, 30, 15, 200, 200 );
};
function banglaStatic( canvas, width ){
//Drawing the Bangladesh flag.
//Declaring variables that regard width and height of the canvas.
//Variables C to L are needed for the waving function.
var a = width / 1.9;
var b = 200;
var c = 7*a/13;
var l = a / 13;
canvas.width = b;
canvas.height = a;
var ctx = canvas.getContext('2d');
var radius = 45;
};
function banglaWave( canvas, wavelength, amplitude, period, shading ){
var fps = 30;
var ctx = canvas.getContext('2d');
var w = canvas.width, h = canvas.height;
var od = ctx.getImageData(0,0,w,h).data;
// var ct = 0, st=new Date;
return setInterval(function(){
var id = ctx.getImageData(0,0,w,h);
var d = id.data;
var now = (new Date)/period;
for (var y=0;y<h;++y){
var lastO=0,shade=0;
for (var x=0;x<w;++x){
var px = (y*w + x)*4;
var o = Math.sin(x/wavelength-now)*amplitude*x/w;
var opx = ((y+o<<0)*w + x)*4;
shade = (o-lastO)*shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData(id,0,0);
// if ((++ct)%100 == 0) console.log( 1000 * ct / (new Date - st));
},1000/fps);
}
Thanks in advance for any advice/assistance.
I am not sure where your problem is. I did not see any event handling code, so I assume that's your question:
Define a function to "handle the mouse event". For example, if you want to move the flag when the user moves the mouse over it, define something like:
function mouseMove(event) {
var mouseX,
mouseY;
event.preventDefault(); // stops browser to do what it normally does
// determine where mouse is
mouseX = event.pageX;
mouseY = event.pageY;
// do something useful, e.g. change the flag to waving when mouse is over flag
}
Then, register this function to be called when the mouse moves:
canvas.addEventListener("mousemove", mouseMove, false);
canvas is the canvas you paint the flag on, "mousemove" is the name of the event (many more exist, such as "mousedown", "mouseup", "mouseout" (leaving canvas), "mousewheel", etc.), mouseMove is the name of your function (the event handler, as it's called).
Events are a little different from browser to browser (and even browser version), so you might need to implement different event handler if you need it across browsers.
Hoping this helped...
canvas is like a sheet. there is no any object on which you can hover.
for doing what you wanted to do is just,bound an area on the flag,
follow the 'virtualnobi' answer and calculate if mouse co-ordinate falls on that region,
if true do what ever you want.
like
if (mouseX<100 && mouseX>0 && mouseY>0 && mouseY<100){
//animate the flag
}
use mouseX=event.clientX;
mouseY=event.clientY;
bounded area is x=(0,100) , y=(0,100) here.

Categories