How to lock movement on diagonal axis in Vue/JavaScript? - javascript

The goal is to lock the movable direction of the div on the diagonal axis.
Related to the code below:
The Event #mousedown triggers a boolean to true which activates the move state.
The Event #mousedown calculates the offset
The Event #move calculates the new coordinates of the div based on the users mouse position
With e.clientX + (offsetX * Math.tan(angle * rad)) I can lock the movement to a negative gradient.
I tested it with different angels but it looks like the math is wrong.
What am I missing?
new Vue({
el: '#app',
data: {
x: 0,
y: 0,
coordinates: {
top: "10px",
left: "10px"
},
draggable: false,
offset: [0, 0],
},
methods: {
down(e) {
this.draggable = true;
this.offset = [
e.target.offsetLeft - e.clientX,
e.target.offsetTop - e.clientY
];
},
up(e) {
this.draggable = false;
},
move(e) {
if (this.draggable) {
this.coordinates.left = (e.clientX + this.offset[0]) + "px";
this.coordinates.top = (e.clientX + (this.offset[0] * Math.tan(45 * Math.PI / 180))) + "px";
}
}
}
})
#app {
position: relative;
width: 100vh;
height: 100vh;
}
.draggable{
cursor: pointer;
position: absolute;
border-radius: 100px;
background-color: lightcoral;
width: 30px;
height: 30px;
padding: 10px;
}
<script src="https://unpkg.com/vue"></script>
<div id="app" #mouseup="up" #mousemove="move">
<div class="draggable" :style="coordinates" #mousedown="down">
</div>
</div>

Related

Resize and rearrange divs through drag & drop and dynamic CSS

I have two divs that I want my users to be able to hit a button and arrange these two divs top/down or left/right. I have implemented it but whenever I arrange them left/right, the right div often overflows to the bottom of the left div.
I have seen another similar example that talks about resizing left/right divs, but I still don't know what exactly caused my right div to overflow. Any help is appreciated!
Here is my example:
var d = $('#divider'); // divider between top and bottom divs
var t = $('#tl'); // top/left div
var b = $('#br'); // bottom/right div
var h = $('body').height();
var w = $('body').width();
var isDragging = false;
var isLandscape = false;
d.mousedown(function(e) {
isDragging = true;
});
$(document).mouseup(function() {
isDragging = false;
}).mousemove(function(e) {
if (isDragging) {
if (!isLandscape) {
t.css('height', e.pageY);
b.css('height', h - e.pageY - d.height());
d.css('height', h - t.height() - b.height());
} else {
t.css('width', e.pageX);
b.css('width', w - e.pageX - d.width());
d.css('width', w - t.width() - b.width());
}
}
});
var rotateBtn = document.getElementById('rotateScreen');
if (rotateBtn) {
rotateBtn.addEventListener('click', rotateDisplay, false);
} else {
throw error;
}
function rotateDisplay() {
if (!isLandscape) {
isLandscape = true;
t.css('height', h);
t.css('width', Math.round(0.75 * w));
b.css('height', h);
b.css('width', Math.round(0.24 * w));
d.css('height', h);
d.css('width', w - t.width() - b.width());
d.css('cursor', 'w-resize');
} else {
isLandscape = false;
t.css('height', Math.round(0.75 * h));
t.css('width', w);
t.css('float', 'left');
b.css('height', Math.round(0.24 * h));
b.css('width', w);
b.css('float', 'left');
d.css('height', h - t.height() - b.height());
d.css('width', w);
d.css('cursor', 'n-resize');
d.css('float', 'left');
}
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#br {
width: 100%;
height: 24%;
float: left;
background: gold;
}
#tl {
width: 100%;
height: 75%;
float: left;
background: navy;
}
#divider {
height: 1%;
background: #fff;
float: left;
width: 100%;
cursor: ns-resize;
}
#control {
position: absolute;
z-index: 5;
background-color: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control">
<button id="rotateScreen">🔁</button>
</div>
<div id="tl">This is the top/left div</div>
<div id="divider"></div>
<div id="br">This is the bottom/right div</div>

