My scenario : Container (div) with some objects (div). The objects can be moved inside the container (with the option containment set to parent).
Now i need to move multiple objects at once. To do this i found this useful plugin. Unfortunately this plugin does not handle the property containment, as reported here.
My test on JSFiddle , disable this function
$(".obj").on("drag", function(ev, ui)
To active the multiple drag, click on the objects. I was able to block the drag event.
Problem of my test:
At that point i wouldn't know how to reactivate the drag.
Note
I should probably know the direction of the drag (with start - stop events). But at this point i can't stop the drag.
My solutions
But also the K Scandrett solution is very good. It is very difficult to apply in my particular case, which has been simplified in the example.
Always using this plugin for enable the multiple drag. Each time i select multiple objects and drag them, in the dragstart event i do this (change the property containment of the object, depending on the positions of the selected objects) :
//1024 * 648 is the width of the container
$(obj).unbind("dragstart").bind("dragstart" , function(ev, ui){
var dimObjFirst = {
x : parseInt($(this).css("left")),
y : parseInt($(this).css("top"))
};
if($("blablabla > div.ui-selected").length > 1){
var minLeft = 1024,maxRight = 0,minTop = 648,maxDown = 0;
$("blablabla > div.ui-selected").each(function(){
var elem = $(this);
var dim = {
w : parseInt(elem.css("width")),
h : parseInt(elem.css("height")),
l : parseInt(elem.css("left")),
t : parseInt(elem.css("top")),
};
if(dim.l < minLeft) minLeft = dim.l;
if(dim.l + dim.w > maxRight) maxRight = dim.l + dim.w;
if(dim.t < minTop) minTop = dim.t;
if(dim.t + dim.h > maxDown) maxDown = dim.t + dim.h;
});
var offsetContainer = $(".container").offset();
$(this).draggable( "option" , "containment" , [
(dimObjFirst.x - minLeft) + parseInt(offsetContainer.left),
(dimObjFirst.y - minTop) + parseInt(offsetContainer.top),
(dimObjFirst.x + (1024 - maxRight)) + parseInt(offsetContainer.left),
(dimObjFirst.y) + (648 - maxDown) + parseInt(offsetContainer.top)
]);
}
});
$(obj).unbind("dragstop").on("dragstop", function(ev, ui) {
if($("blablabla > div.ui-selected").length > 1) {
$("blablabla > div.ui-selected").each(function(){
$(this).draggable( "option" , "containment" , "parent" );
});
}
});
And add this line of code this._setContainment(); at the start of the function _mouseDrag of the jQuery UI plugin.
Looks like a fun project so....
I implemented it with a bounding box (similar to Twisty's comment).
I figured the benefit of doing it this way is that it will then constrain all multiple selected objects to the bounds of the container.
The bounding box I've coloured so you can visualise how it works. Of course you'd likely leave it transparent in practice.
Code comments are inline, but happy to answer any questions on the code if you have them.
No plugins were used (just jQuery and jQueryUI).
var disableclick = false;
var boundingBoxTop, boundingBoxBottom, boundingBoxLeft, boundingBoxRight;
var $container = $("#container");
var containerHeight = $container.height();
var containerWidth = $container.width();
var containerTop = $container.offset().top;
var containerLeft = $container.offset().left;
// add the bounding box to the container and make it draggable
var $boundingBox = $("<div id='boundingBox' style='position:absolute;background-color:#fcf5d4'>").prependTo($container);
$boundingBox.draggable({
grid: [10, 10],
containment: "parent",
stop: function( event, ui ) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function(e){
disableclick = false;
},200);
},
});
$(".obj").click(function(e) {
if (!disableclick) {
var $objClicked = $(this);
$objClicked.toggleClass("ui-selected");
var $selectedItems = $("#container .ui-selected");
// move any items in bounding box back into container before we re-process them
$boundingBox.find('*').each(function() {
var $this = $(this);
if ($this.parent().is($boundingBox)) {
// adjust its positioning to be relative to the container
$this.css("top", ($this.offset().top - containerTop) + "px");
$this.css("left", ($this.offset().left - containerLeft) + "px");
$container.append($this); // return it to the container
}
});
// reversing co-ords to what might be expected here so that we can scale them back to what they need to be for a bounding box
boundingBoxTop = containerHeight;
boundingBoxBottom = 0;
boundingBoxLeft = containerWidth;
boundingBoxRight = 0;
// find the bounds of the smallest rectangle that will cover all the currently selected objects
$selectedItems.each(function() {
var $this = $(this);
var top = $this.offset().top - containerTop;
var bottom = $this.offset().top - containerTop + $this.height();
var left = $this.offset().left - containerLeft;
var right = $this.offset().left - containerLeft + $this.width();
boundingBoxTop = (top < boundingBoxTop) ? top : boundingBoxTop;
boundingBoxBottom = (bottom > boundingBoxBottom) ? bottom : boundingBoxBottom;
boundingBoxLeft = (left < boundingBoxLeft) ? left : boundingBoxLeft;
boundingBoxRight = (right > boundingBoxRight) ? right : boundingBoxRight;
});
// get the height and width of bounding box
var boundingBoxHeight = boundingBoxBottom -= boundingBoxTop;
var boundingBoxWidth = boundingBoxRight -= boundingBoxLeft;
if (boundingBoxBottom > 0) // will be negative when nothing is selected
{
// update the bounding box with its new position and size
$boundingBox.css("top", boundingBoxTop + "px");
$boundingBox.css("left", boundingBoxLeft + "px");
$boundingBox.css("width", boundingBoxWidth + "px");
$boundingBox.css("height", boundingBoxHeight + "px");
// add each selected item to the bounding box so we can drag the box with them in it
$selectedItems.each(function() {
var $this = $(this);
// correct the item's position to be relative to the bounding box
$this.css("top", ($this.offset().top - containerTop - boundingBoxTop) + "px");
$this.css("left", ($this.offset().left - containerLeft - boundingBoxLeft) + "px");
$boundingBox.append($this); // add item to bounding box
});
}
}
});
#container {
position: absolute;
width: 400px;
height: 150px;
background: #eee;
}
.obj {
position: absolute;
background: #ccc;
}
.ui-selected {
background: #1C90F3;
}
#obj1 {
width: 20px;
height: 20px;
left: 20px;
top: 20px;
}
#obj2 {
width: 20px;
height: 20px;
left: 100px;
top: 20px;
}
#obj3 {
width: 20px;
height: 20px;
left: 20px;
top: 100px;
}
#obj4 {
width: 20px;
height: 20px;
left: 100px;
top: 100px;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/jquery-3.2.1.min.js" />
<div style="margin-bottom:10px">
Click boxes to select/deselect multiple items.<br/>Drag to move selection.
</div>
<div id="container">
<div class="obj" id="obj1"></div>
<div class="obj" id="obj2"></div>
<div class="obj" id="obj3"></div>
<div class="obj" id="obj4"></div>
</div>
I enhance the answer by using jquery ui Selectable plugin
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Draggable - Default functionality</title>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<style>
#container {
position: absolute;
width: 400px;
height: 150px;
background: #eee;
}
.obj {
position: absolute;
background: #ccc;
}
.ui-selected,
.ui-selecting {
background: #1C90F3;
}
#obj1 {
width: 20px;
height: 20px;
left: 20px;
top: 20px;
}
#obj2 {
width: 20px;
height: 20px;
left: 100px;
top: 20px;
}
#obj3 {
width: 20px;
height: 20px;
left: 20px;
top: 100px;
}
#obj4 {
width: 20px;
height: 20px;
left: 100px;
top: 100px;
}
</style>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
</head>
<body>
<div id="container">
<div class="obj" id="obj1"></div>
<div class="obj" id="obj2"></div>
<div class="obj" id="obj3"></div>
<div class="obj" id="obj4"></div>
</div>
<script type="text/javascript">
var disableclick = false;
var boundingBoxTop, boundingBoxBottom, boundingBoxLeft, boundingBoxRight;
var $container = $("#container");
var containerHeight = $container.height();
var containerWidth = $container.width();
var containerTop = $container.offset().top;
var containerLeft = $container.offset().left;
// add the bounding box to the container and make it draggable
var $boundingBox = $("<div id='boundingBox' style='position:absolute;background-color:#fcf5d4'>").prependTo($container);
$boundingBox.draggable({
grid: [10, 10],
containment: "parent",
stop: function (event, ui) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function (e) {
disableclick = false;
}, 200);
},
});
$('.obj').draggable({
grid: [10, 10],
containment: "parent",
stop: function (event, ui) {
disableclick = true; // don't want to toggle selection when dragging
setTimeout(function (e) {
disableclick = false;
}, 200);
},
});
function selectionStarted() {
$boundingBox.find('*').each(function () {
var $this = $(this);
if ($this.parent().is($boundingBox)) {
// adjust its positioning to be relative to the container
$this.css("top", ($this.offset().top - containerTop) + "px");
$this.css("left", ($this.offset().left - containerLeft) + "px");
$this.draggable("enable");
$container.append($this); // return it to the container
}
});
$boundingBox.css("top", "0px");
$boundingBox.css("left", "0px");
$boundingBox.css("width", "0px");
$boundingBox.css("height", "0px");
}
function selectedEnded() {
var $selectedItems = $("#container .ui-selected");
// reversing co-ords to what might be expected here so that we can scale them back to what they need to be for a bounding box
boundingBoxTop = containerHeight;
boundingBoxBottom = 0;
boundingBoxLeft = containerWidth;
boundingBoxRight = 0;
// find the bounds of the smallest rectangle that will cover all the currently selected objects
$selectedItems.each(function () {
var $this = $(this);
var top = $this.offset().top - containerTop;
var bottom = $this.offset().top - containerTop + $this.height();
var left = $this.offset().left - containerLeft;
var right = $this.offset().left - containerLeft + $this.width();
boundingBoxTop = (top < boundingBoxTop) ? top : boundingBoxTop;
boundingBoxBottom = (bottom > boundingBoxBottom) ? bottom : boundingBoxBottom;
boundingBoxLeft = (left < boundingBoxLeft) ? left : boundingBoxLeft;
boundingBoxRight = (right > boundingBoxRight) ? right : boundingBoxRight;
});
// get the height and width of bounding box
var boundingBoxHeight = boundingBoxBottom -= boundingBoxTop;
var boundingBoxWidth = boundingBoxRight -= boundingBoxLeft;
if (boundingBoxBottom > 0) // will be negative when nothing is selected
{
// update the bounding box with its new position and size
$boundingBox.css("top", boundingBoxTop + "px");
$boundingBox.css("left", boundingBoxLeft + "px");
$boundingBox.css("width", boundingBoxWidth + "px");
$boundingBox.css("height", boundingBoxHeight + "px");
// add each selected item to the bounding box so we can drag the box with them in it
$selectedItems.each(function () {
var $this = $(this);
// correct the item's position to be relative to the bounding box
$this.css("top", ($this.offset().top - containerTop - boundingBoxTop) + "px");
$this.css("left", ($this.offset().left - containerLeft - boundingBoxLeft) + "px");
$this.draggable("disable");
$boundingBox.append($this); // add item to bounding box
});
}
}
</script>
<script type="text/javascript">
$("#container").selectable({
start: selectionStarted,
stop: selectedEnded
});
</script>
</body>
</html>
Related
I trying to create a map framework for some games and i have a problem with recalc position of marker. Look url to test, with wheel you can resize div with image but the dot red not come back to own position. Sorry but im new on this y trying to learn more about js and css. Thanks
$('.map-live').css('width', "928px");
$('.map-live').css('height', "928px");
$('.map-live').css('background-size', "100%");
$('.map-live').bind('mousewheel DOMMouseScroll', function(event) {
var divSize = $('.map-live').css('width');
console.log(divSize);
divSize = divSize.replace('px', '')
divSize = parseInt(divSize);
console.log("oldSize: " + divSize);
var delta_px = event.originalEvent.wheelDelta > 0 ? (divSize + (divSize * 0.15)) : (divSize - (divSize * 0.15));
console.log("NewSize: " + delta_px);
$(this).css('width', delta_px + "px");
$(this).css('height', delta_px + "px");
$(this).css('background-size', "100%");
UpdatePoints();
});
$(function() {
$("#map-live").draggable();
});
document.getElementById('map-live').addEventListener('click', printPosition)
function getPosition(e) {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
return {
x,
y
}
}
function printPosition(e) {
var position = getPosition(e);
console.log('X: ' + position.x + ' Y: ' + position.y);
var divX = parseInt($('.map-live').css('width').replace('px', ''));
var divY = parseInt($('.map-live').css('height').replace('px', ''));
var vhX = (position.x / divX) * 100;
var vhY = (position.y / divY) * 100;
console.log('vhX: ' + vhX + ' vhY: ' + vhY);
}
function UpdatePoints() {
$('.point').css('top', '2.477565353101834vh');
$('.point').css('left', '2.477565353101834vh');
$('.point').css('position', 'absolute');
}
body {
margin: 0;
overflow: hidden;
}
.map-live {
position: absolute;
left: 10px;
z-index: 9;
background-image: url(https://i.ibb.co/d2y5G1y/map.jpg);
width: 222px;
height: 222px;
transition: all 0.2s linear;
}
.point {
position: absolute;
left: 2.477565353101834vh;
top: 2.477565353101834vh;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="map-live ui-widget-content" id="map-live">
<div class="point"></div>
</div>
jsfiddle.net/f84mto52
Someone can correct me, but I believe your use of position: absolute is what is making the <div class="point"></div> stay in place.
Your UpdatePoints is setting always the same position in the div. With 'vh' you are calculating and absolute position proportional to viewport, no to parent container.
So, you are zooming the background image but the position (x, y) will be always be (x, y), positions are not zoomed. You need to recalculate which is the new position.
So you need to calculate new position.
function UpdatePoints(){
var divW = parseInt($('.map-live').css('width').replace('px',''));
var divH = parseInt($('.map-live').css('height').replace('px',''));
var topPosition = (2.477565353101834 / 928) * divH;
var leftPosition = (2.477565353101834 / 928) * divW;
$('.point').css('top', topPosition+'vh');
$('.point').css('left', leftPosition+'vh');
$('.point').css('position', 'absolute');
}
Also, instead using 'vh' I recommend to calculate the px position instead. I have added the already calculated delta_px parameter to UpdatePoints function:
<style>
.point {
position: absolute;
left: 22.99180647678502px;
top: 22.99180647678502px;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
</style>
<script>
function UpdatePoints(delta_px){
var position = (delta_px/100)*2.477565353101834;
$('.point').css('top', position+'px');
$('.point').css('left', position+'px');
$('.point').css('position', 'absolute');
}
</script>
Also, here we are calculating the top-left position of the .point element, not the position for the center. As it is a circle, it work fine, but if you use any other shape the position translation should be calculated from its center.
I recommend to do some research about how to translate elements. You can start here:
Calculating relative position of points when zoomed in and enlarged by a rectangle!
Zoom in on a point (using scale and translate)!
How do I effectively calculate zoom scale?!
I'm trying to create my own click and drag function in JavaScript without the use of jquery. I know that jquery is easy to implement, but I prefer my own code. What I have, as i click the div, then move the mouse, the div moves to the same spot and doesn't implement a "dragging" look to it. I'm not sure why this is. I want my outcome to be able to move the div over the image that way I can "crop" the image based on the div, etc. My code is:
index.js
function _(element) {
return document.getElementById(element);
}
index.css
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgb(255,255,255);
position: absolute;
}
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8"/>
<title>Image Cropping</title>
<link rel = "stylesheet" href = "index.css"/>
<script src = "index.js"></script>
</head>
<body>
<div class = "image">
<img src = "model.jpg" alt = "Model" id = "theImage"/>
<div class = "selection" id = "selection"/>
</div>
<script>
_("theImage").ondragstart = function() { return false; };
var m = _("selection");
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() {
window.removeEventListener("mousemove", move, true);
}
function mouseDown(e) {
window.addEventListener("mousemove", move, true);
}
function move(e) {
var x = m.style.left;
var y = m.style.top;
var mouseX = e.clientX;
var mouseY = e.clientY;
m.style.top += (mouseX - x) + "px";
m.style.left += (mouseY - y) + "px";
// Also tried: m.style.top = (mouseX - x) + "px";
// And : m.style.left = (mouseY - y) + "px";
}
</script>
</body>
</html>
To add the "dragging look to it", you can:
change the cursor (cursor: move;)
keep the cursor's offset relative to the mouse
For the second one, I reused a function I created for one of my projects, for which I implemented drag and drop for mobile, not wanting to use a big library:
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
Using this function, the math becomes simple:
m.style.left = (mouseX - offset.left) + "px";
m.style.top = (mouseY - offset.top) + "px";
Full demo
_("theImage").ondragstart = function () { return false; };
var m = _("selection"), offset;
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() { window.removeEventListener("mousemove", move, true); }
function mouseDown(e) {
// SAVE THE OFFSET HERE
offset = {
left: e.pageX - realOffset(m).left,
top: e.pageY - realOffset(m).top
};
window.addEventListener("mousemove", move, true);
}
function move(e) {
// REUSE THE OFFSET HERE
m.style.left = (e.pageX - offset.left) + "px";
m.style.top = (e.pageY - offset.top) + "px";
}
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
function _(element) { return document.getElementById(element); }
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgba(255,255,255,.5);
position: absolute;
cursor: move;
}
<div class="image">
<img src="http://i.imgur.com/vxkljMP.jpg" alt="Model" id="theImage" />
<div class="selection" id="selection"></div>
</div>
I'd like to know if there's a way to explore the content of a div by moving mouse? like for example having a 1000px*1000px pic inside a 500px*500px div content in overflow:hidden and being able to see the rest of the picture by putting the cursor in the right-bottom side of the div.
And if there's a way how should I proceed ?
Something nice and smooth?
jQuery(function($) {
const $mmGal = $('#mmGal'),
$mmImg = $('#mmImg'),
damp = 10; // 1 = immediate, higher number = smoother response
let X = 0, Y = 0,
mX = 0, mY = 0,
wDiff = 0, hDiff = 0,
zeno, tOut;
// Get image size after it's loaded
$mmImg.one('load', function() {
wDiff = (this.width / $mmGal.width()) - 1;
hDiff = (this.height / $mmGal.height()) - 1;
}).each(function() {
if (this.complete) $(this).trigger("load");
});
$mmGal.on({
mousemove(ev) {
mX = ev.pageX - this.offsetLeft;
mY = ev.pageY - this.offsetTop;
},
mouseenter() {
clearTimeout(tOut);
clearInterval(zeno);
zeno = setInterval(function() { // Zeno's paradox "catching delay"
X += (mX - X) / damp;
Y += (mY - Y) / damp;
// Use CSS transition
$mmImg.css({transform: `translate(${-X * wDiff}px, ${-Y * hDiff}px)`});
// If instead you want to use scroll:
// $mmGal[0].scrollTo(X * wDiff, Y * hDiff);
}, 26);
},
mouseleave() {
// Allow the image to move for some time even after mouseleave
tOut = setTimeout(function() {
clearInterval(zeno);
}, 1200);
}
});
});
#mmGal {
position: relative;
margin: 0 auto;
width: 500px;
height: 220px;
overflow: hidden;
background: #eee;
}
#mmImg {
display: block;
}
<div id="mmGal">
<img id="mmImg" src="https://i.stack.imgur.com/BfcTY.jpg">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Here's another similar approach to mousemove element in opposite direction
http://en.wikipedia.org/wiki/Zeno%27s_paradoxes
give widht and height to div wrapped for the image
here is the DEMO
on :hover add overflow: visible; to the div
This is almost what you want. See this fiddle http://jsfiddle.net/sajith/RM9wK/
HTML
<div id="container"><img src="http://farm4.staticflickr.com/3668/12858161173_8daa0b7e54_b.jpg"/></div>
CSS
#container {
width:300px;
height:300px;
overflow: hidden;
}
#container img {
position: relative;
}
Javascript
$(function() {
$( "#container" ).mousemove(function( event ) {
var width = $("#container img").width();
var height = $("#container img").height();
var divWidth = $("#container").width();
var divHeight = $("#container").height();
var xPos = (width / divWidth - 1) * event.pageX
var yPos = (height / divHeight -1) * event.pageY
$("#container img").css('left', '-'+ xPos+'px');
$("#container img").css('top', '-'+ yPos+'px');
});
});
I would use "triggers" (hot spot) ~ add some small div element and set their position as you want, now when mouse enter trigger some events....
Simple Example: jsfiddle
CSS
div.container {
position:relative;
width:100px;
height:100px;
overflow:hidden;
}
.trigger {
right:0;
bottom:0;
position:absolute;
z-index:2;
width:10px;
height:10px;
background-color:transparent;
}
HTML
<div class='container'>
<img src='http://static.adzerk.net/Advertisers/12f0cc69cd9742faa9c8ee0f7b0d210e.jpg' />
<div class='trigger'></div>
</div>
jQuery
$('.trigger').mouseenter(
function(){
$(this).parent('.container').css({
'width':'220px',
'height':'250px'
});
});
$('.container').mouseleave(
function(){
$(this).css({
'width':'100px',
'height':'100px'
});
});
I have implemented a parallax scrolling effect based on a tutorial I found. The effect works great. However, when I specify the background images, I am unable to control the y (vertical) axis. This is causing problems because I'm trying to set locations on multiple layered images.
Any thoughts on what's causing the problem?
Here is one external script:
$(document).ready(function(){
$('#nav').localScroll(800);
//.parallax(xPosition, speedFactor, outerHeight) options:
//xPosition - Horizontal position of the element
//inertia - speed to move relative to vertical scroll. Example: 0.1 is one tenth the speed of scrolling, 2 is twice the speed of scrolling
//outerHeight (true/false) - Whether or not jQuery should use it's outerHeight option to determine when a section is in the viewport
$('#mainimagewrapper').parallax("50%", 1.3);
$('#secondaryimagewrapper').parallax("50%", 0.5);
$('.image2').parallax("50%", -0.1);
$('#aboutwrapper').parallax("50%", 1.7);
$('.image4').parallax("50%", 1.5);
})
This is another external script:
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
Here is the CSS for one section:
#aboutwrapper {
background-image: url(../images/polaroid.png);
background-position: 50% 0;
background-repeat: no-repeat;
background-attachment: fixed;
color: white;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
#aboutwrapper .image4 {
background: url(../images/polaroid2.png) 50% 0 no-repeat fixed;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
.image3{
margin: 0 auto;
min-width: 970px;
overflow: auto;
width: 970px;
}
Both of these are being called to achieve the parallax scrolling. I really just want to more specifically control the background image locations. I've tried messing with the CSS background position and I've messed with the first javascript snippet as well. No luck.
just a quick shot, have you tried actually placing the images, either in a div or just using the img src tag to actually move the element rather than manipulating the y axis of a background image?
I was wondering if it is possible to set background-color with help of mouse coordinates.
What i have is:
I have a DIV-A which is draggable and some other divs which are droppable.
What i need is :
I need to highlight other divs on my page which are droppable, whenever my DIV-A passes over them. What i have is mouse coordinates, is it possible to apply css on the bases of mouse coordinates using jquery.
Something like the following may work. You will probably need to deal with window's scrollLeft and scrollTop to get it perfect. You will probably want to throttle and memoize (if the drop positions don't change) it too.
Also, some more performance can be tweaked out of it by caching offset(), only binding mousemove when needed, and by tweaking the each loop to utilize an optimized loop (e.g. for(var i=droppables.length;i>-1;){var self = droppables.eq(--i);...}).
Also note that this will only change the color of the divs when the MOUSE passes over them...not necessarily when the draggable passes over them...this makes things a little more complicate but the function below should send you in the right direction.
$(document).mousemove(function(e){
// this should be throttled...
var x = e.pageX,
y = e.pageY;
// this loop could be optimized...
$("div.droppables").each(function(){
// these vars could be memoized...
var self = $(this),
divL = self.offset().left,
divT = self.offset().top,
divR = self.width() + divL,
divB = self.height() + divT;
// if the MOUSE coords are between the droppable's coords
// change the background color
if(x >= divL && x <= divR && y >= divT && y <= divB){
self.css("background", "red");
}
else{
// reset the background color
self.css("background", "");
}
});
});
I posted a demo for you here. Basically this cycles through each droppable position, so if you have a lot of them, it could really slow down mouse movement.
Oh, and I added two variables you can adjust if you want to increase the proximity to the droppable. Adjust the xmargin and ymargin variables as desired.
CSS
.draggable { width: 90px; height: 90px; padding: 0.5em; position: relative; top: 0; left: 0; z-index: 2; }
.droppable { width: 120px; height: 120px; padding: 0.5em; position: absolute; z-index: 1; }
#drop1 { top: 150px; left: 300px; }
#drop2 { top: 400px; left: 100px; }
HTML
<div class="draggable ui-widget-content">
<p>Drag me to my target</p>
</div>
<div id="drop1" class="droppable ui-widget-header">
<p>Drop here</p>
</div>
<div id="drop2" class="droppable ui-widget-header">
<p>Drop here</p>
</div>
Script
$(function(){
var xmargin = 10,
ymargin = 10,
drag = $('.draggable'),
drop = $('.droppable'),
dgw = drag.outerWidth() + xmargin,
dgh = drag.outerHeight() + ymargin,
pos = [];
drop
.droppable({
//hoverClass: 'ui-state-active',
drop: function(event, ui) {
$(this).addClass('ui-state-highlight').find('p').html('Dropped!');
}
})
// set up droppable coordinates array (left, top, right, bottom) for each element
.each(function(i){
var dropzone = drop.eq(i);
var l = dropzone.position().left,
t = dropzone.position().top,
r = l + dropzone.outerWidth() + xmargin,
b = t + dropzone.outerHeight() + ymargin;
pos.push([l,t,r,b]);
});
drag
.draggable()
// bind to drag event, or this could be placed inside the draggable function
.bind( "drag", function(event,ui){
var l = ui.offset.left,
t = ui.offset.top;
// cycle through each droppable and compare current postion to droppable array
drop.each(function(i){
if ( ( l + dgw ) > pos[i][0] && l < pos[i][2] && ( t + dgh ) > pos[i][1] && t < pos[i][3] ) {
$(this).addClass('ui-state-active');
} else {
$(this).removeClass('ui-state-active');
}
});
});
});
Have a look at the "Visual feedback" sample over at
jQuery UI, and as gmcalab mentioned, not having IDs is not an issue if you just use a class as the selector. Sorry if I'm not reading this correctly.
Declare selector and selector2 to whatever you want...
$(selector).mousemove(function(event) {
// Set some bounds, these are arbitrary here not sure what sort of area your looking for...
var lowerXBound= 0,
upperXBound = 100,
lowerYBound = 0,
upperYBound = 100,
currentX = event.pageX,
currentY = event.pageY;
var color = currentX > lowerXBound && currentX < upperXBound && currentY > lowerYBound && currentY < upperYBound ? 'red' : 'green';
$(selector2).css('background-color', color);
});
You can use .hover() for this, so when the mouse is over the div, change it's background colour:
$("yourdiv").hover(function () {
$(this).css("background-color", "#ff0000");
},
function () {
$(this).css("background-color", "#ffffff");
});