Before / After Javascript issue - javascript

I am working on the currently codepen to display a hair treatment results
CODEPEN
But as soon as I add it to my website, it does not work.
I made a fiddle, and seems like the following class is breaking the code (on the fiddle works fine but does not follow the mouse pointer on the movement).
.wrapper_estudio {
width: 965px;
margin: 81px auto 0px auto;
padding-top: 100px;
}
EDIT
More especifically, the margin: 81px auto 0px auto; or the width: 965px; value.
DEMO (NOT JSFIDDLE) -> Check out this Demo to see what is exactly going on. Open console and uncheck the margin (or the width) on the div wrapper_estudio. Why does it work when margin is not set?
DEMO (JS FIDDLE)
$(function(){
var isDragging = false,
slide = $('.slide'),
controls = $('.controls');
$(".container").mousedown(function() {
$('.container').mousemove(function(e) {
var elemOffset = $(this).offset(),
relX = (e.pageX / $(this).width()) * 100;
console.log(relX);
if(relX < 98){
slide.css('width',relX + '%');
controls.css('left',relX - 3 + '%');
}
isDragging = true;
$(window).unbind("mousemove");
});
})
.mouseup(function() {
var wasDragging = isDragging;
isDragging = false;
$('.container').unbind("mousemove");
});
$('.container').mouseleave(function(){
isDragging = false;
$(this).unbind("mousemove");
});
});

Your problem lies in relX = (e.pageX / $(this).width()) * 100; where e.pageX gets the x position of the mouse relative to the left edge of the document as stated in the documentation.
Now when you add the margins with css the .container acquires an offset from the left side resulting in something like in this fiddle and the slider won't work correctly as happens in your website or in the fiddle you gave.
To solve this you need to modify the x coordinate like this:
relX = ((e.pageX-elemOffset.left) / $(this).width()) * 100;
What this does is subtracting the left offset of the image container from the distance from the left edge of the document thus returning the relative position of the mouse in the element.
So your final code should look like this:
$(function(){
var isDragging = false,
slide = $('.slide'),
controls = $('.controls');
$(".container").mousedown(function() {
$('.container').mousemove(function(e) {
var elemOffset = $(this).offset(),
relX = ((e.pageX-elemOffset.left) / $(this).width()) * 100;
console.log(relX);
if(relX < 98){
slide.css('width',relX + '%');
controls.css('left',relX - 3 + '%');
}
isDragging = true;
$(window).unbind("mousemove");
});
})
.mouseup(function() {
var wasDragging = isDragging;
isDragging = false;
$('.container').unbind("mousemove");
});
$('.container').mouseleave(function(){
isDragging = false;
$(this).unbind("mousemove");
});
});
And here is the working fiddle

Related

Before/After slider HTML5 starting position

I've recently came across this before/after slider on codepen.io.
But I have a question: how can I change the position where the slider starts. The slider starts int he middle, and I don't see where in this code that is set:
function trackLocation(e) {
var rect = videoContainer.getBoundingClientRect(),
position = ((e.pageX - rect.left) / videoContainer.offsetWidth)*100;
if (position <= 100) {
videoClipper.style.width = position+"%";
clippedVideo.style.width = ((100/position)*100)+"%";
clippedVideo.style.zIndex = 3;
}
}
var videoContainer = document.getElementById("video-compare-container"),
videoClipper = document.getElementById("video-clipper"),
clippedVideo = videoClipper.getElementsByTagName("video")[0];
videoContainer.addEventListener( "mousemove", trackLocation, false);
videoContainer.addEventListener("touchstart",trackLocation,false);
videoContainer.addEventListener("touchmove",trackLocation,false);
on the bottom of the css
#video-clipper video {
width: 450%;
postion: absolute;
height: 100%;
}
https://codepen.io/anon/pen/jwMwXB

Creating a pure javascript range slider control