JQUERY How to disable not-allowed cursor while dragging?

I've got issue with the not-allowed cursor. While dragging the "drag" element, not-allowed cursor appears and I can't drag it anymore. How can i prevent that? I want to make my "drag" element always be "absolute" while mouse is down.
Note: I know that it can happens becouse "pointer-events" but I need it to be contained into this code.
Some code:
$("#drag").bind({
mousedown : function (e) {
var dragged = $(this);
dragged.css({
left : e.pageX - (50 / 2),
top : e.pageY - (50 / 2)
});
dragged.addClass("absolute");
dragged.css({
'pointer-events' : 'none'
})
var upHandler = function () {
dragged.removeClass("absolute");
dragged.css({
'pointer-events' : 'all'
})
$("body").off('mouseup', upHandler);
$("body").off('mousemove', moveHandler);
}
var moveHandler = function (e) {
dragged.css({
left : e.pageX - (50 / 2),
top : e.pageY - (50 / 2)
});
}
$("body").bind({
mouseup : upHandler,
mousemove : moveHandler
})
}
});
$("body").mousemove(function (event) {
$("#log").text("pageX: " + event.pageX + ", pageY: " + event.pageY);
});
https://jsfiddle.net/38zecoL1/1/
Thanks for any help.
Before handling your mouse events, make a call to
e.preventDefault();
It cancels the event which prevents the browser from performing the default behavior. Normally it would show a "not allowed" cursor on elements that typically are not draggable.
$("box").mouseover(function() {
$(this).addClass("green");
var box = $(this).attr("id");
$("#result").html(box);
});
/*
Solution
*/
$("box").mousedown(function(e) {
// Booooom! This should stop the undesired default beahvior.
e.preventDefault();
});
$("box").mouseleave(function() {
$(this).removeClass("green");
});
$("#drag").bind({
mousedown: function() {
$(this).addClass("absolute");
},
mouseup: function() {
$(this).removeClass("absolute");
},
mousemove: function(e) {
$(this).css({
left: e.pageX - (50 / 2),
top: e.pageY - (50 / 2)
});
}
});
$("body").mousemove(function(event) {
$("#log").text("pageX: " + event.pageX + ", pageY: " + event.pageY);
});
box {
float: left;
width: 100px;
height: 100px;
background-color: red;
margin: 20px;
}
#log {
position: absolute;
top: 150px;
}
.green {
background-color: green;
}
#drag {
width: 50px;
height: 50px;
float: left;
background-color: blue;
}
#drag.absolute {
position: absolute;
}
html,
body {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
<box id="box1">
<div id="drag"></div>
</box>
<box id="box2"></box>
<div id="result"></div>
<div id="log"></div>
Original fiddle: https://jsfiddle.net/38zecoL1/4/

How can I smoothly move layers from one position to another when the mouse leaves and enter the window?

I am refining a parallax effect trying to create a smooth transition between two positions using where the mouse leaves and enters the window. If you notice the JSFiddle has a 'pop' that I want to replace with the transition. How can I do that?
$(document).ready(function() {
$('#layer-one').mousemove(function(e) {
parallax(e, this, 1);
parallax(e, document.getElementById('layer-two'), 2);
parallax(e, document.getElementById('layer-three'), 3);
});
});
function parallax(e, target, layer) {
var layer_coeff = 10 / 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
});
};
JSFiddle
Thank you in advance.
Perhaps, you can use GSAP libraries to make that offset effect smoother, this is just a fast example, give it a try:
var initPos = $('#layer-one').position();
$(document).ready(function() {
$('#layer-one').mousemove(function(e) {
parallax(e, this, 1);
parallax(e, document.getElementById('layer-two'), 2);
parallax(e, document.getElementById('layer-three'), 3);
});
});
function parallax(e, target, layer) {
var layer_coeff = 10 / 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
});*/
TweenLite.to($(target), 2, {x:x, y:y});
};
document.onmouseleave = function() {
$("#layer-one").animate({
opacity: 0.4,
left: 10,
}, 'fast');
};
.layer {
padding: 20px;
color: white;
}
#base-layer {
overflow: hidden;
}
#layer-one {
background: red;
}
#layer-two {
background: green;
}
#layer-three {
background: blue;
}
.slider {
margin-left: auto;
margin-right: auto;
overflow: hidden;
padding-top: 200px;
}
.slider img {
width: 80%;
padding-left: 10%;
padding-right: 10%;
height: auto;
margin-left: auto;
margin-right: auto;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenLite.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/easing/EasePack.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/plugins/CSSPlugin.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="base-layer">
<div id="layer-one" class="layer">
Content
<div id="layer-two" class="layer">
Content
<div id="layer-three" class="layer">
Content
<section class="slider">
<img src="http://i.imgur.com/fVWomWz.png">
</section>
</div>
</div>
</div>
</div>

Keep selected div centered when zooming

I have this HTML code:
<div class="inner">
<div class="nhood">
<div class="image"></div>
</div>
</div>
And this CSS:
.image {
width: 4000px;
height: 4000px;
background: beige;
margin: 150px;
position: absolute;
}
.nhood {
overflow: hidden;
width: 100%;
height: 100%;
box-sizing: border-box;
position: relative;
background: black;
}
The .image div is filled with 400 divs, all floating left, creating a huge 'chess'-pattern, the code is the following:
.image > div {
border: 1px dotted;
width: 5%;
height: 5%;
float: left;
box-sizing:border-box;
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
position: relative;
user-select: none;
}
You are able to click on any cell to show its info, and the whole .image div is draggable. Now if you have selected a cell and you ZOOM (which basically only shrinks/extends the 4000x4000 div to 2000x2000 or the other way round) it zooms in ANYWHERE but I want to keep focus on the cell that was selected earlier.
I have made an image of this:
http://smimoo.lima-city.de/zoom.png
I hope this was any clear...
EDIT:
JS
function zoomIn() {
$(draggable).animate({
height: '4000',
width: '4000',
borderWidth: 0
}, 600, function() {
$divs.animate({
borderWidth: 0
});
});
}
function zoomOut() {
$(draggable).animate({
height: '2000',
width: '2000',
borderWidth: 0
}, 600, function() {
$divs.animate({
borderWidth: 1
});
});
EDIT2:
This is my js to center the function (written before Mario helped me out):
function centerField() {
var myObject = $(draggable).find('.selected');
var docWidth = ($(viewport).width() / 2) - (myObject.outerWidth()/2);
var docHeight = ($(viewport).height() / 2) - (myObject.outerWidth()/4);
var myOff = myObject.offset();
var distanceTop = myOff.top - docHeight;
var distanceLeft = myOff.left - docWidth;
var position = $(draggable).position();
var left = position.left;
var top = position.top;
var right = left - $(viewport).width() + draggable.outerWidth(true);
var bottom = top - $(viewport).height() + draggable.outerHeight(true);
if(left - distanceLeft > 0) {
distanceLeft = left;
}
if(right - distanceLeft < 0) {
distanceLeft = right;
}
if(top - distanceTop > 0) {
distanceTop = top;
}
if(bottom - distanceTop < 0) {
distanceTop = bottom;
}
$(draggable).animate({
left: '-=' + distanceLeft,
top: '-=' + distanceTop
}, { duration: 200, queue: false });
}
Assume that the selected div has the class .selected, this function will center the div:
function centerSelected() {
var selectedElement = $('.image .selected');
var p = selectedElement.position();
var w = $('.nhood').width();
var h = $('.nhood').height();
var offsetX = (w/2)-p.left - (selectedElement.width() / 2);
var offsetY = (h/2)-p.top - (selectedElement.height() / 2);
if(offsetX > 0) offsetX = 0;
if(offsetY > 0) offsetY = 0;
$('.image').css('left', offsetX + 'px');
$('.image').css('top', offsetY + 'px');
}
Just call centerSelected after every zoom operation.
Here is a jsfiddle with slightly modified css to get the presentation work:
http://jsfiddle.net/q1r95w3g/3/
Edit
If you want the div to get centered during jQuery animation, you can call centerSelected in the step callback of the animate method, e.g.:
function zoomIn() {
$(draggable).animate({
height: '4000',
width: '4000',
borderWidth: 0
},{
duration: 600,
complete: function() {
$divs.animate({
borderWidth: 0
});
},
step: function(now, fx) {
centerSelected();
}
});
}

how to detect element dropped out side of a circle?

I am using raphael.js library and created a circle and a small black circle inside it. And now I want to drag that small circle out of the big circle. How can I detect whether the circle was dropped outside the circle or not?
<script src="jquery-1.9.1.js"></script>
<script type="text/javascript" src="raphael.js"></script>
<script src="jquery-ui.min.js"></script>
<script>
$(function () {
var paper = new Raphael(0, 0, 150,150),
circle = paper.circle(75, 75, 15);
//circle2=false;
circle2=paper.circle(75, 75, 4);
circle2.hide();
circle.attr({
'stroke': '#f00',
'stroke-width': 4,
'fill': '#fff'
});
circle.hover(function(e) {
this.animate({ r: 30 }, 1000,'super_elastic');
circle2.show();
'fill': '#000'
});
}, function() {
this.animate({ r: 15 }, 1000, 'super_elastic');
circle2.hide();
});
circle2.hover(function(e) {
circle.animate({ r: 30 }, 1000,'super_elastic');
circle2.show();
}, function() {
});
/*******/
var p = paper.set(circle2);
circle2.set = p;
p.newTX=0,p.newTY=0,p.fDx=0,p.fDy=0,p.tAddX,p.tAddY,p.reInitialize=false;
start = function () {
},
move = function (dx, dy,x,y,cx) {
var a = this.set;$('#circle2').text(dx);
$('#circle3').text(dy);
$('#circlex').text(x);
$('#circley').text(y);
$('#circlez').text(cx);
a.tAddX=dx-a.fDx,a.tAddY=dy-a.fDy,a.fDx=dx,a.fDy=dy;
if(a.reInitialize)
{
a.tAddX=0,a.fDx=0,a.tAddY=0;a.fDy=0,a.reInitialize=false;
}
else
{
a.newTX+=a.tAddX,a.newTY+=a.tAddY;
a.attr({transform: "t"+a.newTX+","+a.newTY});
}
},
up = function () {
this.set.reInitialize=true;
};
p.drag(move, start, up);
/*******/
// modify this function
Raphael.easing_formulas.super_elastic = function(n) {
return Math.pow(2, -10 * n) * Math.sin((n - .075) * (2 * Math.PI) / .3) + 1;
};
});
</script>
<body>
<div name='circle2' id='circle2' style="
background: red;
width: 10px;
height: 10px;
"></div>
<div name='circle3' id='circle3' style="
background: red;
width: 10px;
height: 10px;
"></div>
<div name='circle3' id='circlex' style="
background: red;
width: 10px;
height: 10px;
"></div>
<div name='circle3' id='circley$$' style="
background: red;
width: 10px;
height: 10px;
"></div>
<div name='circle3' id='circlez' style="
background: red;
width: 10px;
height: 10px;
"></div>
</body>
The distance between the centres of circles will become larger than the sum of their radii. Some pseudocode:
d = sqrt((x1 - x2)^2 + (y1 - y2)^2)
if(d > r1+r2)
print("It is out!");
else
print("It is inside!")
where your circle of radius r1 is at (x1, y1) and another one with radius r2 is at (x2, y2).

Categories

Resources