Here's the jsfiddle.
It's the interface to cropping an image. As you can see the selection div takes the same background image and positions it to the negative of the top and left attributes of the selection div. In theory this should give a perfect overlap, but there's a jitter as you move the selection div around, and I can't seem to figure out what is causing it.
html
<div id="main">
<div id="selection"></div>
</div>
css
#main {
width: 600px;
height: 450px;
position: relative;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
background-size: contain;
}
#selection {
width: 100px;
height: 100px;
position: absolute;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
border: 1px dotted white;
background-size: 600px 450px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
selection.css("background-position", (((-selection.position().left) - 1) + "px " + ((-selection.position().top ) - 1) + "px"));
}
});
$("#selection").mouseup(function (e) {
move = false;
});
})
It would appear that there is a value of 5 offset that needs to be added to ensure seamlessness
DEMO http://jsfiddle.net/nzx0fcp5/2/
offset = [e.pageX - selection.offset().left + 5, e.pageY - selection.offset().top + 5];
So, while experimenting I discovered that this was only a problem at certain sizes of the image. At the original size it is no problem, neither at half nor a quarter of this size. It wasn't simply a matter of keeping the image in proportion not having the image square or using even pixel sizes. I'm assuming this had something to do with partial pixel sizes, but I'm not sure, and I couldn't see any way to work around this, at least none that seemed worth the effort.
So while checking out the code of other croppers I took a look at POF's image cropper, they seem to have got round the problem by not using the background-position property at all (I'm not sure if it's plugin or they coded it themselves). They just set the image down and then used a transparent selection div with 4 divs stuck to each edge for the shading. So there's no pixel crunching on the fly at all. I like the simplicity and lightweight nature of this design and knocked up a version myself in jsfiddle to see if I could get it to work well.
new jitter free jsfiddle with no pixel crunching
I liked the solution for the preview box as well.
html
<body>
<div id="main">
<img src="http://flavorwire.files.wordpress.com/2012/01/scarlett_johansson.jpg" />
<div id="upperShade" class="shade" > </div>
<div id="leftShade" class="shade" > </div>
<div id="selection"></div>
<div id="rightShade" class="shade"></div>
<div id="lowerShade" class="shade" ></div>
</div>
</body>
css
#main {
position:relative;
width: 450px;
height: 600px;
}
#selection {
width: 148px;
height: 148px;
position: absolute;
border: 1px dotted white;
top: 0px;
left: 0px;
z-index: 1;
}
.shade {
background-color: black;
opacity: 0.5;
position: absolute;
}
#upperShade {
top: 0px;
left: 0px;
width: 600px;
}
#leftShade {
left: 0px;
top: 0px;
height: 150px;
width: auto;
}
#rightShade {
left: 150px;
top: 0px;
height: 150px;
width: 450px;
}
#lowerShade {
left:0px;
top: 150px;
width: 600px;
height: 300px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
setShade();
}
});
function setShade() {
$("#upperShade").css("height", selection.position().top);
$("#lowerShade").css("height", 600 - (selection.position().top + 150));
$("#lowerShade").css("top", selection.position().top + 150);
$("#leftShade").css("top", selection.position().top);
$("#leftShade").css("width", selection.position().left);
$("#rightShade").css("top", selection.position().top);
$("#rightShade").css("left", selection.position().left + 150);
$("#rightShade").css("width", 450 - selection.position().left);
}
$("#selection").mouseup(function (e) {
move = false;
});
});
Related
I need to increase height actually to increase bottom and top of div each for 25px also left and right side each for 25px.I don't now is that even possible.
So this is just example but it is similar to my code:
function increaseDiv() {
var myDiv = document.querySelector(".box")
var currWidth = myDiv.clientWidth;
myDiv.style.width = currWidth + 100 + "px";
}
.box {
width: 300px;
height: 200px;
position: absolute;
left: 100px;
background: black;
}
<div class="box"></div>
<button onclick="increaseDiv()">Click</button>
Here is demo https://jsfiddle.net/SutonJ/0pdwm39a/14/
The problem is that position of your div are related to left side and this is why it looks like you increase only the right side; try to add positioning with transform by center or make it by flex(align-items + justify-content)
.box {
width: 300px;
height: 200px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
background: black;
}
If I am understanding you correctly, I think if you changed
var currWidth = myDiv.clientWidth;
myDiv.style.width = currWidth + 100 + "px";
to
var currWidth = myDiv.getBoundingClientRect().width;
myDiv.style.width = currWidth + 50 + "px";
and also added
var currHeight = myDiv.getBoundingClientRect().height;
myDiv.style.height = currHeight + 50 + "px";
I also noticed that your div is using absolute positioning, so you may also need to offset the left and top according to the size change. If you are getting an issue with the actual position when the size changes let me know.
What about CSS scale?
That will keep the actual position of the element and expand it in all directions, unless you specify a transform-origin value.
Edited with an ever growing effect...
let myDiv = document.querySelector(".box");
let orgiSize = myDiv.getBoundingClientRect().width;
let increments = 0;
function increaseDiv() {
increments += 50; // That is 25px on both sides...
// Make the math here
var percentage = Math.floor((orgiSize + increments) / orgiSize * 100) / 100
console.log(percentage);
myDiv.style.transform = `scale(${percentage})`; // That is a percentage value
}
.box {
width: 300px;
height: 200px;
position: absolute;
left: 100px;
background: black;
}
/* for the demo */
button {
position: absolute;
z-index: 9999;
}
<div class="box"></div>
<button onclick="increaseDiv()">Click</button>
I am making a div resizer and cannot use any plugin as I need to customize many things on it's basis. I have achieved the task to resize the div from right side. In this I am manipulating the drag and calculating the units accordingly.
This script works fine if I keep the drag limited to right side.
But now my task is to resize it on both ends. I understand that some technique would be applied.
One technique I am trying to apply is the half the div and notice the distance from that center point e.g if the center is 200px and the mouse is at 10px then we can start decreasing the div from right and vice-versa.
var handle, measurement, isResizing;
var pageWidth = $(window).width();
var maxUnit = 300;
var minUnit = 50;
var maxLimit;
var adjustment = 0;
var container;
function calculateUnit(maxUnit, maxLimit, currentWidth) {
var offset = maxLimit - currentWidth;
return Math.ceil(maxUnit - offset);
}
function adjustContainer(innerContainerWidth, widthDiff, heightDiff) {
handle.css({
'width': (innerContainerWidth - widthDiff) + 'px',
'left': (widthDiff / 2) + 'px',
'top': (heightDiff / 2) + 'px'
});
}
function InitSizeCalculator() {
container = $("#topDrag");
console.log('height c', container.height());
//console.log('width c', container.width());
handle = $('#drag'), measurement = document.getElementById('measurement'), isResizing = false;
var heightDiff = container.height() - 170;
var widthDiff = container.width() - handle.width();
console.log('height c', heightDiff);
//maxLimit = (pageWidth <= 720) ? (pageWidth - 20) : (pageWidth - (pageWidth / 3)) - 60;
maxLimit = container.width();
adjustContainer(handle.width(), widthDiff, heightDiff);
//handle.css('width', maxLimit);
measurement.innerHTML = maxUnit + ' m';
}
InitSizeCalculator(); //initialize the variable first
handle.on('mousedown touchstart', function(e) {
isResizing = true;
lastDownX = e.clientX;
});
$(document).on('mousemove touchmove', function(e) {
var currentWidth = e.clientX - adjustment;
console.log(e.clientX);
// we don't want to do anything if we aren't resizing.
var unit = calculateUnit(maxUnit, maxLimit, currentWidth);
if (!isResizing || unit < minUnit || e.clientX > maxLimit)
return;
handle.css('width', currentWidth);
measurement.innerHTML = unit + ' cm';
})
.on('mouseup touchend', function(e) {
// stop resizing
isResizing = false;
});
//start
.imgContainer-p {
position: relative !important;
border-right: black 1px dashed;
border-left: black 1px dashed;
cursor: w-resize;
height: 220px
}
#drag {
position: absolute;
/*right: 500px;*/
top: 0;
bottom: 0;
/*width: 500px;*/
}
.imgWinder {
position: absolute;
top: 0;
left: 0;
width: 100%;
/*height: 200px;*/
height: 90%;
}
.imgPaper {
position: relative;
top: 0;
left: 0;
width: 100%;
/*height: 200px;*/
height: 90%;
}
.measurment-p {
width: 100%;
height: 20px;
border-bottom: 1px dashed black;
border-left: 1px dashed black;
border-right: 0px dashed black;
padding-top: 10px;
text-align: center;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-9 col-sm-12" id="topDrag">
<div class="imgContainer-p" id="drag">
<img id="imgWinder" class="imgWinder" draggable="false" src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Cylinder_geometry_rotated.svg/2000px-Cylinder_geometry_rotated.svg.png" />
<div style="width: 100%; height: 20px; border-bottom: 1px dashed black; border-left: 1px dashed black; border-right: 0px dashed black; padding-top: 10px; text-align: center">
<span style="background-color: #FFFFFF; padding: 0 10px;">
<span class="label label-default">Size</span>
<span class="label label-warning" id="measurement">01</span>
<!--Padding is optional-->
</span>
</div>
</div>
</div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
When you drag an element from the right side to expand it, you're effectively updating the the right position of the element by adding the number of pixels covered in the drag action to its width.
This is how elements behave in a browser - left to right and hence similar to increasing width using CSS. But when you drag the opposite side of it, meaning the left hand side, the browser doesn't know how to handle this.
Now since you're resizing an element to the left hand side, you have space there, and the left edge of the element moves to a new position in that space, but you can't add width to the left. So, you have to give an illusion of it being added to the left hand side, by maintaining the right edge at its current position.
When you drag the element's left edge towards the left, calculate the difference between its old left position and its new left position, and add it to the width of the element. This will make sure the width expands to fit the new displacement.
When you drag the left edge towards the right side, to shrink the element, do the same procedure, except reduce it from the total width instead of adding it.
When you drag the right side towards the left, hence reducing the resize, calculate the difference and reduce it from the width.
This should help you with the code:
Adjust a div's height/width by dragging its left/top border without jQuery draggable?
I have a div that animates up and down which works fine. The issue I'm getting is that every time the page loads the div starts at the very top of the page and then jumps down to where it needs to be after the animation starts.
<body id="body">
<div id="square"></div>
</body>
#body {
background: #000;
}
#square {
background-color: #fff;
margin: 0 auto;
position: relative;
width: 100px;
height: 100px;
}
var box = document.getElementById('square');
TOP = (window.innerHeight - box.offsetHeight)/2;
box.style.top = TOP;
var down = setInterval(animateDown, 15);
var up;
function animateDown()
{
TOP += 3;
box.style.top = TOP + 'px';
if(TOP > 900){
clearInterval(down);
up = setInterval(animateUp, 15);
}
}
function animateUp()
{
TOP -= 3;
box.style.top = TOP + 'px';
if(TOP <= (window.innerHeight - box.offsetHeight)/2){
clearInterval(up);
down = setInterval(animateDown, 15);
}
}
Here is a link to the jsfiddle as well >> https://jsfiddle.net/xgilmore/pLbgvc3L/
thanks in advance
This is sort of a work around, but you can start the box off as hidden, and then once you start animating, set it visible. https://jsfiddle.net/pLbgvc3L/1/
function animateDown()
{
box.style.visibility = 'visible';
#square {
background-color: #fff;
//margin: 0 auto;
position: relative;
width: 100px;
height: 100px;
top: 20%;
visibility: hidden;
}
Oh sorry, I actually know what is going on, it just took a second look to figure it out. top: 20% doesn't do anything because percentages only work if the parent element (body) has an explicit height. Like so https://jsfiddle.net/pLbgvc3L/2/
What I want:
| A | | B | | C |
^ ^
When you move the handles left and right A, B, and C resize accordingly
| A | | B | | C |
What I have is the || between B and C sliding, but not resizing B and all I get on the other one is the resize cursor. Basically C is a curtain and covers A and B. I did get min size working for C.
| A | C |
I broke somebody else's perfectly good code to get this far:
var isResizing = false,
who='',
lastDownX = 0;
$(function () {
var container = $('#container'),
left = $('#left'),
right = $('#right'),
middle = $('#middle'),
hand2 = $('#hand2'),
handle = $('#handle');
handle.on('mousedown', function (e) {
isResizing = true;
who=e.target.id;
lastDownX = e.clientX;
});
$(document).on('mousemove', function (e) {
var temp, min;
// we don't want to do anything if we aren't resizing.
if (!isResizing)
return;
min=container.width() * 0.1;
temp = container.width() - (e.clientX - container.offset().left);
if (temp < min)
temp = min;
if (who == 'handle')
right.css('width', temp);
if (who == 'hand2')
left.css('width', temp);
}).on('mouseup', function (e) {
// stop resizing
isResizing = false;
});
});
body, html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
/* Disable selection so it doesn't get annoying when dragging. */
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: moz-none;
-ms-user-select: none;
user-select: none;
}
#container #left {
width: 40%;
height: 100%;
float: left;
background: red;
}
#container #middle {
margin-left: 40%;
height: 100%;
background: green;
}
#container #right {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 200px;
background: rgba(0, 0, 255, 0.90);
}
#container #handle {
position: absolute;
left: -4px;
top: 0;
bottom: 0;
width: 80px;
cursor: w-resize;
}
#container #hand2 {
position: absolute;
left: 39%;
top: 0;
bottom: 0;
width: 80px;
cursor: w-resize;
}
<div id="container">
<!-- Left side -->
<div id="left"> This is the left side's content!</div>
<!-- middle -->
<div id="middle">
<div id="hand2"></div> This is the middle content!
</div>
<!-- Right side -->
<div id="right">
<!-- Actual resize handle -->
<div id="handle"></div> This is the right side's content!
</div>
</div>
Been playing with it here: https://jsfiddle.net/ju9zb1he/5/
I was looking for a solution that required less extensive CSS. It does have one minor bug(FIXED), but hopefully this should get you started. Here is a DEMO.
Also I aimed to use DOM Traversal methods like .next() and .prev() that way it wouldn't be so attribute dependent, and would be easily reusable if you needed a feature like this multiple times on a page.
Edit - Further Explanation
The idea here is onClick of a .handle we want to gather the total width (var tWidth) of the .prev() and .next() divs relative to the .handle in the DOM. We can then use the start mouse position (var sPos) to substract the amount of pixels we've moved our mouse (e.pageX). Doing so gives us the correct width that the .prev() div should have on mousemove. To get the width of the .next() div we need only to subtract the width of the .prev() div from the total width (var tWidth) that we stored onClick of the .handle. Hope this helps! Let me know if you have any further questions, however I will likely be unavailable till tomorrow.
HTML
<div class="container">
<div id="left"></div>
<div id="l-handle" class="handle"></div>
<div id="middle"></div>
<div id="r-handle" class="handle"></div>
<div id="right"></div>
</div>
CSS
#left, #middle, #right {
display: inline-block;
background: #e5e5e5;
min-height: 200px;
margin: 0px;
}
#l-handle, #r-handle {
display: inline-block;
background: #000;
width: 2px;
min-height: 200px;
cursor: col-resize;
margin: 0px;
}
jQuery
var isDragging = false,
cWidth = $('.container').width(),
sPos,
handle,
tWidth;
$('#left, #middle, #right').width((cWidth / 3) - 7); // Set the initial width of content sections
$('.handle').on('mousedown', function(e){
isDragging = true;
sPos = e.pageX;
handle = $(this);
tWidth = handle.prev().width() + handle.next().width();
});
$(window).on('mouseup', function(e){
isDragging = false;
});
$('.container').on('mousemove', function(e){
if(isDragging){ // Added an additional condition here below
var cPos = sPos - e.pageX;
handle.prev().width((tWidth / 2) - cPos); // This was part of the bug...
handle.next().width(tWidth - handle.prev().width());
// Added an update to sPos here below
}
});
Edit
The bug was caused by 2 things.
1) On mousemove we were dividing the total width by two, instead of an updated mouse offset.
2) The sPos was not updating on mousemove, and stayed a static number based off of the click location.
Resolution
Update the sPos on mousemove that way the mouse offset is accurately based off of the previous mousemove position, rather than the click position. When this is done we can then subtract the .next() div's width from the total width. Then we subtract our current mouse position from the remaining width. The fiddle has been updated as well.
$('.container').on('mousemove', function(e){
var cPos = sPos - e.pageX;
if(isDragging && ((tWidth - handle.next().width()) - cPos) <= tWidth){
handle.prev().width((tWidth - handle.next().width()) - cPos);
handle.next().width(tWidth - handle.prev().width());
sPos = e.pageX;
}
});
Edit
Added an additional condition on mousemove to prevent the drag from exceeding the total width (var tWidth).
Can you please explain what you're trying to accomplish?
I don't believe you need to use position: absolute. The premise of absolute positioning is to override the margin and padding imposed on an element by its parent.
You don't need to do this, all elements have relative positioning by default which makes them push eachother around and don't allow overlapping.
I'm probably missing something, but I think this is what you want with nothing but some very basic CSS: http://jsfiddle.net/3bdoazpk/
<div class='first'>
asdf
</div><div class='second'>
dasdf
</div><div class='third'>
sadf
</div>
body {
margin: 0;
}
div {
display: inline-block;
height: 100%;
}
.first, .third {
width: 40%;
}
.first {
background-color: red;
}
.second {
background-color: blue;
width: 20%;
}
.third {
background-color: green;
}
I have 2 <div>s with ids A and B. div A has a fixed width, which is taken as a sidebar.
The layout looks like diagram below:
The styling is like below:
html, body {
margin: 0;
padding: 0;
border: 0;
}
#A, #B {
position: absolute;
}
#A {
top: 0px;
width: 200px;
bottom: 0px;
}
#B {
top: 0px;
left: 200px;
right: 0;
bottom: 0px;
}
I have <a id="toggle">toggle</a> which acts as a toggle button. On the toggle button click, the sidebar may hide to the left and div B should stretch to fill the empty space. On second click, the sidebar may reappear to the previous position and div B should shrink back to the previous width.
How can I get this done using jQuery?
$('button').toggle(
function() {
$('#B').css('left', '0')
}, function() {
$('#B').css('left', '200px')
})
Check working example at http://jsfiddle.net/hThGb/1/
You can also see any animated version at http://jsfiddle.net/hThGb/2/
See this fiddle for a preview and check the documentation for jquerys toggle and animate methods.
$('#toggle').toggle(function(){
$('#A').animate({width:0});
$('#B').animate({left:0});
},function(){
$('#A').animate({width:200});
$('#B').animate({left:200});
});
Basically you animate on the properties that sets the layout.
A more advanced version:
$('#toggle').toggle(function(){
$('#A').stop(true).animate({width:0});
$('#B').stop(true).animate({left:0});
},function(){
$('#A').stop(true).animate({width:200});
$('#B').stop(true).animate({left:200});
})
This stops the previous animation, clears animation queue and begins the new animation.
You can visit w3school for the solution on this the link is here and there is another example also available that might surely help,
Take a look
The following will work with new versions of jQuery.
$(window).on('load', function(){
var toggle = false;
$('button').click(function() {
toggle = !toggle;
if(toggle){
$('#B').animate({left: 0});
}
else{
$('#B').animate({left: 200});
}
});
});
Using Javascript
var side = document.querySelector("#side");
var main = document.querySelector("#main");
var togg = document.querySelector("#toogle");
var width = window.innerWidth;
window.document.addEventListener("click", function() {
if (side.clientWidth == 0) {
// alert(side.clientWidth);
side.style.width = "200px";
main.style.marginLeft = "200px";
main.style.width = (width - 200) + "px";
togg.innerHTML = "Min";
} else {
// alert(side.clientWidth);
side.style.width = "0";
main.style.marginLeft = "0";
main.style.width = width + "px";
togg.innerHTML = "Max";
}
}, false);
button {
width: 100px;
position: relative;
display: block;
}
div {
position: absolute;
left: 0;
border: 3px solid #73AD21;
display: inline-block;
transition: 0.5s;
}
#side {
left: 0;
width: 0px;
background-color: red;
}
#main {
width: 100%;
background-color: white;
}
<button id="toogle">Max</button>
<div id="side">Sidebar</div>
<div id="main">Main</div>
$('#toggle').click(function() {
$('#B').toggleClass('extended-panel');
$('#A').toggle(/** specify a time here for an animation */);
});
and in the CSS:
.extended-panel {
left: 0px !important;
}
$(document).ready(function () {
$(".trigger").click(function () {
$("#sidebar").toggle("fast");
$("#sidebar").toggleClass("active");
return false;
});
});
<div>
<a class="trigger" href="#">
<img id="icon-menu" alt='menu' height='50' src="Images/Push Pin.png" width='50' />
</a>
</div>
<div id="sidebar">
</div>
Instead #sidebar give the id of ur div.
This help to hide and show the sidebar, and the content take place of the empty space left by the sidebar.
<div id="A">Sidebar</div>
<div id="B"><button>toggle</button>
Content here: Bla, bla, bla
</div>
//Toggle Hide/Show sidebar slowy
$(document).ready(function(){
$('#B').click(function(e) {
e.preventDefault();
$('#A').toggle('slow');
$('#B').toggleClass('extended-panel');
});
});
html, body {
margin: 0;
padding: 0;
border: 0;
}
#A, #B {
position: absolute;
}
#A {
top: 0px;
width: 200px;
bottom: 0px;
background:orange;
}
#B {
top: 0px;
left: 200px;
right: 0;
bottom: 0px;
background:green;
}
/* makes the content take place of the SIDEBAR
which is empty when is hided */
.extended-panel {
left: 0px !important;
}