I managed to create a somewhat working slider control but something feels kind of off. It doesnt quite behave as a normal control should. Sometimes while sliding it gets stuck and well, you might want to see for yourself.
How would you create the slider so that it slides smoothly without interruption or the user needing the cursor exactly on the red track?
function createRange(e) {
var range = (((e.offsetX - 0) * (255 - 0)) / (200-40 - 0)) + 0;
var rounded = Math.round(range);
return rounded;
}
function colorSlider(e) {
createRange(e)
}
var dragging = false;
document.getElementById("knob").addEventListener('mousedown', function(e) {
dragging = true;
e.target.style.pointerEvents = "none"
})
window.addEventListener('mousemove', function(e) {
if (dragging) {
if (createRange(e) <= 255) {
document.getElementById("knob").style.left = e.offsetX + "px"
}
}
})
Here is a fixed version of your slider.
var dragging = false;
var knobOffset = 0;
var track = document.getElementById('track'),
knob = document.getElementById('knob'),
trackWidth = track.offsetWidth,
trackLeft = track.offsetLeft,
trackRight = trackLeft + trackWidth,
knobWidth = knob.offsetWidth,
maxRight = trackWidth - knobWidth; // relatively to track
knob.addEventListener('mousedown', function(e) {
// knob offset relatively to track
knobOffset = e.clientX - knob.offsetLeft;
dragging = true;
});
window.addEventListener('mouseup', function(e) {
dragging = false;
})
window.addEventListener('mousemove', function(e) {
if (dragging) {
// current knob offset, relative to track
var offset = e.clientX - trackLeft - knobOffset;
if(offset < 0) {
var offset = 0;
} else if(offset > maxRight) {
var offset = maxRight;
}
knob.style.left = offset + "px"
}
});
#track {width: 200px;height: 5px; margin:100px; background: red}
#knob {height: 10px; width: 40px; background: black;position: relative; }
<div id='track'>
<div id="knob"></div>
</div>

Resize div with drag handle when rotated

