How to resize a div on drag? [Issue with rotation] - javascript

I need to be able to re-size a div when dragging two handlers.
Please use the following link
http://jsbin.com/lopumaheyu/1/
Click the green box, after drag orange boxes, the script work correctly and green box is re-sized.
I have an issue when CSS rotation is being applied to the green box, example:
http://output.jsbin.com/zirugeroju/1/
As you can notice there is a swift for the opposite knob an user is dragging.
What could be wrong here and how to fix it?
A better solution also with jQuery is also welcome
resize: function (handler, event) {
if (event.clientX <= 0) { // cover bug
return;
}
var elm = document.getElementById(this.config.elm);
switch (handler) {
case 'tl':
// x
var marginR = elm.offsetLeft + elm.clientWidth,
newW = marginR - event.clientX,
xPos = event.clientX;
elm.style.left = xPos + 'px';
elm.style.width = newW + 'px';
// y
var marginT = elm.offsetTop + elm.clientHeight,
newH = marginT - event.clientY,
yPos = event.clientY;
elm.style.top = yPos + 'px';
elm.style.height = newH + 'px';
this.setPositionHandlers();
break;
case 'tr':
break;
case 'bl':
break;
case 'br':
var newW = event.clientX - this.config.x,
newH = event.clientY - this.config.y;
elm.style.width = newW + 'px';
elm.style.height = newH + 'px';
this.setPositionHandlers();
break;
}
},

I think you can add:
-webkit-transform-origin: left top;
on #target to avoid the little swift on top left orange handler.
#target {
background-color: lightgreen;
-ms-transform: rotate(10deg);
-webkit-transform: rotate(10deg);
-webkit-transform-origin: left top;
transform: rotate(10deg);
}

Related

Circle moving out of window

var circle = document.getElementById("circle");
function moveUp() {
var top = circle.offsetTop;
newTop = top - 10;
circle.style.top = newTop + "px";
console.log("moveUP Called")
}
function moveDown() {
var top = circle.offsetTop;
newTop = top + 10;
circle.style.top = newTop + "px";
console.log("moveDown Called")
}
function moveLeft() {
var left = circle.offsetLeft;
newLeft = left - 10;
circle.style.left = newLeft + "px";
console.log("moveLeft Called")
}
function moveRight() {
var left = circle.offsetLeft;
newLeft = left + 10;
circle.style.left = newLeft + "px";
console.log("moveRight Called")
}
window.addEventListener("keypress", (event) => {
if (event.key == 'w') {
moveUp();
} else if (event.key == 's') {
moveDown();
} else if (event.key == 'a') {
moveLeft();
} else if (event.key == 'd') {
moveRight();
}
})
body {
margin: 2px;
background-color: aquamarine;
}
#circle {
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
}
In the above code where on key press circle moves, for example on 'w' it moves up, for 's' it moves down and so on.
But the problem is that the circle even moves out of the window, how do I fix it and what is the problem??
var circle = document.getElementById("circle");
console.log(window.innerWidth, window.innerHeight)
function moveUp() {
var top = circle.offsetTop;
console.log(top)
newTop = top - 10;
if(newTop < 0) {
newTop = 0;
}
circle.style.top = newTop + "px";
}
function moveDown() {
var top = circle.offsetTop;
var height = circle.offsetHeight + top;
if((height + 10) >= window.innerHeight) {
return;
}
newTop = top + 10;
circle.style.top = newTop + "px";
/* console.log("moveDown Called") */
}
function moveLeft() {
var left = circle.offsetLeft;
newLeft = left - 10;
if(newLeft<0) {
newLeft = 0;
}
circle.style.left = newLeft + "px";
}
function moveRight() {
var left = circle.offsetLeft;
newLeft = left + 10;
if(newLeft > window.innerWidth - 100 ) {
newLeft = window.innerWidth - 100 ;
}
circle.style.left = newLeft + "px";
}
window.addEventListener("keypress", (event) => {
if (event.key == 'w') {
moveUp();
} else if (event.key == 's') {
moveDown();
} else if (event.key == 'a') {
moveLeft();
} else if (event.key == 'd') {
moveRight();
}
})
body{
margin:2px;
background-color: aquamarine;
}
#circle{
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
overflow: hidden;
}
<div id="circle">
</div>
Explaination
for moveup() if the position is a negative number that means the div is going out of the viewport. So with the if condition new position will be always set to 0 preventing the div to go negative position.
for moveDown() first you get the offsetTop which means how far is the box from top position along with the offsetHeight which represents the height of the box. So add these two to get the total height. Now simply check if this height is going over the innerHeight + the distance(10) you are going with each move. If it is more than the innerHeight simply return. otherwise move the box.
moveLeft() is same as moveUp().
moveRight() is also same as moveDown() but here we're calculating the innerWidth. Subtract it with the box width so it doesn't go outside the viewport. Now simple condition check and set the new right position.
hope it helped
What is the problem?
There is no problem. CSS does exactly what you told it to do.
For example, you can click on 'w' couple of times, which will set left property for your absolutely positioned circle to, let's say, -160px. This will instruct the browser to move your element to the left, away from the viewport, i.e. to position it -160px of the left edge of the initial containing block or nearest positioned ancestor. More about left property: https://developer.mozilla.org/en-US/docs/Web/CSS/left
I would not say that it is a problem, because it is exactly what left is used for - move elements to whatever position you like. Sometimes you can hide elements by setting their position: absolute; left: -10000px;
How do I fix it?
If you don't want your circle to move away from the viewport, you need to check if your circle is 'touching' the viewport. I will use example with the left, but the same logic can be applied to top, right and bottom.
So for the left, this will consist of two parts:
Check what is the initial distance from your circle to the left edge of the viewport.
Check if absolute value of your new left value is not greater than this distance.
For example, for the left method:
var elDistanceToLeft = window.pageXOffset + circle.getBoundingClientRect().left;
function moveLeft() {
let left = circle.offsetLeft;
newLeft = Math.abs(left - 10) <= elDistanceToLeft ? left - 10 : -elDistanceToLeft;
circle.style.left = newLeft + "px";
}
In this case your circle will move all way to the left (on pressing 'a') until it 'touches' the viewport (screen). Then it will stop.
Here is a code snippet
var elDistanceToLeft = window.pageXOffset + circle.getBoundingClientRect().left
function moveLeft() {
let left = circle.offsetLeft;
newLeft = Math.abs(left - 10) <= elDistanceToLeft ? left - 10 : -elDistanceToLeft;
circle.style.left = newLeft + "px";
}
window.addEventListener("keypress", (ev) => { if (ev.key == 'a') { moveLeft();} })
#circle {
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
}
#parent {
position: relative;
padding: 200px;
}
<div id="parent">
<div id="circle"></div>
</div>

