combine two image and change one of this on click - javascript

I have to combine two images as in the diagram (under this message). The green image must be on the red line of another image, the problem is that by reducing the window as soon as the image 1 is resized responsively, the green image moves and no longer remains glued with the other.
I reserve a way to do this (HTML, CSS or jQuery), the two images must behave as if they were one, responsively. Also when I click on the small image this must be changed with another image of the same size but different.
Thanks to everyone who will offer me help.

See the code snippet below (also found here - it doesn't show very well on SO as you can't resize the output window). It's not 100% clear to me what you want to do, but I think this accomplishes it. If not, let me know and I'll amend the answer.
// This position is relative to the original size of the first image.
// i.e. when the window is exactly as large as image 1, image 2 will
// be displayed at (100, 200)
var pos = [100, 200];
// Reposition img2 as the window is resized
function reposition () {
img2.style.left = (pos[0] / img1.naturalWidth * img1.clientWidth) + "px";
img2.style.top = (pos[1] / img1.naturalHeight * img1.clientHeight) + "px";
// The position is re-calculated based on the scaling of image 1
// (its current width / its original width)
// This is multiplied by pos to ensure that image 2 is always in the
// same position proportional to the size of image 1
}
// Run reposition on window changes
window.onresize = function () {
reposition();
}
window.onload = function () {
reposition();
}
// Change the image on click
img2.onclick = function () {
img2.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Unterf%C3%BChrung_B22_M%C3%BCnchner_Ring_3150017.jpg/320px-Unterf%C3%BChrung_B22_M%C3%BCnchner_Ring_3150017.jpg"
}
/* Image 1 will fill the window */
#img1 {
width: 50vw;
}
/* Image 2 has absolute position, and is 1/5 the size of image 1 */
#img2 {
position: absolute;
width: 15vw;
/* Obviously this sizing can be changed */
}
body {
margin: 0;
}
/*
Because both images scale with the window, they will keep
the same size proportional to each other. This could also be done in Javascript if needed.
*/
<!-- Example images -->
<img id="img1" src="https://cdn.pixabay.com/photo/2016/06/18/17/42/image-1465348_960_720.jpg" />
<img id="img2" src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Tunnel_Eierberge_Regional_Express_3300341.jpg/320px-Tunnel_Eierberge_Regional_Express_3300341.jpg" />

Related

JS-based hidden image breaks body width and height

