Changing imsg src from one to another shows a 'flick' - javascript

I have an img elment with an image. For instance:
<img id='imageWord' src=images\Card.png onclick='changeImage();'>
When user clicks on it, I want to make a fadeOut, change its src to another image, and then fadeIn.
function changeImage()
{
$('#ImageWord').animate({opacity:0})
.queue(function(){
$(this).attr("src", '');
replaceImage('#ImageWord', 'images\newImage.png');
$(this).dequeue()
})
.animate({opacity:1});
}
var MAX_HEIGHT = 260;
var MAX_WIDTH = 260;
function keepAspectRatio(temp, target, url)
{
$(target).removeAttr('style');
// Get height and width once loaded
var realHeight = temp.height;
var realWidth = temp.width;
// Get how much to divide by (1 if image fits in dimensions)
// Get rid of ", 1" if you just want everything to be either
// MAX_HEIGHT tall or MAX_WIDTH wide
var factor = Math.max(realHeight/MAX_HEIGHT, realWidth/MAX_WIDTH, 1);
realHeight /= factor;
realWidth /= factor;
// Set the target image's source, height and width
$(target).attr("src", url).css({height: realHeight, width: realWidth});
if (realWidth != MAX_WIDTH)
{
var offsetX = (MAX_WIDTH - realWidth ) / 2;
var sum = parseFloat($(target).css("left").replace("px", "")) + offsetX;
$(target).css("left", sum);
}
if (realHeight != MAX_HEIGHT)
{
var offsetY = (MAX_HEIGHT - realHeight) / 2;
var sum = parseFloat($(target).css("top").replace("px", "")) + offsetY;
$(target).css("top", sum);
}
}
function replaceImage($target, url) {
$("<img>").load(function() {
keepAspectRatio(this, $target, url);
}).attr("src", url);
}
Sometimes I see the following:
Card.png fadeOut.
No image (0.1 seconds)
Card.png again (0.1 seconds).
newImage.png fadeIn.
I want to avoid step 3.
Any advice?

As this example shows, you could put all your images at start in display none. Than use jQuery fadeIn and fadeOut to show the right image. All you need is to put them in an position:relative div and define them as position:absolute :
<div class="slideshow" style="position: relative; ">
<img src="http://cloud.github.com/downloads/malsup/cycle/beach1.jpg" width="200" height="200" style="position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 5; opacity: 0; display: none; ">
<img src="http://cloud.github.com/downloads/malsup/cycle/beach2.jpg" width="200" height="200" style="position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 5; opacity: 0; display: none; ">
<img src="http://cloud.github.com/downloads/malsup/cycle/beach3.jpg" width="200" height="200" style="position: absolute; z-index: 6; top: 0px; left: 0px; display: block; width: 200px; height: 200px; opacity: 1; ">
<img src="http://cloud.github.com/downloads/malsup/cycle/beach4.jpg" width="200" height="200" style="position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 5; opacity: 0; display: none; ">
<img src="http://cloud.github.com/downloads/malsup/cycle/beach5.jpg" width="200" height="200" style="position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 5; opacity: 0; display: none; ">
</div>
http://jquery.malsup.com/cycle/basic.html

Supposing you have more that 2 pictures to show (as a slideshow) You could try using two images, one on top of the other. One is the image you are actually displaying, the other is the one you need to show when the first fades.
This way, you can fade the first, showing the bottom one. When the fade animation is ended you place it (callback) under the other one and change its src. There will be no flickering, as you load it in the background.
If you have only 2 images, then the fading is enough to cycle between the images.
Another solution that may solve your problem is to preload your images and store them in the cache. If i'm not wrong, it could solve the problem.
Sorry I provide no code, but I'm at work.... anyway if you need more details tell me.

Related

Slightly move img accordingly with mousemove