I could find similar questions involving jQuery UI lib, or only css with no handle to drag, but nothing with pure maths.
What I try to perform is to have a resizable and rotatable div. So far so easy and I could do it.
But it gets more complicate when rotated, the resize handle does calculation in opposite way: it decreases the size instead of increasing when dragging away from shape.
Apart from the calculation, I would like to be able to change the cursor of the resize handle according to the rotation to always make sense.
For that I was thinking to detect which quadrant is the resize handle in and apply a class to change cursor via css.
I don't want to reinvent the wheel, but I want to have a lightweight code and simple UI. So my requirement is jQuery but nothing else. no jQuery UI.
I could develop until achieving this but it's getting too mathematical for me now.. I am quite stuck that's why I need your help to detect when the rotation is enough to have the calculation reversed.
Eventually I am looking for UX improvement if anyone has an idea or better examples to show me!
Here is my code and a Codepen to try: http://codepen.io/anon/pen/rrAWJA
<html>
<head>
<style>
html, body {height: 100%;}
#square {
width: 100px;
height: 100px;
margin: 20% auto;
background: orange;
position: relative;
}
.handle * {
position: absolute;
width: 20px;
height: 20px;
background: turquoise;
border-radius: 20px;
}
.resize {
bottom: -10px;
right: -10px;
cursor: nwse-resize;
}
.rotate {
top: -10px;
right: -10px;
cursor: alias;
}
</style>
<script type="text/javascript" src="js/jquery.js"></script>
<script>
$(document).ready(function()
{
new resizeRotate('#square');
});
var resizeRotate = function(targetElement)
{
var self = this;
self.target = $(targetElement);
self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>');
self.currentRotation = 0;
self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right'];
self.bindEvents = function()
{
self.handles
//=============================== Resize ==============================//
.on('mousedown', '.resize', function(e)
{
// Attach mouse move event only when first clicked.
$(document).on('mousemove', function(e)
{
var topLeft = self.target.offset(),
bottomRight = {x: topLeft.left + self.target.width(), y: topLeft.top + self.target.height()},
delta = {x: e.pageX - bottomRight.x, y: e.pageY - bottomRight.y};
self.target.css({width: '+=' + delta.x, height: '+=' + delta.y});
})
.one('mouseup', function(e)
{
// When releasing handle, round up width and height values :)
self.target.css({width: parseInt(self.target.width()), height: parseInt(self.target.height())});
$(document).off('mousemove');
});
})
//============================== Rotate ===============================//
.on('mousedown', '.rotate', function(e)
{
// Attach mouse move event only when first clicked.
$(document).on('mousemove', function(e)
{
var topLeft = self.target.offset(),
center = {x: topLeft.left + self.target.width() / 2, y: topLeft.top + self.target.height() / 2},
rad = Math.atan2(e.pageX - center.x, e.pageY - center.y),
deg = (rad * (180 / Math.PI) * -1) + 135;
self.currentRotation = deg;
// console.log(rad, deg);
self.target.css({transform: 'rotate(' + (deg)+ 'deg)'});
})
.one('mouseup', function(e)
{
$(document).off('mousemove');
// console.log(self.positions[parseInt(self.currentRotation/90-45)]);
$('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation/90-45)]);
});
});
};
self.init = function()
{
self.bindEvents();
self.target.append(self.handles.clone(true));
}();
}
</script>
</head>
<body>
<div id="all">
<div id="square"></div>
</div>
</body>
</html>
Thanks for the help!
Here is a modification of your code that achieves what you want:
$(document).ready(function() {
new resizeRotate('#square');
});
var resizeRotate = function(targetElement) {
var self = this;
self.target = $(targetElement);
self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>');
self.currentRotation = 0;
self.w = parseInt(self.target.width());
self.h = parseInt(self.target.height());
self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right'];
self.bindEvents = function() {
self.handles
//=============================== Resize ==============================//
.on('mousedown', '.resize', function(e) {
// Attach mouse move event only when first clicked.
$(document).on('mousemove', function(e) {
var topLeft = self.target.offset();
var centerX = topLeft.left + self.target.width() / 2;
var centerY = topLeft.top + self.target.height() / 2;
var mouseRelativeX = e.pageX - centerX;
var mouseRelativeY = e.pageY - centerY;
//reverse rotation
var rad = self.currentRotation * Math.PI / 180;
var s = Math.sin(rad);
var c = Math.cos(rad);
var mouseLocalX = c * mouseRelativeX + s * mouseRelativeY;
var mouseLocalY = -s * mouseRelativeX + c * mouseRelativeY;
self.w = 2 * mouseLocalX;
self.h = 2 * mouseLocalY;
self.target.css({
width: self.w,
height: self.h
});
})
.one('mouseup', function(e) {
$(document).off('mousemove');
});
})
//============================== Rotate ===============================//
.on('mousedown', '.rotate', function(e) {
// Attach mouse move event only when first clicked.
$(document).on('mousemove', function(e) {
var topLeft = self.target.offset(),
center = {
x: topLeft.left + self.target.width() / 2,
y: topLeft.top + self.target.height() / 2
},
rad = Math.atan2(e.pageX - center.x, center.y - e.pageY) - Math.atan(self.w / self.h),
deg = rad * 180 / Math.PI;
self.currentRotation = deg;
self.target.css({
transform: 'rotate(' + (deg) + 'deg)'
});
})
.one('mouseup', function(e) {
$(document).off('mousemove');
$('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation / 90 - 45)]);
});
});
};
self.init = function() {
self.bindEvents();
self.target.append(self.handles.clone(true));
}();
}
The major changes are the following:
In the resize event, the mouse position is transformed to the local coordinate system based on the current rotation. The size is then determined by the position of the mouse in the local system.
The rotate event accounts for the aspect ratio of the box (the - Math.atan(self.w / self.h) part).
If you want to change the cursor based on the current rotation, check the angle of the handle (i.e. self.currentRotation + Math.atan(self.w / self.h) * 180 / Math.PI). E.g. if you have a cursor per quadrant, just check if this value is between 0..90, 90..180 and so on. You may want to check the documentation if and when negative numbers are returned by atan2.
Note: the occasional flickering is caused by the box not being vertically centered.
Nico's answer is mostly correct, but the final result calculation is incorrect -> which is causing the flickering BTW. What is happening is the increase or decrease in size is being doubled by the 2x multiplication. The original half-width should be added to the new half-width to calculate the correct new width and height.
Instead of this:
self.w = 2 * mouseLocalX;
self.h = 2 * mouseLocalY;
It should be this:
self.w = (self.target.width() / 2) + mouseLocalX;
self.h = (self.target.height() / 2) + mouseLocalY;

mousemove parallax only move slightly instead of mouse position

I'm wanting the plane and rocket to only move approx 5% from their original place when the mouse hits the hero-panel area.
this current code makes both images follow and offset where the mouse position is.
Please assist.
$(document).ready(function () {
$('#hero-panel').mousemove(function (e) {
parallax(e, document.getElementById('plane'), 1);
parallax(e, document.getElementById('rocket'), 2);
});
});
function parallax(e, target, layer) {
var layer_coeff = 10 / layer;
var x = ($(window).width() - target.offsetWidth) / 4 - (e.pageX - ($(window).width() / 4)) / layer_coeff;
var y = ($(window).height() - target.offsetHeight) / 4 - (e.pageY - ($(window).height() / 4)) / layer_coeff;
$(target).offset({ top: y ,left : x });
};
https://jsfiddle.net/jc0807/c5yke2on/
Thanks
Ok, I think I understand what you're looking for:
fiddle
$(document).ready(function () {
var plane = document.getElementById('plane');
var rocket = document.getElementById('rocket');
plane.homePos = { x: plane.offsetLeft, y: plane.offsetTop };
rocket.homePos = { x: rocket.offsetLeft, y: rocket.offsetTop };
$('#hero-panel').mousemove(function (e) {
parallax(e, document.getElementById('plane'), 10);
parallax(e, document.getElementById('rocket'), 20);
});
});
function parallax(e, target, layer) {
var x = target.homePos.x - (e.pageX - target.homePos.x) / layer;
var y = target.homePos.y - (e.pageY - target.homePos.y) / layer;
$(target).offset({ top: y ,left : x });
};
What we're doing here is recording the starting position of the plane and the rocket as a new property 'homePos' on the plane and rocket objects. This makes it easy to apply the parallax effect as an offset from the original positions based on the mouse distance from the object homePos.
If you modify the layer value passed to parallax, the amount of movement will change (we're dividing the mouse offset from the middle of the object's starting position by it, to calculate the new object offset amount).
I guess my question is somehow related to the one above and I didn't want to create a duplicate.
I am using the code bellow to "navigate" into an image on mousemove. The problem is that I cannot manage to make the image fill all the viewable screen area. I've added a red background to the container to show what I mean. The desired result would be to no red background visible.
HTML
<div class="m-scene" id="main">
<div class="scene_element">
<img class="body" src="http://www.planwallpaper.com/static/images/nature-background-images2.jpg" />
</div>
</div>
JS
$(document).ready(function() {
$('img.body').mousemove(function(e) {
parallax(e, this, 1);
});
});
function parallax(e, target, layer) {
var layer_coeff = 20 / layer;
var x = ($(window).width() - target.offsetWidth) / 2 - (e.pageX - ($(window).width() / 2)) / layer_coeff;
var y = ($(window).height() - target.offsetHeight) / 2 - (e.pageY - ($(window).height() / 2)) / layer_coeff;
$(target).offset({
top: y,
left: x
});
};
CSS
.m-scene {
background-color: red;
overflow: hidden;
width: 100%;
}
.scene_element {
margin-left: auto;
margin-right: auto;
overflow: hidden;
}
.scene_element img {
width: 100%;
height: auto;
margin-left: auto;
margin-right: auto;
}
My jsFiddle is: fiddle
Thank you!

How can I create a click and drag to change the width of an object with jQuery?

I have an object that I want to change the width of when you click on it and drag right or left. Adding to the width or taking away from it as you move the mouse (or finger).
<style>
#changeMe {width:300px; height: 200px;}
</style>
<div id="changeMe">
Some Content
</div>
<script>
$('#changeMe').mousedown(function(){
//Some Code?????
});
</script>
What you want to do is track the x co-ords of the mouse. If greater than they were before, increase size, if lower, decrease the size.
Not tested but the below should be inspiration.
var oldXPos = 0;
var isDragging = false;
$(document).mousemove(function(event) {
if (isDragging)
{
var difference = event.pageX - oldXPos;
// Do something with this value, will be an int related to how much it's moved
// ie $('#changeMe').css.width += difference;
}
oldXPos = event.pageX;
});
$('#changeMe').mousedown(function() {
isDragging = true;
})
$('#changeMe').mouseup(function() {
isDragging = false;
})
You just need a resizable({}) effect .
$('#changeMe').resizable({});
You can look at this article
Resizable
$(function() {
$('.testSubject').resizable();
});
or
#changeMe {width:300px; height: 200px; border: 1px solid black;}
<body>
<div id="changeMe">
Some Content
</div>
</body>
$('#changeMe').resizable({});
Or
$(function(){
$('img[src*=small]').toggle(
function() {
$(this).attr('src',
$(this).attr('src').replace(/small/,'medium'));
},
function() {
$(this).attr('src',
$(this).attr('src').replace(/medium/,'large'));
},
function() {
$(this).attr('src',
$(this).attr('src').replace(/large/,'small'));
}
);
});
If I understand your question correctly, that you want to be able to dynamically increase/decrease the size of the object as it moves along the x-axis, I recommend that you use $('#changeMe').offset() inside the jQuery UI drag event.
You can create a formula that you want to use based on an initial offset, and the new offset to size your container by $('#changeMe').css({ width: X, height: Y });, and insert whatever your X and Y values are in pixels.
Edited for further elaboration with code:
var initX = 0;
var initW = 0;
$('#changeMe').draggable({
start: function() {
initX = $(this).offset().left;
initW = $(this).width();
},
drag: function() {
var deltaX = initX - $(this).offset().left;
$(this).css({ width: initW + deltaX });
}
});
If you used that as your base, it's a very nice and simple solution for your application.

Categories