How to 3D tilt a background image to change the perspective as you move the mouse?

How can I add a 3D tilt to a background image so that when you move the mouse the perspective of the image changes? I will be using this on an illustration of a piece of art on a wall in a gallery so I want it to tilt depending on where you mouse is as if you are viewing it from a different part of the room.
<style>
body {
background-image: url("https://c1.wallpaperflare.com/preview/442/138/421/art-gallery-canvas-arts-gallery.jpg");
background-position: 50% 50%;
height:100vh;
background-repeat:no-repeat;
}
</style>
<body>
By combining the css perspective and transform properties, we can achieve something like this
document.querySelector('.image-holder img').addEventListener('load', (event) => {
let cordinates = document.querySelector('.image-holder img').getBoundingClientRect();
let imageX = (cordinates.left + window.scrollX + cordinates.right) / 2;
let imageY = (cordinates.top + window.scrollY + cordinates.bottom) / 2;
const ANGLE_COMPENSATION = 10;
document.querySelector('.image-holder').addEventListener('mousemove', (event) => {
let mouseX = event.clientX;
let mouseY = event.clientY;
let xOffset = imageX - mouseX;
let yOffset = imageY - mouseY;
let xRotationAngle = yOffset / ANGLE_COMPENSATION;
let yRotationAngle = xOffset / ANGLE_COMPENSATION;
document.querySelector('.image-holder img').style.transform = "rotateX(" + xRotationAngle + "deg) rotateY(" + yRotationAngle + "deg) "
})
})
body .image-holder {
perspective: 2000px;
margin: 20px;
}
<div class="image-holder">
<img src="https://c1.wallpaperflare.com/preview/442/138/421/art-gallery-canvas-arts-gallery.jpg" />
</div>
Reduce the value of ANGLE_COMPENSATION to increase senstivity.

Horizontal scrolling menu with Javascript

I have created a menu that it is bigger than the width of the page.
And I want when it goes to it's last item, the first will appear again like a circle with no end.
here is the css code of the menu
`.slider
width: 200%
height: 65vh
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
display: flex
align-items: center
user-select: none
transition: all 0s
&:hover
cursor: grab`
and this is the js
var isDown = false;
var startX;
var mousePosition;
var offset = [0,0];
$('.slider').mousedown(function(e) {
$(this).css('cursor', 'grabbing');
$('.pointer').css({'width': '55px', 'height': '55px'});
isDown = true;
startX = e.clientX;
offset = [
this.offsetLeft - e.clientX,
this.offsetTop - e.clientY
];
// var startX = e.pageX;
// var math = Math.round(Math.sqrt(Math.pow(startX - event.clientX, 2))) + 'px';
// $(this).css('transform', 'translate(' + math + 'px, -50%)');
// console.log(math);
});
$('.slider').mousemove(function(e) {
// e.preventDefault();
if (isDown){
// var tap = $('.slider').offset().left;
// console.log(e.pageX - tap);
mousePosition = e.clientX ;
console.log(mousePosition);
// $(this).css('transform', 'translate(' + mousePosition + ', -50%)');
// console.log(e);
this.style.left = (mousePosition + offset[0]) + 'px';
startX = mousePosition;
// this.style.transform = "translate3d(" + 0 + "1110px, " + 0 + "0px, 0)";
// div.style.left = (mousePosition.x + offset[0]) + 'px';
}
});
$('.slider').mouseup(function() {
$(this).css('cursor', 'grab');
$('.pointer').css({'width': '30px', 'height': '30px'});
isDown = false;
});
When the slider goes to it's last item it ends, but I want the first one to appear again.
May I suggest using an already existing library?
There is a library called Endless.js, and this does exactly what you asked for. The demo can be found here.