I am trying to achieve the following effect: https://github.com/thispagedoesntexist (the one that the character has)
I want my image to move just slightly according to where I move my mouse. Maybe it has something to do with 3d transformation and scaling ... I don't know
I browsed the web and tried to come up with something by myself, but I couldn't. Here's where I stpoped:
HTML
<img class="image" id="module-hotjar" src="./img/image.png" alt="">
CSS
.image{
position: fixed;
z-index: 1;
display: flex;
bottom: -300px;
height: 90vh;
left: 15%;
transition: 0.3s ease;
transform: translate(0px, 0px);
}
JS
var image = document.querySelector('.image');
let root = document.documentElement;
root.addEventListener('mousemove', (e) => {
;
x = e.offsetX / 10;
y = e.offsetY / 10;
image.style.transform = `translate(${x}px,${y}px)`;
});
Thank you
You're on the right track. To achieve this parallax effect, you can apply different ratios to the elements. The difficult part is finding/creating the right images and finding the correct ratios, so that it looks kind of "realistic":
const background = document.querySelector('.background'),
patrick = document.querySelector('.patrick'),
bob = document.querySelector('.bob'),
root = document.documentElement;
root.addEventListener('mousemove', (e) => {
const x = e.clientX,
y = e.clientY;
background.style.transform = `translate(${-x / 20}px,${-y / 40}px)`;
patrick.style.transform = `translate(${-x / 15}px,${-y / 40}px)`;
bob.style.transform = `translate(${x / 10}px,${y / 10}px)`;
});
.background{
position: fixed;
bottom: -5vh;
width: 110vw;
left: -5vw;
}
.patrick{
position: fixed;
bottom: -7vh;
height: 90vh;
right: 10%;
margin-left: -25%;
}
.bob{
position: fixed;
bottom: -10vh;
height: 90vh;
left: 50%;
margin-left: -25%;
}
<img class="background" src="https://wallpaperaccess.com/full/3896911.jpg" />
<img class="patrick" src="https://assets.stickpng.com/thumbs/5cb78e9b7ff3656569c8cec1.png" />
<img class="bob" src="https://lh3.googleusercontent.com/proxy/wHCNlCMGLIi4Fa3QQlxyLRw_uyZoLauUFpMCDzSowxbjmA6gy12KqK6Fe6XD45T6EWas1dimdsh7Rfl3Mv9w3Z28iJAKCqaQLu8TChGV8yzbRqL7WpwHozSPaDYBJIefwmayIaROJ7M" />

Using 100% does not make my canvas fill the window [duplicate]

