html canvas zindex - javascript

How do I change the zindex of an element inside a canvas?
Example code:
fabric.Image.fromURL('http://nocookie.net/bw.jpg', function(image) {
image.set('left', 200).set('top', 250);
canvas.add(image);
});
var helloWorld = new fabric.Text('Hello world!', {
left: 0,
top: 0,
fontfamily: 'delicious_500',
zindex: 10
});
canvas.add(helloWorld);
Using the fabric.js library.
For future reference:
fabric.Element.html#bringForward

I can't get the dang thing working at all, but here's my guess as to what's happening:
Fabric asks that URL for the image. Fabric has been given a callback method when the image is returned, so while it's waiting, it moves on to the next task
Fabric creates the Text object and adds it to the canvas.
Finally, it notices that the image has loaded (the specific example you provided actually 404'd on me), and passes it to the callback method.
Because the image is added to the canvas after the text, I'm assuming that Fabric is acting just as the canvas normally would: things that are added later are drawn on top of things that are already there. ...Even though you gave the text a z-index.
Remember, I couldn't get it to work and just gave up. So it's entirely possible I'm totally, completely wrong. If that is the case, I have another theory:
Are you sure that zindex is the correct property? If you are, then try setting it on the image, as well:
image.set('left', 200).set('top', 250).set('zindex', 5);
And if you aren't sure, then... there you go.

Since fabric.js version 1.1.4 a new method for zIndex manipulation is available:
canvas.moveTo(object, index);
object.moveTo(index);
i hope this is what you want:
http://jsfiddle.net/Kienz/RRv3g/

Related

TweenJS javascript

My first Stackoverflow question. The tween seems to run because it calls the brute function at the end. However, there's no tween happening.
window.onload=init();
function init() {
testImg = document.getElementById("testImg");
createjs.Tween.get(testImg).wait(2000).to({alpha: 1}, 600).call(brute);
}
function brute() {
// why this function get called if there's no visible tween?
console.log("testImg alpha is " + testImg.alpha)
testImg.style.opacity=1;
}
#testImg {
opacity: .3;
background: url("http://oyos.org/oyosbtn_466x621.jpg");
}
<script src="https://code.createjs.com/tweenjs-0.6.2.min.js"></script>
<body>
<div id="testImg">
here is the div
</div>
</body>
TweenJS isn't really optimized to tween styles on HTML elements, since it was developed to tween properties directly on objects. There is a CSS plugin that can help, particularly when dealing with properties that have suffixes (like "px" on width/height, etc)
However, it can definitely be done. There are a few issues with your code:
As you mentioned in your comment above, you have to target the "opacity" instead. The alpha property is what EaselJS DisplayObjects use.
You have to target the testImg.style instead, since the opacity lives on that element, and not on the testImg directly. Setting opacity/alpha on the #testImg will do nothing
Unfortunately, TweenJS doesn't know how to read CSS properties set on elements using CSS classes or selectors. The getComputedStyle is very expensive to look up, and is required to determine what the current style of the element is.
You can totally make your demo work, but you have to consider these things. Here is an updated snippet (from this pen):
createjs.Tween.get(testImg.style) // Target the style
.to({opacity:0.3}) // Set the property initially
.wait(2000)
.to({opacity: 1}, 600)
.call(brute); // Tween the opacity instead
You could also use the change event to update the opacity yourself:
createjs.Tween.get(testImg)
.set({alpha:0}) // Still requires an initial set
.wait(2000)
.to({alpha:1})
.call(brute)
.on("change", function(event) {
// Every time the tween is updated, set the opacity
testImg.style.opacity = testImg.alpha;
});
Note that the CSS plugin I mentioned above can handle the computedStyle lookup now (a fairly recent addition).
Hope that sheds some light on the behaviour.
Cheers,

Unable to set CSS background-image property with JavaScript