I use a Zoom JavaScript for zoom my images when I click on it.
This JavaScript creates a hidden copy of my image with bigger dimensions.
Problem is, when I load my page, the body takes a height and width according to the hidden image.
You can see at the right of the screen the menu doesn't fit with the width of the screen (the hidden image is not displayed).
Is there a solution when I load the page, the size of the body does not take into account the hidden image?
// To achieve this effect we're creating a copy of the image and scaling it up. Next we'll pull the x and y coordinates of the mouse on the original image. Then we translate the big image so that the points we are looking at match up. Finally we create a mask to display the piece of the image that we're interested in.
let settings = {
'magnification': 3,
'maskSize': 200
}
// Once our images have loaded let's create the zoom
window.addEventListener("load", () => {
// find all the images
let images = document.querySelectorAll('.image-zoom-available');
// querySelectorAll produces an array of images that we pull out one by one and create a Zoombini for
Array.prototype.forEach.call(images, (image) => {
new Zoombini(image);
});
});
// A Zoombini (or whatever you want to call it), is a class that takes an image input and adds the zoomable functionality to it. Let's take a look inside at what it does.
class Zoombini {
// When we create a new Zoombini we run this function; it's called the constructor and you can see it taking our image in from above
constructor(targetImage) {
// We don't want the Zoombini to forget about it's image, so let's save that info
this.image = targetImage;
// The Zoombini isActive after it has opened up
this.isActive = false;
// But as it hasn't been used yet it's maskSize will be 0
this.maskSize = 0;
// And we have to start it's coordinates somewhere, they may as well be (0,0)
this.mousex = this.mousey = 0;
// Now we're set up let's build the necessary compoonents
// First let's clone our original image, I'm going to call it imageZoom and save it our Zoombini
this.imageZoom = this.image.cloneNode();
// And pop it next to the image target
this.image.parentNode.insertBefore(this.imageZoom, this.image);
// Make the zoom image that we'll crop float above it's original sibling
this.imageZoom.style.zIndex = 1;
// We don't want to be able to touch it though, we want to reach whats underneat
this.imageZoom.style.pointerEvents = "none";
// And so we can translate it let's make it absolute
this.imageZoom.style.position = "absolute";
// Now let's scale up our enlarged image and add an event listener so that it resizes whenever the size of the window changes
this.resizeImageZoom();
window.addEventListener("resize", this.resizeImageZoom.bind(this), false);
// Now that we're finishing the constructor we need to addeventlisteners so we can interact with it
// This function is just below, but still exists within our Zoombini
this.UI();
// Finally we'll apply an initial mask at default settings to hide this image
this.drawMask();
}
// resizeImageZoom resizes the enlarged image
resizeImageZoom() {
// So let's scale up this version
this.imageZoom.style.width = this.image.getBoundingClientRect().width * settings.magnification + 'px';
this.imageZoom.style.height = "unset"
}
// This could be inside the constructor but it's nicer on it's own I think
UI() {
this.image.addEventListener('mousemove', (event) => {
// When we move our mouse the x and y coordinates from the event
// We subtract the left and top coordinates so that we get the (x,y) coordinates of the actualy image, where (0,0) would be the top left
this.mousex = event.clientX - this.image.getBoundingClientRect().left;
this.mousey = event.clientY - this.image.getBoundingClientRect().top;
// if we're not active then don't display anything
if (!this.isActive) return;
// The drawMask() function below displays our the portion of the image that we're interested in
this.drawMask();
});
// When they mousedown we open up our mask
this.image.addEventListener('mousedown', () => {
// But it can be opening or closing, so let's pass in that information
this.isExpanding = true;
// To do that we start the maskSizer function, which calls itself until it reaches full size
this.maskSizer();
// And hide our cursor (we know where it is)
this.image.classList.add('is-active');
});
// if the mouse is released, close the mask
this.image.addEventListener('mouseup', () => {
// if it's not expanding, it's closing
this.isExpanding = false;
// if the mask has already expanded we'll need to start another maskSizer to shrink it. We don't run the maskSizer unless the mask is changing
if (this.isActive) this.maskSizer();
});
// same as above, caused by us moving out of the zoom area
this.image.addEventListener('mouseout', () => {
this.isExpanding = false;
if (this.isActive) this.maskSizer();
});
}
// The drawmask function shows us the piece of the image that we are hovering over
drawMask() {
// Let's use getBoundingClientRect to get the location of our images
let image = this.image.getBoundingClientRect();
let imageZoom = this.imageZoom.getBoundingClientRect();
// We'll start by getting the (x,y) of our big image that matches the piece we're mousing over (which we stored from our event listener as this.mousex and this.mousey). This is a clunky bit of code to help the zooms work in a variety of situations.
let prop_x = this.mousex / image.width * imageZoom.width * (1 - 1 / settings.magnification) - image.x - window.scrollX;
let prop_y = this.mousey / image.height * imageZoom.height * (1 - 1 / settings.magnification) - image.y - window.scrollY;
// Shift the large image by that amount
this.imageZoom.style.left = -prop_x + "px";
this.imageZoom.style.top = -prop_y + "px";
// Now we need to create our mask
// First let's get the coordinates of the point we're hovering over
let x = this.mousex * settings.magnification;
let y = this.mousey * settings.magnification;
// And create and apply our clip
let clippy = "circle(" + this.maskSize + "px at " + x + "px " + y + "px)";
this.imageZoom.style.clipPath = clippy;
this.imageZoom.style.webkitClipPath = clippy;
}
// We'll use the maskSizer to either expand or shrink the size of our mask
maskSizer() {
// We're in maskSizer so we're changing the size of our mask. Let's make the mask radius larger if the Zoombini is expanding, or shrink it if it's closing. The numbers below might need to be adjusted. It closes faster than it opens
this.maskSize = this.isExpanding ? this.maskSize + 35 : this.maskSize - 40;
// It has the form of: condition ? value-if-true : value-if-false
// Think of the ? as "then" and : as "else"
// if we've reaached max size, don't make it any larger
if (this.maskSize >= settings.maskSize) {
this.maskSize = settings.maskSize;
// we'll no longer need to change the maskSize so we'll just set this.isActive to true and let our mousemove do the drawing
this.isActive = true;
} else if (this.maskSize < 0) {
// Our mask is closed
this.maskSize = 0;
this.isActive = false;
this.image.classList.remove('is-active');
} else {
// Or else we haven't reached a size that we want to keep yet. So let's loop it on the next available frame
// We bind(this) here because so that the function remains in context
requestAnimationFrame(this.maskSizer.bind(this));
}
// After we have the appropriate size, draw the mask
this.drawMask();
}
}
function zoom(e) {
var zoomer = e.currentTarget;
e.offsetX ? offsetX = e.offsetX : offsetX = e.touches[0].pageX
e.offsetY ? offsetY = e.offsetY : offsetX = e.touches[0].pageX
x = offsetX / zoomer.offsetWidth * 100
y = offsetY / zoomer.offsetHeight * 100
zoomer.style.backgroundPosition = x + '% ' + y + '%';
}
//My image generated after page load
.image-zoom-available {
height: unset;
border-radius: 30px;
z-index: 1;
pointer-events: none;
position: absolute;
width: 834.688px;
left: 526.646px;
top: 231.729px;
clip-path: circle(0px at 439.062px 987.812px);
}
<div class="col-12 col-xl-3 col-lg-5 justify-content-center ">
<div class="mb-3">
<img class="image-zoom-available" style="height:75%; border-radius: 30px" src='{{ asset(' /radio/ ') }}{{examen.idpatient.id}}_examen_{{examen.id}}_radio.png' id="image_radio" draggable="false" />
</div>
</div>
Try adding the following property in your hidden image css :
display: none
A non visible element still take space in the web page. Cf: What is the difference between visibility:hidden and display:none?
Remove or override the display: none property when you want to display the image.
I add
this.imageZoom.style.display = "none";
on the event : mouseup and
this.imageZoom.style.display = "block";
on mousedown event. And it's fix thanks !

