When I manage to move the image comparison slider, the actual 'slider' left behind. The slider JS code is from https://www.w3schools.com/howto/howto_js_image_comparison.asp
and can be easily inspect there but I will paste the code in here too.
I have tried to move the slider with Css grid but the as mentioned before the slider icon won't move with the images.
function initComparisons() {
var x, i;
/* Find all elements with an "overlay" class: */
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/* Once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function: */
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0, w, h;
/* Get the width and height of the img element */
w = img.offsetWidth;
h = img.offsetHeight;
/* Set the width of the img element to 50%: */
img.style.width = (w / 2) + "px";
/* Create slider: */
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/* Insert slider */
img.parentElement.insertBefore(slider, img);
/* Position the slider in the middle: */
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/* Execute a function when the mouse button is pressed: */
slider.addEventListener("mousedown", slideReady);
/* And another function when the mouse button is released: */
window.addEventListener("mouseup", slideFinish);
/* Or touched (for touch screens: */
slider.addEventListener("touchstart", slideReady);
/* And released (for touch screens: */
window.addEventListener("touchstop", slideFinish);
function slideReady(e) {
/* Prevent any other actions that may occur when moving over the image: */
e.preventDefault();
/* The slider is now clicked and ready to move: */
clicked = 1;
/* Execute a function when the slider is moved: */
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/* The slider is no longer clicked: */
clicked = 0;
}
function slideMove(e) {
var pos;
/* If the slider is no longer clicked, exit this function: */
if (clicked == 0) return false;
/* Get the cursor's x position: */
pos = getCursorPos(e)
/* Prevent the slider from being positioned outside the image: */
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/* Execute a function that will resize the overlay image according to the cursor: */
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/* Get the x positions of the image: */
a = img.getBoundingClientRect();
/* Calculate the cursor's x coordinate, relative to the image: */
x = e.pageX - a.left;
/* Consider any page scrolling: */
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/* Resize the image: */
img.style.width = x + "px";
/* Position the slider: */
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
initComparisons();
.img-comp-container {
margin:auto;
position: relative;
height: 100vh;
width: 100vw
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow:hidden;
}
.img-comp-img img {
display: block;
vertical-align: middle;
}
.img-comp-slider {
position: absolute;
z-index: 9;
cursor: ew-resize;
width: 0;
height: 0;
border-style: solid;
border-width: 9px 0 9px 14px;
border-color: transparent transparent transparent #ffffff;
}
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img/ysl_before.jpg" width="650" height="450">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img/ysl_after.jpg" width="650" height="450">
</div>
</div>
I believe this fixes what you are looking for:
Wrap the existing container in another div (img-comp-outer-container), remove margin from img-comp-container and set height/width of img-comp-container to auto.
You can then style the outer container to align the component how you like
<div class="img-comp-outer-container"> <!--new div -->
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img_snow.jpg" width="650" height="450">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img_forest.jpg" width="650" height="450">
</div>
</div>
</div> <!--new div end -->
.img-comp-outer-container {
/* add your styles to move around component */
}
.img-comp-container {
/* margin: auto; */
position: relative;
height: auto; /* was 100vh */
width: auto; /* was 100vw */
}
I wanted to bring the two images, that I'm comparing using image compare slider to the center of the page. The code available on W3Schools to compare images using slider but there was not suggestion about centering it. So what I did was I placed div id box and added all other classes into it and styled the box as white with height and width and added float-right to the img-comp-container. You can change the width and height of box accordingly to center the slider.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {box-sizing: border-box;}
.img-comp-container {
float: right; /*new change*/
position: relative;
height: 200px; /*should be the same height as the images*/
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow:hidden;
}
.img-comp-img img {
display:block;
vertical-align:middle;
}
.img-comp-slider {
position: absolute;
z-index:9;
cursor: ew-resize;
/*set the appearance of the slider:*/
width: 40px;
height: 40px;
background-color: #2196F3;
opacity: 0.7;
border-radius: 50%;
}
/*new change*/
#box{
background: white;
width: 150px;
height: 200px;
}
</style>
<script>
function initComparisons() {
var x, i;
/*find all elements with an "overlay" class:*/
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/*once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function:*/
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0, w, h;
/*get the width and height of the img element*/
w = img.offsetWidth;
h = img.offsetHeight;
/*set the width of the img element to 50%:*/
img.style.width = (w / 2) + "px";
/*create slider:*/
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/*insert slider*/
img.parentElement.insertBefore(slider, img);
/*position the slider in the middle:*/
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/*execute a function when the mouse button is pressed:*/
slider.addEventListener("mousedown", slideReady);
/*and another function when the mouse button is released:*/
window.addEventListener("mouseup", slideFinish);
/*or touched (for touch screens:*/
slider.addEventListener("touchstart", slideReady);
/*and released (for touch screens:*/
window.addEventListener("touchend", slideFinish);
function slideReady(e) {
/*prevent any other actions that may occur when moving over the image:*/
e.preventDefault();
/*the slider is now clicked and ready to move:*/
clicked = 1;
/*execute a function when the slider is moved:*/
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/*the slider is no longer clicked:*/
clicked = 0;
}
function slideMove(e) {
var pos;
/*if the slider is no longer clicked, exit this function:*/
if (clicked == 0) return false;
/*get the cursor's x position:*/
pos = getCursorPos(e)
/*prevent the slider from being positioned outside the image:*/
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/*execute a function that will resize the overlay image according to the cursor:*/
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/*get the x positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x coordinate, relative to the image:*/
x = e.pageX - a.left;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/*resize the image:*/
img.style.width = x + "px";
/*position the slider:*/
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
</script>
</head>
<body>
<h1>Compare Two Images</h1>
<p>Click and slide the blue slider to compare two images:</p>
<div id="box">/*new change*/
<div class="img-comp-container">
<div class="img-comp-img">
<img src="img_snow.jpg" width="300" height="200">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="img_forest.jpg" width="300" height="200">
</div>
</div>
</div>
<script>
/*Execute a function that will execute an image compare function for each element with the img-comp-overlay class:*/
initComparisons();
</script>
</body>
</html>
Related
i am trying to zoom out the image when scroll . if i change the width and height of image to 150px. the image is zooming in first then zooming out when go back scroll. however i want the other way around. on the first view the image is full width and height then when i scroll i want to zoom out the image first then proceed to red background. then if i scroll back again the image will be zoom in again. Please help.
This is the code:
https://codesandbox.io/s/relaxed-elgamal-43iltb?file=/index.html
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
</head>
<style>
body {
margin: 0;
}
img {
width: 100%;
height: 100%;
background-color: black;
}
.fade {
height: 100vh;
width: 100%;
position: fixed;
top: 0;
left: 0;
background: blue;
}
.zoom {
height: 100vh;
width: 100%;
display: grid;
place-items: center;
position: fixed;
top: 0;
left: 0;
}
.afterzoom {
position: relative;
height: 200vh;
width: 100%;
background: red;
overflow-x: auto;
}
.third {
position: absolute;
height: 300vh;
width: 100%;
background: red;
overflow-x: auto;
}
</style>
<body>
<div class="fade"></div>
<div class="zoom">
<img src="https://via.placeholder.com/150" alt="" />
</div>
<div class="afterzoom">
<p>This should appear after the above element is fully zoomed.</p>
</div>
<div class="third">
<p>Thirdpage</p>
</div>
</body>
</html>
<script>
const zoomElement = document.querySelector(".zoom");
const fadeElement = document.querySelector(".fade");
const afterZoomElement = document.querySelector(".afterzoom");
const imgElement = document.querySelector("img");
const WIDTH = document.body.clientWidth;
const HEIGHT = zoomElement.clientHeight;
const IMAGE_WIDTH = imgElement.clientWidth;
const IMAGE_HEIGHT = imgElement.clientHeight;
const ZOOM_SPEED = 100; // Lower is faster
const ZOOM_BREAKPOINT = WIDTH / IMAGE_WIDTH; // When it should stop zooming in
const IMAGE_HEIGHT_MAX = IMAGE_HEIGHT * ZOOM_BREAKPOINT;
const ABSOLUTE = ZOOM_BREAKPOINT * ZOOM_SPEED; // Absolute position, when the Element reached maximum size
// Fade --------------------------------------------------------------------------------------
const FADE_SPEED = 500; // Lower is faster
let fade = 1;
let prev = 0;
// -------------------------------------------------------------------------------------- Fade
function anim() {
let scroll = window.scrollY;
let temp = scroll / ZOOM_SPEED;
let zoom = temp > 1 ? temp : 1;
console.log("ZOOM_BREAKPOINT", ZOOM_BREAKPOINT);
// Only update the Elements scale, when we are below the breakpoint
if (zoom < ZOOM_BREAKPOINT) {
console.log("less breakpont");
console.log("zoom", zoom);
// Only scale the Image, so the Zoom element does not mess with the document width
imgElement.style.transform = `scale(${zoom - 0.6})`;
// Sets the Elements position to fixed, so it can resize without scrolling away
zoomElement.style.top = "0px";
zoomElement.style.position = "fixed";
} else {
// Makes sure the Element always reaches Max Size
imgElement.style.transform = `scale(${ZOOM_BREAKPOINT})`;
// Sets the elements position to absolute, so it will scroll with the rest of the document
zoomElement.style.position = "absolute";
zoomElement.style.top = ABSOLUTE + "px";
}
// Fade --------------------------------------------------------------------------------------
let dif = prev - scroll;
if (zoom < ZOOM_BREAKPOINT - FADE_SPEED / ZOOM_SPEED) {
fade = 1;
} else if (zoom > ZOOM_BREAKPOINT) {
fade = 0;
} else {
fade += dif / FADE_SPEED;
}
fadeElement.style.opacity = fade;
prev = scroll;
// -------------------------------------------------------------------------------------- Fade
}
// Resets scroll position on every reload
if ("scrollRestoration" in history) {
history.scrollRestoration = "manual";
}
document.addEventListener("scroll", () => window.requestAnimationFrame(anim));
// Fade --------------------------------------------------------------------------------------
zoomElement.style.opacity = 1;
// -------------------------------------------------------------------------------------- Fade
// Positions the afterZoom element right below the zoomed image
afterZoomElement.style.top =
ABSOLUTE + IMAGE_HEIGHT_MAX / 2 + HEIGHT / 2 + "px";
</script>
My code contains five images, four of which are thumbnails,Are displayed by clicking in the main img tag
The problem is, besides changing the photo I want to zoom in but Whenever the photo changes,show zoom for the same photo
my code show result zoom just for fist img and i think it is related to js code this line buti am not sure and i cannot solve it
result.style.backgroundImage = "url('" + img.src + "')";
img in state of1
result zoom div not changing
<script>
function imageZoom(imgID, resultID) {
var img, lens, result, cx, cy;
img = document.getElementById(imgID);
result = document.getElementById(resultID);
/*create lens:*/
lens = document.createElement("DIV");
lens.setAttribute("class", "img-zoom-lens");
/*insert lens:*/
img.parentElement.insertBefore(lens, img);
/*calculate the ratio between result DIV and lens:*/
cx = result.offsetWidth / lens.offsetWidth;
cy = result.offsetHeight / lens.offsetHeight;
/*set background properties for the result DIV:*/
result.style.backgroundImage = "url('" + img.src + "')";
result.style.backgroundSize = (img.width * cx) + "px " + (img.height * cy) + "px";
/*execute a function when someone moves the cursor over the image, or the lens:*/
lens.addEventListener("mousemove", moveLens);
img.addEventListener("mousemove", moveLens);
/*and also for touch screens:*/
lens.addEventListener("touchmove", moveLens);
img.addEventListener("touchmove", moveLens);
function moveLens(e) {
var pos, x, y;
/*prevent any other actions that may occur when moving over the image:*/
e.preventDefault();
/*get the cursor's x and y positions:*/
pos = getCursorPos(e);
/*calculate the position of the lens:*/
x = pos.x - (lens.offsetWidth / 2);
y = pos.y - (lens.offsetHeight / 2);
/*prevent the lens from being positioned outside the image:*/
if (x > img.width - lens.offsetWidth) {x = img.width - lens.offsetWidth;}
if (x < 0) {x = 0;}
if (y > img.height - lens.offsetHeight) {y = img.height - lens.offsetHeight;}
if (y < 0) {y = 0;}
/*set the position of the lens:*/
lens.style.left = x + "px";
lens.style.top = y + "px";
/*display what the lens "sees":*/
result.style.backgroundPosition = "-" + (x * cx) + "px -" + (y * cy) + "px";
}
function getCursorPos(e) {
var a, x = 0, y = 0;
e = e || window.event;
/*get the x and y positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x and y coordinates, relative to the image:*/
x = e.pageX - a.left;
y = e.pageY - a.top;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
y = y - window.pageYOffset;
return {x : x, y : y};
}
}
</script>
<script>
// Initiate zoom effect:
imageZoom("expandedImg", "myresult");
</script>
<script>
function myFunction(imgs) {
var expandImg = document.getElementById("expandedImg");
expandImg.src = imgs.src;
expandImg.parentElement.style.display = "block";
}
</script>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
display: none;
}
/* Expanding image text */
#imgtext {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
</style>
<style>
* {box-sizing: border-box;}
.img-zoom-container {
position: relative;
}
.img-zoom-lens {
position: absolute;
border: 1px solid #d4d4d4;
/*set the size of the lens:*/
width: 40px;
height: 40px;
}
.img-zoom-result {
border: 1px solid #d4d4d4;
/*set the size of the result div:*/
width: 300px;
height: 300px;
}
</style>
<script>
<div class="img-zoom-container">
<img id="expandedImg" src="imgs/img4.jpg" width="300" height="240">
<div id="myresult" class="img-zoom-result"></div>
</div>
<div class="row">
<div class="column">
<img id="expandedImg" src="imgs/img5.jpg" alt="Nature" style="width:100%" onclick="myFunction(this);">
</div>
<div class="column">
<img src="imgs/img4.jpg" alt="Snow" style="width:100%" onclick="myFunction(this);">
</div>
<div class="column">
<img src="imgs/img3.jpg" alt="Mountains" style="width:100%" onclick="myFunction(this);">
</div>
<div class="column">
<img src="imgs/img2.jpg" alt="Lights" style="width:100%" onclick="myFunction(this);">
</div>
</div>
i solve it after 5 min insert my question :))))
i should use this code
function myFunction(imgs) {
var expandImg = document.getElementById("expandedImg");
expandImg.src = imgs.src;
expandImg.parentElement.style.display = "block";
imageZoom("expandedImg", "myresult");
}
I am trying to expand a child element to the very top of its parent with the following code. However, the text disappears after a while of scrolling downward in the child element. How do I fix this?
function setHeight() {
var panel = document.getElementById("panel");
var container = document.getElementById("container");
var panelHeight = container.offsetHeight;
var y = panel.scrollTop;
// YOU MUST SET THE PERCENTAGE, OR A MAX HEIGHT
maxHeight = panelHeight * 0.9;
var targetHeight = Math.min(maxHeight, 0.7 * panelHeight + y);
panel.style.height = targetHeight + "px";
document.getElementById("panelContent").style.marginTop = Math.min(y, panelHeight - maxHeight) + "px";
}
document.getElementById('panel').addEventListener("scroll", setHeight);
#container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: red;
}
#panel {
position: fixed;
width: 100%;
height: 70%;
bottom: 0;
background-color: green;
overflow-y: scroll;
}
<div id="container">
Scroll up to here
<div id="panel">
<div id="panelContent">
As user scroll downs here in this div, expand this div to the top but only as much as the user has scrolled down: asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdassdasdasdasdasdasd
</div>
</div>
</div>
https://jsfiddle.net/1ekpx3sd/
I've been editing this JS image compare example, and everything is great. I just don't know how to change one thing.
The circle button that indicates where the user should drag the image overflows out of the container when its pulled left or right. I'm talking about this: https://prnt.sc/ja1r6g
How can I fix that and make it so that when it's pulled all the way to the right or left, it goes below the image and doesn't show the overflow?
Here's the snipped of the code:
function initComparisons() {
var x, i;
/*find all elements with an "overlay" class:*/
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/*once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function:*/
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0, w, h;
/*get the width and height of the img element*/
w = img.offsetWidth;
h = img.offsetHeight;
/*set the width of the img element to 50%:*/
img.style.width = (w / 2) + "px";
/*create slider:*/
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/*insert slider*/
img.parentElement.insertBefore(slider, img);
/*position the slider in the middle:*/
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/*execute a function when the mouse button is pressed:*/
slider.addEventListener("mousedown", slideReady);
/*and another function when the mouse button is released:*/
window.addEventListener("mouseup", slideFinish);
/*or touched (for touch screens:*/
slider.addEventListener("touchstart", slideReady);
/*and released (for touch screens:*/
window.addEventListener("touchstop", slideFinish);
function slideReady(e) {
/*prevent any other actions that may occur when moving over the image:*/
e.preventDefault();
/*the slider is now clicked and ready to move:*/
clicked = 1;
/*execute a function when the slider is moved:*/
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/*the slider is no longer clicked:*/
clicked = 0;
}
function slideMove(e) {
var pos;
/*if the slider is no longer clicked, exit this function:*/
if (clicked == 0) return false;
/*get the cursor's x position:*/
pos = getCursorPos(e)
/*prevent the slider from being positioned outside the image:*/
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/*execute a function that will resize the overlay image according to the cursor:*/
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/*get the x positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x coordinate, relative to the image:*/
x = e.pageX - a.left;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/*resize the image:*/
img.style.width = x + "px";
/*position the slider:*/
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
initComparisons();
* {box-sizing: border-box;}
.img-comp-container {
position: relative;
height: 200px; /*should be the same height as the images*/
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow:hidden;
}
.img-comp-img img {
display:block;
vertical-align:middle;
}
.img-comp-slider {
position: absolute;
z-index:9;
cursor: ew-resize;
/*set the appearance of the slider:*/
width: 40px;
height: 40px;
background-color: #2196F3;
opacity: 0.7;
border-radius: 50%;
}
<h1>Compare Two Images</h1>
<p>Click and slide the blue slider to compare two images:</p>
<div class="img-comp-container">
<div class="img-comp-img">
<img src="https://placeimg.com/640/480/animals" width="300" height="200">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="https://placeimg.com/640/480/animals?t=1524676145713" width="300" height="200">
</div>
</div>
EDIT: If I just add another div to wrap it all in and add overflow: hidden, it doesn't actually DO anything.
So I've got a solution. Pretty simple one. But you must know the width of your .img-comp-container. And of course overflow: hidden; is there as well
The problem is, that overflow: hidden; works as it should. But since your .img-comp-container is a block style element it spans the whole width of your webpage (or its parent container). Therefore to enforce the overflow not just vertically but also horizontally, you have to limit the width of that div to "hide" it properly
function initComparisons() {
var x, i;
/*find all elements with an "overlay" class:*/
x = document.getElementsByClassName("img-comp-overlay");
for (i = 0; i < x.length; i++) {
/*once for each "overlay" element:
pass the "overlay" element as a parameter when executing the compareImages function:*/
compareImages(x[i]);
}
function compareImages(img) {
var slider, img, clicked = 0,
w, h;
/*get the width and height of the img element*/
w = img.offsetWidth;
h = img.offsetHeight;
/*set the width of the img element to 50%:*/
img.style.width = (w / 2) + "px";
/*create slider:*/
slider = document.createElement("DIV");
slider.setAttribute("class", "img-comp-slider");
/*insert slider*/
img.parentElement.insertBefore(slider, img);
/*position the slider in the middle:*/
slider.style.top = (h / 2) - (slider.offsetHeight / 2) + "px";
slider.style.left = (w / 2) - (slider.offsetWidth / 2) + "px";
/*execute a function when the mouse button is pressed:*/
slider.addEventListener("mousedown", slideReady);
/*and another function when the mouse button is released:*/
window.addEventListener("mouseup", slideFinish);
/*or touched (for touch screens:*/
slider.addEventListener("touchstart", slideReady);
/*and released (for touch screens:*/
window.addEventListener("touchstop", slideFinish);
function slideReady(e) {
/*prevent any other actions that may occur when moving over the image:*/
e.preventDefault();
/*the slider is now clicked and ready to move:*/
clicked = 1;
/*execute a function when the slider is moved:*/
window.addEventListener("mousemove", slideMove);
window.addEventListener("touchmove", slideMove);
}
function slideFinish() {
/*the slider is no longer clicked:*/
clicked = 0;
}
function slideMove(e) {
var pos;
/*if the slider is no longer clicked, exit this function:*/
if (clicked == 0) return false;
/*get the cursor's x position:*/
pos = getCursorPos(e)
/*prevent the slider from being positioned outside the image:*/
if (pos < 0) pos = 0;
if (pos > w) pos = w;
/*execute a function that will resize the overlay image according to the cursor:*/
slide(pos);
}
function getCursorPos(e) {
var a, x = 0;
e = e || window.event;
/*get the x positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x coordinate, relative to the image:*/
x = e.pageX - a.left;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
return x;
}
function slide(x) {
/*resize the image:*/
img.style.width = x + "px";
/*position the slider:*/
slider.style.left = img.offsetWidth - (slider.offsetWidth / 2) + "px";
}
}
}
initComparisons();
* {
box-sizing: border-box;
}
.img-comp-container {
position: relative;
height: 200px;
/*should be the same height as the images*/
/* Overflow must be here, and helping it up with width */
width: 300px;
overflow: hidden;
}
.img-comp-img {
position: absolute;
width: auto;
height: auto;
overflow: hidden;
}
.img-comp-img img {
display: block;
vertical-align: middle;
}
.img-comp-slider {
position: absolute;
z-index: 9;
cursor: ew-resize;
/*set the appearance of the slider:*/
width: 40px;
height: 40px;
background-color: #2196F3;
opacity: 0.7;
border-radius: 50%;
}
<h1>Compare Two Images</h1>
<p>Click and slide the blue slider to compare two images:</p>
<div class="img-comp-container">
<div class="img-comp-img">
<img src="https://placeimg.com/640/480/animals" width="300" height="200">
</div>
<div class="img-comp-img img-comp-overlay">
<img src="https://placeimg.com/640/480/animals?t=1524676145713" width="300" height="200">
</div>
</div>
I am trying to use drag and drop to move pictures from one <div> to another.
Currently, I can move the pictures anywhere in the destination <div>, but what I really want is that the pictures snap together when dropped. Ideally, they would be able to snap together on any side (not just, for example, on the bottom or on the right).
I've tried a few different things (including using <canvas>) and it didn't work.
This is what I have so far:
var clone;
var offsetx = null;
var offsety = null;
var isClone = false;
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
offsetx = ev.target.offsetLeft - event.clientX;
offsety = ev.target.offsetTop - event.clientY;
ev.dataTransfer.setData("text", ev.target.id);
}
function dropTrash(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var remove = document.getElementById(data);
remove.parentNode.removeChild(remove);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
}
function dropClone(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var num = Math.random() * (1000 - 1) + 1;
isClone = true;
clone = document.getElementById(data).cloneNode(true);
clone.id = "newId" + num.toString();
clone.style.position = "absolute";
clone.style.left = (event.clientX+offsetx)+"px";
clone.style.top = (event.clientY+offsety)+"px";
ev.target.appendChild(clone);
}
html, body {
height: 100%;
padding: 0;
margin: 0;
}
div {
width: 50%;
height: 50%;
float: left;
}
#div1 {
background: #DDD;
}
#div2 {
background: #AAA;
}
#div3 {
background: #777;
}
#div4 {
background: #444;
}
#imgDiv {
width: 611px;
height: 324px;
border: 5px solid #DDD;
}
<div id="div1">
</div>
<div id="div2">
</div>
<div id="div3" ondrop="dropTrash(event)" ondragover="allowDrop(event)">
<img id="drag1" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Bartagame_fcm.jpg/1200px-Bartagame_fcm.jpg" draggable="true" ondragstart="drag(event)" width="105" height="105">
<img id="drag2" src="http://www.earthtimes.org/newsimage/lizard_Ngo_Van_Tri_big_281.jpg" draggable="true" ondragstart="drag(event)" width="105" height="105">
</div>
<div id="div4">
<div align="center" id="imgDiv" ondrop="dropClone(event)" ondragover="allowDrop(event)"></div>
</div>
When you start dragging an image, you need to store the position of the cursor, relative to that particular image.
There are multiple position properties in the MouseEvent that will help you calculate that, but if browser support is not an issue, I would go for MouseEvent.offsetX and MouseEvent.offsetY. From the docs:
The offsetX/offsetY read-only property of the MouseEvent interface provides the offset in the X/Y coordinate of the mouse pointer between that event and the padding edge of the target node.
So, on dragstart, you will do just:
x = e.offsetX;
y = e.offsetY;
Then, when you drop the image in your, let's call it canvas (note the italics as it is not a <canvas> element, but any other element that you use as your drop zone, a <div> in this particular example), you need to know the position of the cursor relative to that canvas, so you may think you could use offsetX and offsetY again, and your are partially right. That would give you the expected value if you drop the image on the canvas itself, but there may be other images in it already, and you may drop the current one on top of another one, getting the offsetX and offsetY relative to that one instead.
What you can do is use MouseEvent.pageX and MouseEvent.pageY and, from that value, subtract the position of the (upper-left corner) of that canvas element, which you can get from HTMLElement.offsetLeft and HTMLElement.offsetTop:
e.pageX - imageCanvas.offsetLeft;
e.pageY - imageCanvas.offsetTop;
With this you will get the position of the cursor relative to the canvas element.
Now, you need to subtract the x and y values that you stored on dragstart, and that will give you the left and top values of the upper-left corner of the dragged image, relative to the canvas element:
image.style.left = (e.pageX - imagesCanvas.offsetLeft - x) + 'px';
image.style.top = (e.pageY - imagesCanvas.offsetTop - y) + 'px';
All together it will look like this:
let x;
let y;
let currentTarget = null;
let cloneElement = false;
function startDrag(e, clone) {
const target = e.target;
if (target.tagName === 'IMG') {
x = e.offsetX;
y = e.offsetY;
currentTarget = target;
cloneElement = clone;
}
}
function cloneImage(e) {
startDrag(e, true);
}
function moveImage(e) {
startDrag(e, false);
}
function removeImage(e) {
if (!cloneElement) {
currentTarget.remove();
}
}
function stickImage(e) {
const image = cloneElement ? currentTarget.cloneNode(true) : currentTarget;
imagesCanvas.appendChild(image);
// + 1 for the border
image.style.left = (e.pageX - imagesCanvas.offsetLeft - x + 1) + 'px';
image.style.top = (e.pageY - imagesCanvas.offsetTop - y + 1) + 'px';
currentTarget = null;
}
function allowDrag(e) {
e.preventDefault();
}
// Bind event listeners:
const imagesBarElement = document.getElementById('imagesBar');
const imagesCanvasElement = document.getElementById('imagesCanvas');
document.addEventListener('dragenter', allowDrag);
document.addEventListener('dragover', allowDrag);
imagesBarElement.addEventListener('dragstart', cloneImage);
imagesBarElement.addEventListener('drop', removeImage);
imagesCanvasElement.addEventListener('dragstart', moveImage);
imagesCanvasElement.addEventListener('drop', stickImage);
body {
margin: 0;
font-size: 0;
display: flex;
flex-direction: column;
height: 100vh;
user-select: none;
}
img {
width: 100px;
height: 100px;
}
#imagesBar {
height: 100px;
border-bottom: 1px solid #CCC;
padding: 10px 0;
}
#imagesBar > img {
margin: 0 0 0 10px;
}
#imagesCanvas {
position: relative;
background: #EEE;
flex-grow: 1;
overflow: hidden;
}
#imagesCanvas > img {
position: absolute;
}
<div id="imagesBar">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Bartagame_fcm.jpg/1200px-Bartagame_fcm.jpg" draggable="true">
<img src="http://www.earthtimes.org/newsimage/lizard_Ngo_Van_Tri_big_281.jpg" draggable="true">
</div>
<div id="imagesCanvas"></div>