Edit:
For whatever reason, this does not work with JavaScript. It won't let you set the background image multiple times. To fix this, I set the backgroundPosition property to calc(50% + translation_x) calc(50% + translation_y) instead of setting a transformation in the image. This seems to work (for now).
I am unable to set the "background-image" property of an element dynamically with JavaScript. I have had no issues doing so in the past, but my current script does not work at all. There are no error messages in the console, so I haven't the slightest idea what's happening.
I have created vector graphics for a game and I am attempting to move them across the screen using a group (<g transform = "translate(x, y)">). My script takes the current background of the element, background.style.backgroundImage, and replaces the line containing the group with the transformed version.
Now, if I run
background.style.backgroundImage = "url(\"" + transformed_background + "\")";
console.log(background.style.backgroundImage);
the old version of the background image (without transformations) is (predictably) displayed in the output and the image does not update. For instance, the output might be
… <svg xmlns=\'http://www.w3.org/2000/svg\' width=\'5000\' height=\'5000\'><g> …
while the output of
console.log(transformed_background);
is correct, and is something to the effect of
… <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"5000\" height=\"5000\"><g transform="translate(1327.0717423133253, 1819.0229885057504)"> …
The background of the element will not change, despite my best efforts. I have tried everything imaginable in an attempt to resolve this issue. I believed it might be caused by the loop it is in (with an interval of about 50 ms), but increasing the interval had no effect. This system works elsewhere in the script (where the background is set initially), and this segment uses the same method.
The script is available here, and the issue is on line 175.
Any information would be much appreciated.
Thanks!
The only thing I see is at line 177,
where you use the var from line 175.
You wrote there
document.getElementById("background").backgroundImage = "url(\"" + build_background + ")";
But if I am not wrong you change the background with js like that.
document.getElementById("background").style.backgroundImage = "url(\"" + build_background + ")";
So you forgot the style.
Btw why do you write the js in the html window and not in the window for js?

Activate gif when cursor is over

I am building a Star Wars fansite.
My navigation menu will be star wars lightsabers.
I am planning to make (when the cursor is over the lightsaber) for the actual light sword to come out. When the cursor leaves the lightsaber, it goes back down.
I have a gif that does that, but how to make it unactive then active when cursor is hovered over??
If the idea above doesn't sound correct, how would you suggest I do it?
No, you can't control the animation of the images.
You would need two versions of each images, one that is animated (.gif), and one that's not(.gif/.png/.jpg/etc).
On hover you can easily change from one image to another.
Example:
$(function(){
$('img').each(function(e){
var src = $(e).attr('src');
$(e).hover(function(){
$(this).attr('src', src.replace('nonanimated.gif', 'animated.gif'));
}, function(){
$(this).attr('src', src);
});
});
});
Reference link
like Parag Meshram said, but no need to do it with jQuery or JavaScript:
.foo {
background: url(still.png) no-repeat 0 0;
}
.foo:hover {
background-image: url(animation.gif);
}
It might be a overkill, but I think you can control the GIF with WebGL.
Here is some GIF manipulation, it's not what you ask for, but maybe some inspiration for doing something own http://www.clicktorelease.com/code/gif/
Your best bet is to actually split the handle and the sword into two different graphics to then animate the sword in with Javascript (as background property). This way you wouldn't have the restrictions of the GIF file format but still a lot smaller files. You'll need to create a div the same size as the sword and set it as background, then set the background-position-x to -100% and animate it back in on hover, you can use jQuery for that:
$('.sword').on('hover', function(event){
$(this).animate({
'background-position-x': '0%',
}, 100, 'linear');
});
$('.sword').off('hover', function(event){
$(this).animate({
'background-position-x': '-100%',
}, 100, 'linear');
});
(I wrote this off the top of my head, check the jQuery docs if this doesn't work)
I had a similar situation and found a pretty simple solution. I'm pretty new to JQuery, so I'm not sure if this is in line with best practices, but it works.
I've used a static image (.png for transparency, in my case) and switched out the src attribute to point to the animated .gif on mouseenter and back to the .png on mouseleave. For your lightsaber to go from hilt alone to powering up I would do it a bit differently than usual. Try taking a frame from the .gif in Photoshop and making it into a static image using "save for web and devices". I recommend .png. In your HTML markup use this static image of the hilt for your src of the image, also be sure to give it an ID, such as saber for this example.
Now onto the jquery script. I link it in a separate file. For one saber it should look something like this:
$(document).ready(function()
{
$("#saber").mouseenter(
function()
{
$(this).attr("src", "img/stillframehilt.png");
},
function()
{
$(this).attr("src", "img/saberpowerup.gif");
});
$("#saber").mouseleave(
function()
{
$(this).attr("src", "img/saberpowerup.gif");
},
function()
{
$(this).attr("src", "img/stillframehilt.png");
});
});
Notice the on mouseleave I had it switch src to "img/saberpowerdown.gif". I think that rather than have the saber revert back instantaneously to the hilt in its dormant state (which any Star Wars geek[myself included] would wince at) it would look better to have a .gif that is essentially the reverse of the saber turning on. This can be achieved by reversing the order of the animation frames(ensure that visible layers are correct). For good measure I would make sure when to have it not loop either .gif's as well as add a few extra frames of the hilt alone when the power down is finished to ensure it remains off.
Also, it might be beneficial to add a .click to the saber to change the src to the power down, or even a different animation, but that is just extra flair. For each additional lightsaber use the same code, just changing the id to reference each in a logical way such as by color.
Again, I can't claim this to be in line with best practices as far as jquery goes (I'm but a padawan) but this method worked when I needed to activate a .gif on mouseenter and back on .mouseleave . May The Force be with you.