This question already has answers here:
Getting wrong canvas height
(2 answers)
Closed 7 years ago.
I'm trying to make my canvas fill up the entire window. Setting the width and height to 100% isn't working at all. Instead, it's making it 100px by 100px. Why would this be happening, and how can I achieve my effect?
Here's a fiddle that basically shows my problem. Thank you!
https://jsfiddle.net/t04n6q9y/1/
<body height="100%" width="100%">
<canvas id="myCanvas" width="100%" height="100%"></canvas>
</body>
The width and height are attributes and don't support % they need to be absolute. If you give 100% width and height in CSS, your canvas will not scale to 100% instead it will be zoomed to 100%. I would suggest the following way to achieve 100% width and height:
You need to calculate width in javascript and then apply it, Fiddle
js:
var height = window.innerHeight;
var width = window.innerWidth;
var canvas = document.getElementById('myCanvas');
canvas.height = height;
Snippet:
var height = window.innerHeight;
var width = window.innerWidth;
var canvas = document.getElementById('myCanvas');
canvas.height = height;
canvas.width = width;
var context = canvas.getContext('2d');
context.fillStyle = "#FFFF00";
context.fillRect(0, 0, canvas.width, canvas.height);
body {
margin: 0px;
padding: 0px;
background-color: #00000F
}
canvas {
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
<body>
<canvas id="myCanvas"></canvas>
</body>
You should be doing this with CSS rather than HTML tag attributes. By declaring a CSS class, you will be able to apply this same style to anything else you may want to fullscreen. It also separates the DOM logic from the styling logic.
Here's how I would do it:
HTML:
<canvas class="fullscreen"></canvas>
CSS:
canvas.fullscreen {
width: 100vw;
height: 100vh;
}
The "vw" and "vh" units represent percentage of View Width and View Height, respectively. Using these units will ensure your canvas fills the entire viewport regardless of the size of its parent elements.
All that needed to be done was for the canvas to have an element to expand in.
HTML:
<body>
<div id="canback">
<canvas id="myCanvas"></canvas>
</div>
</body>
CSS:
body {
margin: 0px;
padding: 0px;
background-color: #00000F
}
#canback {
height: 100%;
width: 100%;
margin: 0 auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#myCanvas {
background:#f4f4f4;
height:100%;
width: 100%;
padding: 0;
margin: 0 auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
Here is a Fiddle
I hope this helped. :D

Wrap dynamic content with jQuery

Within Sitefinity CMS, I am using a gallery script that seems to be compiled in the backend files. In other words, I can't access nor change the sourcecode.
The gallery works as it should, but I would like to add a lightbox to it. So I started using 'wrapAll' combined with on load. This works on the very first image, but as soon as the next image is loaded dynamically (in other words, the image and surrounding tags are being replaced), it stops working.
I am stuck. Anyone any idea?
My code:
$(window).on("load", function () {
var i = 0;
$(".galleria-images .galleria-image img").each(function () {
i++;
//alert(i);
var lightboximg = $(this).attr("src");
$(this).wrap("<a href=" + lightboximg + " class='fancybox'></a>");
});
$(".fancybox").fancybox();
})
I also tried to just add fancybox() to the structure, but that works once as well.
The generated HTML (as it should):
<div style="position: relative; top: 0px; left: 0px; width: 100%; height: 100%;" class="galleria-images">
<div style="overflow: hidden; position: absolute; top: 0px; left: 0px; transition: none 0s ease 0s ; opacity: 0; z-index: 0;" class="galleria-image"><div style="position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; z-index: 2;" class="galleria-layer"></div>
<div style="overflow: hidden; position: absolute; top: 0px; left: 0px; z-index: 4; background: rgb(0, 0, 0) none repeat scroll 0% 0%; display: none;" class="galleria-frame">
</div>
</div>
<div style="overflow: hidden; position: absolute; top: 0px; left: 0px; opacity: 1; width: 563px; height: 340px; transition: none 0s ease 0s ; z-index: 1;" class="galleria-image"><div style="position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; z-index: 2; display: none; width: 563px; height: 352px;" class="galleria-layer">
</div>
<div style="overflow: hidden; position: absolute; top: 0px; left: 0px; z-index: 4; background: rgb(0, 0, 0) none repeat scroll 0% 0%; display: none;" class="galleria-frame">
</div>
<a href="/images/default-source/scholen/adm/administratief-en-juridisch-44.jpg?sfvrsn=2" class="fancybox">
<img src="/images/default-source/scholen/adm/administratief-en-juridisch-44.jpg?sfvrsn=2" style="display: block; opacity: 1; min-width: 0px; min-height: 0px; max-width: none; max-height: none; transform: translate3d(0px, 0px, 0px); width: 544px; height: 340px; position: absolute; top: -6px; left: 0px;" height="340" width="544"></a>
</div>
</div>
The next image looks the same, except the image isn't wrapped.
update
Eventually solved it by killing Galleria and starting it over again using my own options. The excerpt is:
Galleria.configure({
extend: function (options) {
Galleria.log(this) // the gallery instance
Galleria.log(options) // the gallery options
// listen to when an image is shown
this.bind('image', function (e) {
Galleria.log(e) // the event object may contain custom objects, in this case the main image
Galleria.log(e.imageTarget) // the current image
lightboximg = jQuery(e.imageTarget).attr("src");
jQuery(e.imageTarget).addClass('test');
jQuery(e.imageTarget).wrap("<a href=" + lightboximg + " class='fancybox'></a>");
$(".fancybox").fancybox();
});
}
});
The problem is that "load" event triggers only once. That's why you can see only one image wrapped.
Here is a easy way to do it:
HTML
<div id="container">
Hello World
</div>
JS
(function() {
setInterval(function(){
$("#container").append('<div class="item new">New Item</div>');
}, 3000);
setInterval(function() {
$('.item').css('color', 'red');
$('.item').removeClass('new');
}, 100);
})();
Fiddle
Downside of this approach is unnecessary load on page, so if you need performance, take a look at:Determining if a HTML element has been added to the DOM dynamically
The third option, and the best on my opinion is to trigger custom event when image added, but for this you will need to change code, which actually responsible for adding images to the page:
$(document).trigger('imageAdded');
$(document).on('imageAdded', function() {....})

Parallax scrolling effect, start at certain percentage on page?

I am using this script to create a parallax scroll effect on my page:
$(window).scroll(function (e) {
parallax();
});
function parallax() {
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', - (scrolled * 0.1) + '%');
$('.cloud2').css('top', - (scrolled * 0.3) + '%');
$('.cloud3').css('top', - (scrolled * 0.2) + '%');
}
HTML:
<div class="cloud1"></div>
<div class="cloud2"></div>
<div class="cloud3"></div>
CSS (same for .cloud2 and .cloud3 but with different background image, opacity and 'top' 'left'):
.cloud1 {
background: url(../images/cloud1.png) no-repeat;
opacity: 0.9;
position: fixed;
width: 100%;
height: 100%;
top: 50%;
left: 20%;
z-index: 1;
}
When the script begins (on scroll) the HTML changes to this:
<div class="cloud1" style="top: 0%; "></div>
which makes the 'cloud' jump to the top of the page, and then the parallax starts (which you can see for a very short period of time as it's already jumped to the top of the page)
Is there a way to set the style="top: 0%;" to start at say 20% when the parallax begins, and then begin to multiply by 0.1?
Here is a codepen of the problem : http://codepen.io/anon/pen/tkfDH
Hopefully this is clear,
Any help is appreciated
Jon
Okay so I think i've fixed the problem.
$(window).scroll(function(e){
parallax();
});
function parallax(){
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', -(scrolled*0.1)+70+'%');
// the 70 corresponds to the 'cloud1' value for 'top'.
$('.cloud2').css('top', -(scrolled*0.3)+50+'%');
// the 50 corresponds to the 'cloud2' value for 'top'.
}
http://cdpn.io/naIjf
#hero {
background:black;
color: white;
}
.cloud1, .cloud2 {
opacity: 0.8;
position: fixed;
width: 100%;
height: 100%;
z-index: 1;
}
.cloud1 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 70%;
left: 0;
}
.cloud2 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 50%;
left: 65%;
}
Fixed the jump.
Hope this helps.