I need to position image at the bottom of the background image and have them stay in place when window is resized

I have a background image and I have other images that need to stay at the bottom of the background image, even if the window resizes or there is a different screen size.
This is a ReactJS web app so any javascript or CSS will work.
CSS:
html {
background: url(imageInMemory.png) no-repeat center center fixed;
background-size: contain;
}
Javascript:
// I calculate the ratio for 'background-size: contain'
let A = window.innerWidth;
let B = window.innerHeight;
let W = naturalWidth; // Width of image, I have this hardcoded
let H = naturalHeight; // Height of image, I have this hardcoded
const ratio = Math.min((A/W), (B/H));// this is the ratio to which the image was scaled given the current window size.
// I position images on top of background images where they should be using this new ratio
<div style={{marginTop: ratio * H * .7}}>
<img src='otherImage'/>
</div>
This works on some window sizes, but sometimes the images will not be on top of the right area of the background Image.
I did a responsive layout for one image behind and a floating form resizing and repositioning all fields and texts.
I will not put all my code here, then i said to you create your own code inside a function named like "update_field_positions" running in events window resize and load.
For screens with more than 608px the height of my image is 882px
Then i define the reason of proportion: img_cadastro.clientHeight / 882
And use this value for resize and reposition all the items
I used css too:
#media screen and (max-width:608px) {
.img_cadastro {
width:100%;
height:auto;
}
and
#media screen and (min-width:608px) {
.img_cadastro {
width:608px;
height:882px;
}
A little piece of my working js code:
function update_field_positions() {
.... (some code) ....
var razao = img_cadastro.clientHeight / 882;
bloco_campos_ext.style.top = ((258 * razao) + compensador) + "px";
div_voucher.style.marginTop = ((57 * razao) + compensador_voucher) + "px";
div_voucher.style.marginLeft = ((120 * razao) + compensador) + "px";
nome_voucher.style.fontSize = (24 * razao) + "px";
cod_voucher.style.fontSize = (28 * razao) + "px";
resize_object(bloco_campos_ext, 357, 148, razao, false);
resize_object(bloco_campos_int, 357, 148, razao, false);
}
Use this css to your div:
position:fixed;
bottom:0;
For a responsive screen working when the windows is resized
Your codes of getting ratio and repositioning should be inside a function, you could create a function named update_field_positions for example: update_field_positions()
then your function must be called in 2 events, onload and window.resize
example:
function start() {
update_field_positions();
window.onresize = update_field_positions;
}
<body onLoad="start()">
Tou should use onload, for wait objects become ready before working with them to avoid errors and window.onresize to update values with a new window.innerWidth
The other problem is that the window can be resized to a smaller size than your image
And then you have to create some code to handle these situations:
if (window.innerWidth < naturalWidth) {...}