I want to stop my div from moving

I have a code which causes the waterlevel in a bottle to go up or down by clicking a button. however, it can't stop without clicking on stop. I need it to basically reset when it empties, and that the div of the waterlevel doesn't go below a certain point (or above a certain point). If you're interested in what I'm making; I'm making an alcohol simulator. So you'll basically see the waterlevel of an alcohol drink going down (i.e. 100 px), and 100 px down means that you can see the waterlevel(alcogol level) in the stomach with i.e. 50 px, and that equals 20 px in the blood circulation and 10 px in the brains. (just to get an idea.)
But if I click on the button of going down, the div will just leave the bottle and will have an endless journey. (js please, not jquery)
here's my JS code:
function move_img(str) {
var step=2 ; // change this to different step value
switch(str){
case "down":
var x=document.getElementById('i1').offsetTop;
x= x + step;
document.getElementById('i1').style.top= x - 1 + "px";
break;
case "up":
var x=document.getElementById('i1').offsetTop;
x= x -step;
document.getElementById('i1').style.top= x + "px";
break;
case "left":
var y=document.getElementById('i1').offsetLeft;
y= y - step;
document.getElementById('i1').style.left= y + "px";
break;
case "right":
var y=document.getElementById('i1').offsetLeft;
y= y + step;
document.getElementById('i1').style.left= y + "px";
break;
}
}
function auto(str) {
myVar = setInterval(function(){ move_img(str); }, 2) ;
}
setTimeout(function( ) { clearInterval( myVar ); }, 1);
function nana(){
}
Your fiddle doesn't work. You'll need to specify the height as well as the top attribute, and I believe top has to be above bottom. I've made an example here. The changes to your examples are:
//javascript
if (str == 'up' || str == 'down') {
var top = el.offsetTop;
var height = el.offsetHeight; //get height to modify
console.log(height);
if (str == 'up') {
top -= step;
height += step; //adjust height
} else {
top += step;
height -=step; //adjust height
}
if (top_max >= top && top >= 0) { //make sure #i1 is inside #i
document.getElementById('i1').style.top = top + "px";
document.getElementById('i1').style.height = height + "px"; //modify height
} else {
clearInterval(myVar)
}
//css
#i1 {
width: 100px;
display: inline-block;
background:red;
position: absolute;
top: 150px; //initial top
bottom: 250px; //as as bottom of #i
height:100px; //initial height
}

Moving an image with 360° angle in Javascript

I am trying to make an image move 360° (not rotate) back it's course, but so far I was able to move only to a specific direction, if I add left & bottom course, then the image going diagonal to left & bottom. Here are the properties:
CSS
#circle{
background:red;
border-radius:100px;
height:100px; width:100px;
position:absolute;
}
JavaSript
(function() {
var speed = 10,
moveBox = function(){
var el = document.getElementById("circle"),
left = el.offsetLeft,
moveBy = 3;
el.style.left = left + moveBy + "px";
if(left > 200){
clearTimeout(timer);
}
};
var timer = setInterval(moveBox, speed);
}());
HTML:
<div id='circle'></div>
JsFiddle Online Demo
The problem is looping back the red circle, I want it to move to left > bottom > right > up
in a circular manner.
thanks for the help.
Using Math.sin and Math.cos to describe the circle: http://jsfiddle.net/E3peq/7/
(function() {
var speed = 10,
moveX = 0.1,
moveY = 0.1,
increment = 0.1,
amp = 10,
moveBox = function(){
var el = document.getElementById("circle"),
left = el.offsetLeft,
top = el.offsetTop;
moveX += increment;
moveY += increment;
var moveXBy = Math.cos(moveX) * amp;
var moveYBy = Math.sin(moveY) * amp;
el.style.left = (left + moveXBy) + "px";
el.style.top = (top + moveYBy) + "px";
if(left > 200){
clearTimeout(timer);
}
};
var timer = setInterval(moveBox, speed);
}());
Edit: Abraham's answer in the comments is actually a lot nicer looking than this...

Categories

Resources