jQueryui animation with inital undefined height

See the following fiddle:
[edit: updated fiddle => http://jsfiddle.net/NYZf8/5/ ]
http://jsfiddle.net/NYZf8/1/ (view in different screen sizes, so that ideally the image fits inside the %-width layouted div)
The image should start the animation from the position where it correctly appears after the animation is done.
I don't understand why the first call to setMargin() sets a negative margin even though the logged height for container div and img are the very same ones, that after the jqueryui show() call set the image where I would want it (from the start on). My guess is that somehow the image height is 0/undefined after all, even though it logs fine :?
js:
console.log('img: ' + $('img').height());
console.log('div: ' + $('div').height());
$('img').show('blind', 1500, setMargin);
function setMargin() {
var marginTop =
( $('img').closest('div').height() - $('img').height() ) / 2;
console.log('marginTop: ' + marginTop);
$('img').css('marginTop', marginTop + 'px');
}
setMargin();
Interesting problem...after playing around with your code for a while (latest update), I saw that the blind animation was not actually firing in my browser (I'm testing on Chrome, and maybe it was firing but I wasn't seeing it as the image was never hidden in the first place), so I tried moving it inside the binded load function:
$('img').bind('load', function() {
...
$(this).show('blind', 500);
});
Now that it was animating, it seemed to 'snap' or 'jump' after the animation was complete, and also seemed to appear with an incorrect margin. This smacks of jQuery not being able to correctly calculate the dimensions of something that hadn't been displayed on the screen yet. On top of that, blind seems to need more explicit dimensions to operate correctly. So therein lies the problem: how to calculate elements' rendered dimensions before they've actually appeared on the screen?
One way to do this is to fade in the element whose dimensions you're trying to calculate very slightly - not enough to see yet - do some calculations, then hide it again and prep it for the appearance animation. You can achieve this with jQuery using the fadeTo function:
$('img').bind('load', function() {
$(this).fadeTo(0, 0.01, function() {
// do calculations...
}
}
You would need to work out dimensions, apply them with the css() function, blind the image in and then reset the image styles back to their original states, all thanks to a blind animation that needs these dimensions explicitly. I would also recommend using classes in the css to help you manage things a little better. Here's a detailed working example: jsfiddle working example
Not the most elegant way of doing things, but it's a start. There are a lot more easier ways to achieve seemingly better results, and I guess I just want to know why you're looking to do image blinds and explicit alignment this way? It's just a lot more challenging achieving it with the code you used...anyways, hope this helps! :)

jQuery animate problems

I use the following snippet to make an element's background lightblue, then slowly fade to whiite over 30 seconds:
$("#" + post.Id).css("background-color", "lightblue")
.animate({ backgroundColor: "white" }, 30000);
Two questions.
First, instead of fading to white, is there a way to fade opacity to 100%? That way I don't have to change "white" if I choose to change the page's background color?
Second, about once out of every 10 or 15 times, the background stays lightblue and fails to fade to white. I'm using the latest versions of jQuery and the UI core. What could be going wrong?
EDIT: Bounty is for a solution to problem regarding second question.
EDIT2:
Apparently I got downvoted into oblivion because I said I rolled my own solution but didn't show it. My bad. I didn't want to be self-promoting. My code works 100% of the time and doesn't require jQuery. A demonstration and the code can be found at:
http://prettycode.org/2009/07/30/fade-background-color-in-javascript/
For your second question: in my experience this is usually because a Javascript error has occurred somewhere else on the page. Once there is one Javascript exception, the rest of the page stops running Javascript. Try installing Firebug (if you haven't already), then open up the "Console" tab and enable it. Then any javascript errors or exceptions will be printed to the console.
Another thing to try (which kinda contradicts my last statement...) is to disable all your browser plug-ins to see if you can recreate. Sometimes they interfere with scripts on the page (particularly GreaseMonkey.)
If you could provide a sample HTML snippet which reproduces this animation problem it would be a lot easier for us to help you. In the script I have pasted below, I can click it all day, as fast or slow as I like, and it never fails to animate for me.
For the first question: I know you said you'd found a workaround, but the following works for me (even on IE6) so I thought I'd post it, since it may be different from what you were thinking. (Note that setting CSS "opacity" property through jQuery.css() works on IE, whereas IE does not support the "opacity" property directly in CSS.)
<html>
<head>
<style>
body { background-color: #08f; }
#test { background-color: white; width: 100px; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
var myOpacity = 0.125;
$(function(){
$('#test').css('opacity', myOpacity);
$('a').click(function(){
myOpacity = 1.0 - myOpacity;
$('#test').animate({ opacity: myOpacity });
return false;
});
});
</script>
</head>
<body>
<p>Click me</p>
<div id="test">Test</div>
</body></html>
Dont forget the color plugin.
See here
When the color fails to animate to blue you could try to use the callback function to log a message to the console. You can then check that the event actually fired and completed. If it does then you could potentially use two animates. The first one to animate to a halfway house color then the use the callback to animate to white (so you get two bites of the cherry, if the outer fails but completes the callback has a second go)
It would be good if you could try to recreate the issue or give a url of the issue itself.
e.g
$("#" + post.Id).css("background-color", "lightblue")
.animate({ backgroundColor: "#C0D9D9" }, 15000, function(){
$(this).animate({ backgroundColor: "#ffffff" }, 15000)
});
You could always use something like this, avoiding the JQuery animate method entirely.
setTimeout(function() { UpdateBackgroundColor(); }, 10);
UpdateBackgroundColor() {
// Get the element.
// Check it's current background color.
// Move it one step closer to desired goal.
if (!done) {
setTimeout(UpdateBackgroundColor, 10);
}
}
Also, you may be able to remove the "white" coding by reading the background color from the appropriate item (which may involve walking up the tree).
It is possible to have jQuery change the Opacity CSS property of an item (as mentioned in another answer), but there's two reasons why that wouldn't work for your scenario. Firstly, making something "100% opaque" is fully visible. If the item didn't have any other modifications to its opacity, the default opacity is 100%, and there would be no change, so I'm guessing you meant fading to 0% opacity, which would be disappearing. This would get rid of the light blue background, but also the text on top of it, which I don't think was your intent.
A potentially easy fix for your situation is to change the color word "white" to "transparent" in your original code listing. The color plugin may not recognize that color word (haven't checked documentation on that yet), but setting the background color to "transparent" will let whatever color behind it (page background, if nothing else) shine through, and will self-update if you change your page background.
I'll answer your first question.
You can animate opacity like this:
.animate({opacity: 1.0}, 3000)
I think you can try using fadeOut/fadeIn too..
What about:
$("#" + post.Id).fadeIn( "slow" );
You could possibly have two divs that occupy the same space (using position: absolute; and position: relative; setting the z-index on one higher to make sure one is above and the other is below. the top one would have a transparent background and the one below would have a background color. then just fadeout the one below.
As for the second question:
If you think the default animation classes from JQuery are not properly working you could try Bernie's Better Animation Class. I have some good experiences with that library.
Animate only works for numbers. See the jquery docs. You can do opacity but you can't do background color. You can use the color plug in. Background-color uses strings like 'red', 'blue', '#493054' etc... which are not numbers.

Categories