Render div content in fullhd then proportional scale

TV shows slides, that holds HTML inside. TV's resolution is FullHD (1920x1080).
When editing the slide I want to able to know, how slide will exactly be shown on TV. Although I have a FullHD monitor, I've never worked in the browser in fullscreen mode. Other people, which potentially be working with slides, want to see slides as is too.
Using another word, I need to render 1920x1080 div, then proportionally scale it to fit client's browser. How can be this done using CSS or JS, or jQuery?
Edit: I do NOT need to proportional manipulate the image. I need to see how page will look on FullHD resolution regardless of client's viewport resolution
UPDATED!! Here is the demo: https://jsfiddle.net/8jxk0atm/4/
Old resize 1920x1080 aspect ratio demo: https://jsfiddle.net/8jxk0atm/2/
You can create the div spec with 1920x1080. And put this
// screen zoom out for checking
document.body.style.zoom="40%"
on top of your js code.
It will zoom out your document so you can see what it will look on 1920x1080 div.
HTML
<div id="fullscreen"></div>
CSS
html,
body {
margin: 0;
padding: 0;
}
#fullscreen {
width: 1920px;
height: 1080px;
background: green;
color: #fff;
}
JS
// screen zoom out for checking
document.body.style.zoom="40%"
makeFullHD();
function makeFullHD() {
var value = $(window).outerWidth();
value *= 1;
var valueHeight = Math.round((value / 16) * 9);
$('#vidHeight').text(valueHeight);
$('#videoBox').css('width', value + 'px').css('height', valueHeight + 'px');
$('#videoPlayer').css('width', value + 'px');
$('#fullscreen').css({
width: value,
height: valueHeight
});
// test
$('#fullscreen').text('Width:' + value + '\n' + 'Height:' + valueHeight);
}
$(window).resize(function() {
makeFullHD();
});

Show a series of images on scroll

