I'd like to zoom an img with a range button in javascript. However, I don't know how to control the last value the user inputs.
This is my html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Img Zoom</title>
<link rel="stylesheet" type="text/css" href="./css/style.css" />
</head>
<body>
<div id="divImg">
<img id="img" src="./img/rose.jpg" width="200px" height="200"" />
</div>
<div >
<label for="myRangeZ">Zoom</label>
<input type="range" min="1" max="100" value="20" id="myRangeZ" onclick="jsZoom()">
</div>
</body>
<script src="./js/script.js">
</script>
</html>
and this my .js
var z, zoom;
function jsZoom() {
z = document.getElementById("myRangeZ").value;
console.log(z);
img = document.getElementById("img");
console.log(img.width);
console.log(img.height);
if (z > 20) {
zoom = 1.5;
}
else {
zoom = 0.5;
}
document.getElementById("img").style.width = (img.width * zoom) "px";
document.getElementById("img").style.height = (img.height * zoom) "px";
}
When the user goes from 20% to 100% the img is getting bigger, but if the range goes from 100% to 20% the img is not decreasing and it's still getting bigger. I can solve this issue with 2 bottons ( ) but I want it with a range button.
CodePudding user response:
The image can become bigger in size after decreasing the slider because it is set to become 1.5 larger than itself every time the slider is set to a value above 20.
To fix this, simply store the original width and height of the image in a variable so the previous resizing events don't affect additional scaling.
var z, zoom;
var originalWidth = document.getElementById("img").width;
var originalHeight = document.getElementById("img").height;
function jsZoom() {
z = document.getElementById("myRangeZ").value;
img = document.getElementById("img");
if (z > 20) {
zoom = 1.5;
}
else {
zoom = 0.5;
}
document.getElementById("img").style.width = (originalWidth * zoom) "px";
document.getElementById("img").style.height = (originalHeight * zoom) "px";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Img Zoom</title>
<link rel="stylesheet" type="text/css" href="./css/style.css" />
</head>
<body>
<div id="divImg">
<img id="img" src="https://cdn.commercev3.net/cdn.edmundsroses.com/images/popup/23703.jpg" width="200px" height="200"" />
</div>
<div >
<label for="myRangeZ">Zoom</label>
<input type="range" min="1" max="100" value="20" id="myRangeZ" onclick="jsZoom()">
</div>
</body>
<script src="./js/script.js">
</script>
</html>
CodePudding user response:
You read the width every time it changes. So you are basing the width off at that moment in time, not the time when the image was added to the page. You need to store the initial value. You can then alter the zoom code however you like to change the size based on the original dimensions.
var z, zoom;
function jsZoom() {
z = document.getElementById("myRangeZ").value;
img = document.getElementById("img");
if (!img.dataset.width) {
img.dataset.width = img.width;
img.dataset.height = img.height;
}
const width = img.dataset.width;
const height = img.dataset.height;
img.style.width = (width * z/100 width) "px";
img.style.height = (height * z/100 height) "px";
}
jsZoom();
img {
transition: 0.2s;
}
<div id="divImg">
<img id="img" src="https://placekitten.com/300/300" width="200px" height="200"" />
</div>
<div >
<label for="myRangeZ">Zoom</label>
<input type="range" min="1" max="100" value="20" id="myRangeZ" oninput="jsZoom()">
CodePudding user response:
The problem here is that your function is using the width and height from the image, which is obviously being changed by your function. The issue should be solved by saving the initial width and height and referencing those in the last two lines of your function.
These are just "by-the-ways", but I also refactored the if/else statement and moved the width and height console.log
statements to the end for the dimensions to be printed after they're updated.
var z, zoom;
var img = document.getElementById("img");
var width = img.width;
var height = img.height;
function jsZoom() {
z = document.getElementById("myRangeZ").value;
console.log(z);
zoom = z > 20 ? 1.5 : 0.5;
img.style.width = (width * zoom) "px";
console.log(img.width);
img.style.height = (height * zoom) "px";
console.log(img.height);
}
EDIT: The width and height variables should remain outside the function to prevent them from being updated by it and affecting the zoom as a result.
CodePudding user response:
Here's a simpler way:
Wrap everything in a
<form>
. You'll have complete control of all form controls within it.Place
<img>
in a block level tag. In the example the<img>
is inside a<fieldset>
which is not only a block level tag, it's also a form control.Assign the following ruleset to
<img>
:img { object-fit: contain; width: 100% }
This CSS ruleset will ensure that the
<img>
will conform to it's container (ex.<fieldset>
) and maintain aspect ratio as well.
Details are commented in example
// Bind input event on <form>
document.forms.UI.oninput = scaleFrame;
function scaleFrame(e) {
// Reference all form controls
const IO = this.elements;
/*
If the user is interacing with <input>...
...get the value of <input> and convert it into a number...
...set <fieldset> CSS transform:scale() property to the value of <input>...
...display value of <input> with <output>
*/
if (e.target.id === 'scale') {
let size = parseFloat(e.target.value);
IO.frame.style.cssText = `transform: scale(${size})`;
IO.view.value = size;
}
}
html {
font: 300 2ch/1 Consolas;
}
#frame {
width: 200px;
height: 200px;
transform-origin: top left;
}
label {
display: flex;
align-items: center;
}
img {
object-fit: contain;
width: 100%;
}
input,
output {
display: inline-block;
}
#scale {
margin-right: 1rem;
cursor: pointer;
}
<form id='UI'>
<label>
<input id='scale' type='range' min='.1' max='2.5' step='any' value='1'>
x<output id='view'>1.0</output>
</label>
<fieldset id='frame'>
<img src="https://i.ibb.co/hZj77BZ/lena01.jpg" alt="Lena Forsén (Söderberg) 1972">
</fieldset>
</form>