Put overlay on document with transparent window

I would like to do something with my document which is quite unique (haven't seen it before) and thus maybe not even possible.
What I would like is to have a div which will overlay everything in the document, maybe give it background black so that nothing is visible. Second I would like to have a small squire window in the overlay which doesn't share the black background, in fact it is somewhat transparent and therefore it would be possible to 'peek' trough that window to see document content. But only the content where this window is. It would be kinda like those "zoom" plugins in which only a small portion is being zoomed, but in this case it would show specific content. Any idea how to create such a thing?
An example of what you can do is the following (it may not be the best but it works)
HTML
<div id='peakview'></div> <!-- This div is your view window -->
<div id='out'>
<div class='overlay'></div>
<div class='overlay'></div>
<div class='overlay'></div>
<div class='overlay'></div>
</div>
The <div> inside of #out will re-size accordingly to the position of #peakview creating the illusion of a full overlay. This can be done with simple css and some calculus.
Mainly what you need is the position of the element on screen.
var h = $(this).offset().top;
var l = $(this).offset().left;
var r = ($(window).width() - ($(this).offset().left + $(this).outerWidth()));
//right offset
var b = ($(window).height() - ($(this).offset().top + $(this).outerWidth()));
//bottom offset
In my example I used .draggable() from jQuery UI to move the div around. And while dragging the 4 divs shown above are adjusting their height and width to fill up the space between #peakview and document border.
An example for the first div
$('.overlay:eq(0)').css({
top: 0,
left: 0,
width: '100%',
height: h //the height is always changing depending on the #peakview .offset().top
});
In this fiddle you will see how the filling divs behave
Another ruff start:
http://jsfiddle.net/XDrSA/
This require some extra work, but it may suit your needs.
HTML:
<div id="yourContent" style="width: 300px; margin:100px auto;">
<input type="button" id="zoom" value="Click to zoom"/>
</div>
<div id="zoomer">
<div id="window">This is your "window"</div>
<div id="overlay_top"></div>
<div id="overlay_left"></div>
<div id="overlay_right"></div>
<div id="overlay_bottom"></div>
</div>
CSS:
body {
margin:0;
padding:0;
}
#zoomer {
height: 100%;
width: 100%;
position: absolute;
top: 0;
display: none;
}
#overlay_top {
height: 20%;
width: 100%;
background-color: black;
position: absolute;
top: 0
}
#overlay_right {
height: 100%;
width: 20%;
background-color: black;
position: absolute;
right: 0;
}
#overlay_left {
height: 100%;
width: 20%;
background-color: black;
position: absolute;
left: 0;
}
#overlay_bottom {
height: 20%;
width: 100%;
background-color: black;
position: absolute;
bottom: 0;
}
#window {
margin: 0 auto;
height: 100%;
width: 80%;
position: absolute;
background-color: rgba(0,0,0,.5);
}
And a piece of javascript:
$('#zoom').click(function() {
$('#zoomer').fadeIn();
});
You may need to stumble with the positioning, and the window will be a fixed size one. Not draggable though.

Categories