The closest solution I found is Show div on scrollDown after 800px.
I'm learning HTML, CSS, and JS, and I decided to try to make a digital flipbook: a simple animation that would play (ie, load frame after frame) on the user's scroll.
I figured I would add all the images to the HTML and then use CSS to "stack them" in the same position, then use JS or jQuery to fade one into the next at different points in the scroll (ie, increasing pixel distances from the top of the page).
Unfortunately, I can't produce the behavior I'm looking for.
HTML (just all the frames of the animation):
<img class="frame" id="frame0" src="images/hand.jpg">
<img class="frame" id="frame1" src="images/frame_0_delay-0.13s.gif">
CSS:
body {
height: 10000px;
}
.frame {
display: block;
position: fixed;
top: 0px;
z-index: 1;
transition: all 1s;
}
#hand0 {
padding: 55px 155px 55px 155px;
background-color: white;
}
.frameHide {
opacity: 0;
left: -100%;
}
.frameShow {
opacity: 1;
left: 0;
}
JS:
frame0 = document.getElementById("frame0");
var myScrollFunc = function() {
var y = window.scrollY;
if (y >= 800) {
frame0.className = "frameShow"
} else {
frame0.className = "frameHide"
}
};
window.addEventListener("scroll", myScrollFunc);
};
One of your bigger problems is that setting frame0.className = "frameShow" removes your initial class frame, which will remove a bunch of properties. To fix this, at least in a simple way, we can do frame0.className = "frame frameShow", etc. Another issue is that frame0 is rendered behind frame1, which could be fixed a variety of ways. ie. Putting frame0's <img> after frame1, or setting frame0's CSS to have a z-index:2;, and then setting frame0's class to class="frame frameHide" so it doesn't show up to begin with. I also removed the margin and padding from the body using CSS, as it disturbs the location of the images. I have made your code work the way I understand you wanted it to, here is a JSFiddle.
It depends on your case, for example, in this jsFiddle 1 I'm showing the next (or previous) frame depending on the value of the vertical scroll full window.
So for my case the code is:
var jQ = $.noConflict(),
frames = jQ('.frame'),
win = jQ(window),
// this is very important to be calculated correctly in order to get it work right
// the idea here is to calculate the available amount of scrolling space until the
// scrollbar hits the bottom of the window, and then divide it by number of frames
steps = Math.floor((jQ(document).height() - win.height()) / frames.length),
// start the index by 1 since the first frame is already shown
index = 1;
win.on('scroll', function() {
// on scroll, if the scroll value equal or more than a certain number, fade the
// corresponding frame in, then increase index by one.
if (win.scrollTop() >= index * steps) {
jQ(frames[index]).animate({'opacity': 1}, 50);
index++;
} else {
// else if it's less, hide the relative frame then decrease the index by one
// thus it will work whether the user scrolls up or down
jQ(frames[index]).animate({'opacity': 0}, 50);
index--;
}
});
Update:
Considering another scenario, where we have the frames inside a scroll-able div, then we wrap the .frame images within another div .inner.
jsFiddle 2
var jQ = $.noConflict(),
cont = jQ('#frames-container'),
inner = jQ('#inner-div'),
frames = jQ('.frame'),
frameHeight = jQ('#frame1').height(),
frameWidth = jQ('#frame1').width() + 20, // we add 20px because of the horizontal scroll
index = 0;
// set the height of the outer container div to be same as 1 frame height
// and the inner div height to be the sum of all frames height, also we
// add some pixels just for safety, 20px here
cont.css({'height': frameHeight, 'width': frameWidth});
inner.css({'height': frameHeight * frames.length + 20});
cont.on('scroll', function() {
var space = index * frameHeight;
if (cont.scrollTop() >= space) {
jQ(frames[index]).animate({'opacity': 1}, 0);
index++;
} else {
jQ(frames[index]).animate({'opacity': 0}, 0);
index--;
}
});
** Please Note that in both cases all frames must have same height.

(Javascript/CSS) resizing function not working

I have a container div that has to fit in two different types of pictures. Some pictures are 'potrait', width:533px and height:801px, others are 'landscape', width:800px and height:533px.
So to make the div size change to accommodate for the pictures, I wrote the function described below (the 'photos' var is an array of pictures and the [i] is a variable for changing through them and 'img' is a var that fetches the #container element)
function resize() {
var width = photos[i].clientWidth;
var height = photos[i].clientHeight;
if (width + height === 1333) {
img.style.width="800px";
img.style.height="533px";
}
else if (width + height === 1334) {
img.style.width="533px";
img.style.height="801px";
}
}
Then, I placed this function in the next and back functions for switching between the pictures,
function next() {
img.src = photos[i];
el.innerHTML = caption[i];
resize();
if (i<photos.length-1){
i=i+1;
} else {
i=0;
}
}
The next and back functions work, but when they get to the pictures that needed to be resized, the container holds the same dimensions that were preset in the CSS.(the preset widht/height in the CSS is for the landscape pictures, because I only have 2 potrait pictures that the div needs to change its size to.
#container {
height: 533px;
width: 800px;
overflow:hidden;
}
I tried looking at other resize threads but whereas people have needed a way to get only a dynamic width or height, I need both to be that way. I think the problem lies in the "clientWidth/Height" property which I thought gets the width/height of the object before the '.' And i'm not sure if I should set the CSS container div to have a height or leave it to "auto" or a certain percentage. I'd appreciate any help on the matter :)

Categories

Resources