Change of an attribute src seems to interupt other functions, even those not connected to the img. They don't work properly although when the line of code changing the attribute isn't called everything works perfectly fine.
I have my scripts.js that handles navigation - whenever you click header it should fade in content, change it and fade it back onto the screen.
The html of content that is to be changed:
<div id="photoContainer">
<div id="photoSection">
<img id="showedPhoto" src="img/photo1.png" />
</div>
</div>
Stylesheet:
#photoContainer
{
position: absolute;
top: 18%;
z-index: -1;
}
#photoSection
{
transition: all 0.4s ease-in-out;
}
And the most important, script:
/*
* 1. Hides photo after 0.2s of pressing button
* 2. Changes photo to another one
* 3. Shows photo
*/
function SwipePhoto(newSectionNo)
{
if(newSectionNo != currentSectionNo)
{
currentSectionNo = newSectionNo;
setTimeout(HidePhoto, 200);
setTimeout(HideContent, 200);
setTimeout(function() { changeContent(newSectionNo) }, 600);
setTimeout(ShowPhoto, 1000);
setTimeout(ShowContent, 1000);
}
}
HidePhoto, HideContent, ShowPhoto & ShowContent are just basic fadeIn/Out functions but the keypoint is the changeContent:
function changeContent(photoNo)
{
document.getElementById("showedPhoto").src = "img/photo" + photoNo + ".png";//THIS ONE
//showedPhoto.attr("src", "img/photo" + photoNo + ".png"); SAME SITUATION OCCUR WHILE USING JQUERY
content.html(text[photoNo - 1]);
sectionHeader.html(header[photoNo - 1]);
}
Without the line of code: document.getElementById("showedPhoto").src = "img/photo" + photoNo + ".png"; everything works as it should - smooth & clean (except the photo always stays the same which is not good).
But when the attribute src of img is changed all functions that should slowly fadeOut content don't seem to be working. The picture shows without any fade out effect. What is interesting, not only the image is affected as other sections also stop working, they just appear (although they worked fine before adding the line).
I fell like this is a bit more complex so if anyone could help I would be soooo grateful.
If I should add anything to help you understand the code please let me know.
Solved it!
If anyone experiences the same problem try to lower the resolution of photos, in my case they were too big to enable the website work flowlessly.
Related
I have the following to get JSON after clicking a submit button, where temperature is the div wrapper for the other listed elements:
$.getJSON("lookup.php?id=" + v, function(data) {
var items = {};
$.each(data, function(key, val) {
items[key] = parseFloat(val.replace(/\$|,/g, '')).toFixed(2);
});
console.log(items);
if (items["goal"] != null) {
$('#progress').on('webkitTransitionEnd transitionend', function(e) {
console.log(e);
});
$("#goal").text("Goal: " + "$" + items["goal"]);
$("#temperature").css("display", "block");
$("#progress").css("width", items["total"] / items["goal"] * 100 + "%");
$("#pct").text(items["total"] / items["goal"] * 100 + "%");
$("#raised").text("$" + items["total"]);
}
});
This code is inside a jQuery getJSON function. And the temperature should animate like a fundraiser temperature bar.
Here's what I have for that element's CSS:
#progress {
float: left;
transition: width 6s;
width: 0%;
height: 20px;
background: #FF5D50;
z-index: 333;
}
I've been getting inconsistent results with the transitions (I am aware that I should be adding the other browser CSS transitions as well). I'm using Chrome. Sometimes it loads and the transition happens, and sometimes it just loads directly to the percent it's supposed to be at. It should be animating every time, and without making changes to the code, I get different results like it's a race condition, and so it's very difficult to reproduce consistently. However, I read from other answers here on SO that DOM manipulation is synchronous. So I can't understand why sometimes it works and doesn't.
I would appreciate any explanation to what's happening here. Maybe what's checking to see if there needs to be a transition applied is being triggered sometimes before the display attribute changes and this is why it will sometimes not transition? I don't know what exactly checks if a DOM element is changed and applies the CSS transition.
Update: It works even with a 0ms setTimeout that encapsulates the progress bar update after changing the wrapper to display as block - can't reproduce on fiddle since it looks like it runs slower there.
I've spent most of my morning trying to resolve how to create a scrolling marquee on an Angular app; my goal is when the dynamic text is longer than its viewport, it will scroll (repeating, meaning you don't have to wait for the entire title to scroll off the page before you see it again) but when it's short enough to display without being cut off in the viewport width, it does not scroll.
I like examples I'm seeing but need to combine them somehow and I am very beginner when it comes to adding any kind of javascript.
One is using jQuery and marquee:
$('.marquee').marquee({
duplicated: true
});
This one is great because it repeats the text and continues without it having to completely leave the screen to start again. But, my trouble comes when trying to figure out a way to add in javascript to figure out how wide that text will be; either to have it be static or scroll.
For some reason, I am unable to understand how to link to codepen or jsfiddle of the examples I've found that hit close to home. Hoping my inquiry above is enough information. I know commenters can be a bit rough—please be patient with me.
You could use text-shadow(to clone text) and animation if it is only about text.
JS will be necessary to get the width(from text lenght) of the piece to scroll and to update/insert css rule's values.
example inspired from your jsfiddle
function isElementOverflowing(element) {
var overflowX = element.offsetWidth < element.scrollWidth,
overflowY = element.offsetHeight < element.scrollHeight;
return (overflowX || overflowY);
}
// below css updated and injected . can be shorten and nicely rewritten
var element = document.getElementById('ov1');
if (isElementOverflowing(element)) {
var toscroll = element.scrollWidth;
element.style.textShadow = toscroll + 'px 0 ';
element.style.animation = 'marqueeme 5s infinite linear';
var csstyle = document.createElement('style');
csstyle.innerText = '#keyframes marqueeme {100%{ text-indent:-' + toscroll + 'px;}}';
element.appendChild(csstyle)
}
#marquee {
max-width: 15em;
overflow: hidden;
}
#ov1 {
white-space: nowrap;
margin: 0;
}
<div id="marquee">
<p id="ov1">
Yadda yadda overflowing text this line is too long oh noes!
</p>
</div>
example here is using text-indent within the animation, but negative margin-left or translateX will do the same visual.
Another example with
a text-shadow of different color
transform to see it working instead text-indent.
It also sets speed according to text length
# https://codepen.io/gc-nomade/pen/owPNZg
Im a total noob and need some help on a function which I would think for most of you would be quite simple. I am trying to do this with pure Javascript and not JQuery. I have been trying for hours and I cant get it.
What I am trying to achieve is to have a function repeat every time I click on a link.
To be more specific I currently have text that fades in when clicking a link and I would like it to always perform the fade in when I click on it (as if you were to refresh the page).
Basically: Click link (x) -- Text Fades in -- click link (x) -- same text disappears and then fades in from beginning of transition/animation (no fade out) -- repeat
I have come across something very similar on W3 schools which shows a function starting from the beginning every time you click the button: https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_setinterval_progressbar
I thought that modifying this was the answer but because I am trying to change the opacity, I have seen that I have to add a parseFloat to the function because it is a string but I am having no success. The example is:
else { i.style.opacity = parseFloat(i.style.opacity) + .1; }
To throw another spanner in the works, I am using the opacity value from the color:rgba(0,0,0,0) to change the opacity. I thought this may be easier to find since the above example would (in my mind) bypass the parseFloat thing as you would be using i.style.color but I could not find anything.
Below is my code based on a variation of the W3 schools tutorial. I'm pretty sure that clearInterval in JS has a big part to play in what I need. Very much appreciate any help for this and please let me know if you need more clarity :)
<!DOCTYPE html>
<html>
<style>
#about {
color: rgba(10,10,10,0);
transition: color 1s linear 1s;
}
#about:target {
color: rgba(10,10,10,1);
transition: color 1s linear 1s;
}
</style>
<body>
About
<div id="div">
<p id='about'> Please help me figure this out. I really appreciate it</p>
</div>
</body>
<script>
function fadeIn() {
var elem = document.getElementById("about");
var begin = 0;
var id = setInterval(frame, 10);
function frame() {
if (begin == 100) {
clearInterval(id);
} else {
begin++;
elem.style.color = begin + '1';
}
}
}
</script>
</html>
There is a solution, which I am not going to present you, because the JS "hack" will take longer, compared to the CSS-trick: (looking for appropriate reference)
You wrap your stuff, which you want to fade in and out into a container (just making sure) and add a checkbox above it:
<label for="about">About</label>
<intput type="checkbox" name="about" id="about">
<div id="about_container"> bla-bla-bla</div>
then you style your stuff:
Hide the checkbox (the label is clickable)
make two configs for your #about_container
first: in the off mode, second in the on mode (you can comment them out for debugging purpose)
#about + #about_container
then you add the input id with pseudo-selector before the second:
#about:checked + #about_container
on your on mode, and leave the other one, like it is.
MUCH BETTER AND FASTER SOLUTION!
You should also change your question into something like:
How do I make html element appear and disappear on mouse-click or other user-interaction.
You can use transitions and then set opacity 0.5 and after some ms change it in 1 to let it fade on click and return in the older look
Edit:
Just put fadeIn() inside another function, and before the fadeIn() executon set the opacity to 0
Edit:
JS
doIt = function() {
document.getElementById("about").style.color = begin + '0';
fadeIn();
}
HTML
About
I'm applying a repeated background image from a canvas to a div via javascript like this:
var img_canvas = document.createElement('canvas');
img_canvas.width = 16;
img_canvas.height = 16;
img_canvas.getContext('2d').drawImage(canvas, 0, 0, 16, 16);
var img = img_canvas.toDataURL("image/png");
document.querySelector('#div').style.backgroundImage = 'url(' + img + ')';
I have to update it quite frequently. The problem is it flickers upon change, it doesn't appear to happen in Chrome but it's really bad in Firefox and Safari. Is it possible to stop this? I didn't think it would happen since it's a dataurl and therefore doesn't need to be downloaded.
Solution:
// create a new Image object
var img_tag = new Image();
// when preload is complete, apply the image to the div
img_tag.onload = function() {
document.querySelector('#div').style.backgroundImage = 'url(' + img + ')';
}
// setting 'src' actually starts the preload
img_tag.src = img;
Try to preload the image resource to the device storage by including the image in DOM like in the following HTML-Code. Maybe the error comes up because the image resource need to be loaded which takes some time (flickering).
<img src="imageToPreload.png" style="display:none;" alt="" />
You may prefer to use sprites-images. By using sprites your application will need less HTTP-Requests to load all ressources into your page. Also add the following CSS styles if you are using css animations. It will prevent background flickering on mobile devices:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
Preload your image like this, no need to include a <img> with display: none
<link rel="preload" href="/images/bg-min.png" as="image">
Try adding this css to your background element:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
It should help with flickering..
You can also "force" hardware acceleration by adding this to your background element:
-webkit-transform: translate3d(0, 0, 0);
Another option is to use image instead of DIV and change only the image url.
I struggled with this for a bit, tried preloading, appending the image to the document, etc.
In the end, I resaved the JPEG without the "Progressive" option.
That fixed the rolling flicker when the img src was swapped.
In my case changing height: 1080px; (background height) to height: fit-content;
I think that preloading all the images is essential in any case. What I found is that the way the browsers behave while changing the background image dynamically is different from one another. In Firefox for example it flickers when the change is frequent however in Chrome and Safari it doesn't.
The best solution I came up with so far is drawing the image inside a child canvas that fills the space of the whole parent div.
In all cases, the images you are using must be optimized as it affects the rendering performance.
My javascript code that works now, looks like this
const pic = new Image();
const pic2 = new Image();
pic.src="../images/settings_referrals_anim.gif";
pic2.src="../images/settings_referrals_still.png";
I don't actually reference that code in the query, for example, i use
document.querySelector(".button_Settings_referrals").addEventListener("mouseover", function() {
myDiv.style.backgroundImage = "url('../images/settings_referrals_anim.gif')";
But it seems to work. If I replace the long URL with const pic for example it doesn't work, and if I include the image object declaration and location at first time in the assignment, then the flickering stops.
This does not address all of the specifics noted by the OP, but might be useful for others. Tested in Chrome 97, Firefox 96, Android 11, iOS 15.
I have a div that includes these CSS parameters...
#div_image {
background-image: url( [Path to low-res image] );
background-size: cover;
}
I have a corresponding class that looks like this...
.div_image_highres {
background-image: none !important;
}
The corresponding class has a pseudo-element defined as follows:
.div_image_highres::before {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
content: " ";
background-image: url( [Path to highres image] );
background-repeat: no-repeat;
background-position: 50% 0;
background-size: cover;
opacity: 1;
display: block;
}
I have an img element that also points to the high-res image...
<img id="img_highres_preload" src=" [Path to high-res image ] ">
The img element has a corresponding style which allows the image to be displayed (ensuring that image file loads) but not seen...
#img_highres_preload {
width: 1px;
height: 1px;
}
Two notes: (1) I realize a lot of people use other methods of pre-loading (e.g., programmatically), but I have a personal preference for this method. (2) See the addendum about the reliability of the load event.
Last but not least, I have some Javascript (jQuery) that adds the "high-res" class to "div_image" once the high-res file is loaded...
$(document).ready(function() {
$("#img_highres_preload").off().on("load", function() {
$("#div_image").addClass("div_image_highres");
});
});
This could easily be vanilla JS, but since I use jQuery throughout my code, I like having a consistency.
Here's a summary of what's happening...
Presumably, the low-res image is loaded first and becomes the background image for the div. Even if that does not occur, everything will work as intended (i.e., the high-res image will be displayed).
When the high-res image loads into the img element (i.e., Javascript confirms that the high-res file is loaded), the "div_image_highres" class is applied to "div_image".
As result, the div switches to the high-res image without flashing. In my experience, if anything, it shifts a little to the left; but that often doesn't occur and, if it does, it's not inelegant.
And here's the primary reason I use this approach when required: In my application, there are multiple panels the user can navigate, which results in one panel sliding out of view and the new one into view. If I don't use a pseudo-element (as described above) for displaying a high-res image, the image flickers when its div is hidden and re-displayed. With the above-described technique, I can slide the div in and out of view without any flickering.
Regarding the Load Event
You can't depend on the load event firing. For instance, it typically does not fire when the browser has cached an image. So to make a long post even longer, here's the enhancement I have in my code to accommodate that reality...
I modify the document.ready event (shown above) to look like this:
$(document).ready(function() {
positionOnPage(true);
$("#img_highres_preload").off().on("load", function() {
checkImage();
});
});
checkImage = function() {
var image = $("#img_highres_preload")[0];
if (!image.complete || (typeof image.naturalWidth != "undefined" && image.naturalWidth == 0)) {
console.log("Waiting for high-res image.");
}
else if (!$("#div_home").hasClass("div_home_highres")) {
$("#div_home").addClass("div_home_highres");
$("#img_highres_preload").remove();
}
}
The checkImage function examines the image element to see whether an image has in fact been loaded. In this code example, it is a little redundant — that is, the img element has confirmed the load, so there's usually no need to check it (unless there is some reason to believe the file is being misloaded).
I might do it as shown because I also call checkImage from other places in my code, so if I have more of a programmatic response (unlike the simple version shown), I want all of that code in the same place and written just once. The checkImage function might be called when triggered by a timer or when the section displaying the intended image is about to be displayed. Perhaps something like this...
if (sectionName == "[whatever]" && $("#img_highres_preload").length === 1) {
checkImage();
}
In this example, I look for the presence of the preload img element because I know that my previous function removes the element after it has fulfilled its purpose.
This post has a stripped-down version to illustrate the concept. As written above, it only accommodates a single known img element, so the code could be extended to call checkImage with some parameters (e.g., the name of an image or the element itself) and checkImage could look for the existence of the preload element, so that check occurs in one place. It can be fairly fancy, so I went with the simplest example for this post.
In many cases, this stripped-down version is all I need because typically I only use a high-res photo for a window background image. I either start with the display of a low-res image and switch it out as soon as the high-res file is loaded, or I have some animation that gets triggered after I confirm the presence of the high-res image.
A good case for a more generalized version is when I need a series of images loaded at the outset and don't want to start until all of them are ready. In those cases, the web page might begin with some welcome text that stays displayed until all images have been confirmed.
Hey Guys I know this has been an older question but if you are still flickering after all this you can simply put the final version behind you background div. That flicker is seeing behind the image you currently have so if its the final image it will be smooth.
I have a script which generates a random number so that when setImg(); is called a randomly selected image appears:
<img src="" id="imgRand" alt="">
function setImg(){
var numRand = Math.floor(Math.random()*(6 - 1 + 1)) + 1;
document.getElementById("imgRand").src = "images/"+numRand+".jpg";
}
This all works fine, but when the image changes, it just 'appears'. I was wondering if there was any way to get it to fade from one to the other? Everything I've found online talks about setting styles on each individual image, but as Im using this random number script to source my images, I cant think of a way to adapt any of those solutions.
Any help is much appreciated, thanks!
I will provide you with an example using CSS3 transitions. You can adapt and improve it for your specific case.
My specific example works only with Webkit as it is written since the implementation of the transcription end callback is vendor dependent. You can fix this by using the correct vendor event handler names.
/* Fades an element to given opacity */
var fade = function(opacity, fn) {
this.addEventListener("webkitTransitionEnd", function end() {
this.removeEventListener("webkitTransitionEnd", end);
fn && fn.call(this);
}, false);
this.style.opacity = opacity;
};
/* Preloads an image */
var load = function(src, fn) {
var self = this, $img = new Image();
$img.onload = function() {
fn && fn.call(self);
};
$img.src = src;
};
/* Steps:
* 1. Fades out current image.
* 2. Preloads next image.
* 3. When loading of next image is complete, sets next image.
* 4. Fades in.
*/
var $img = document.getElementById("imgRand");
/* Fades out */
fade.call($img, 0, function() {
/* Get random dimensions */
var height = Math.ceil(Math.random() * 100) + 100;
var width = Math.ceil(Math.random() * 200) + 100;
var src = "http://placehold.it/" + width + "x" + height;
/* Preloading */
load.call(this, src, function() {
$img.setAttribute("src", src);
/* Fades in */
fade.call($img, 1);
});
});
You can see it here.
The img element has -webkit-transition-duration style property set to 1s.
The most complicated and overlooked part of this is image preloading. Because, unless you preload all images that you want to use, the animation won't be smooth. But at the same time the detection of when an image has been loaded is not an easy task and the method that I'm using is a naive one that most probably will fail for images in the browser's cache. I won't go into details about that, you can search SO for it.
Disclaimer: It is too freaking late. So, I will just dump the code here and come to it later. If there's doubts.
This can be done most easily using a library such as jQuery but here is a jsFiddle example. I use absolute positioning to have two images placed over the top of each other and give one of them an opacity of 0. Then I just toggle between the two and fade one in and one out using helper functions.
The html looks something like this:
<div id="imageHolder">
<img id="imgRand0" src="http://placehold.it/100x100" />
<img id="imgRand1" src="http://placehold.it/100x100" style="opacity:0;alpha(opacity:0);"/>
</div>
<button onclick="setImg()">New Image</button>
The CSS:
img {
position:absolute;
top:0;
left:0;
}
#imageHolder {
position:relative;
height:100px;
}
And the javascript (I use additional functions from this tutorial):
var counter = 0;
function setImg(){
var numRand = Math.floor(Math.random()*6) + 1;
//document.getElementById("imgRand").src = "images/"+numRand+".jpg";
counter = (counter + 1) % 2;
document.getElementById("imgRand" + counter).src = "http://placehold.it/100&text=" + numRand;
fade('imgRand0');
fade('imgRand1');
}
This was too long to put into a comment, but hopefully it will guide you in the right direction.
So, because you're replacing the src of imgRand with each call to setImg, the two images you're trying to cross-fade will not be present in the DOM at the same time. You will probably need to have two separate image tags that are stacked on top of each other with CSS.
Then you will need to set the src on the top image (the one you want to fade in) and hide this image with CSS or your image will just 'appear' as soon as you set the src.
Then you will want to fade the top image in incrementally by setting the opacity of the image until it's 100...
Sorry for such a crazy description, but it's probably far easier if you have jQuery available. I will go and hunt down an example and update this.
Update: If you have jQuery, this is a rudimentary example of what your script might look like: http://jsfiddle.net/tracyfu/W9wMh/ Some of the other solutions here might be better if you're confined to straight JS.