How can I jump a resized div to next row when the resize is constrained on the parent div like below (fullcalendar like thing).
Update.This code is dependent on InteractJS (http://interactjs.io/)
interact(resizeDiv)
.resizable({
edges: { left: true, right: true, bottom: false, top: false },
restrictEdges: {
endOnly: true,
outer: '.month'
},
restrictSize: {
min: { width: 80, height: 3 },
max: {height: 3}
},
inertia: true,
})
.on('resizemove', function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0),
y = (parseFloat(target.getAttribute('data-y')) || 0);
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.webkitTransform = target.style.transform =
'translate(' + x + 'px,' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height);
var onTopElement = document.elementFromPoint(event.clientX, event.clientY);
let calendarArea = document.getElementById('calendarArea');
console.log(event.clientY, target.offsetTop);
})
Example - Fullcalendar:
Fullcalendar logic is simple, it will create a new div on next row rather than using the same div which you are resizing and apply resize(for fullcalendar, it uses JQuery resize event) event on the new div. I think its technically impossible to use the same div(same dom element) on the two rows which you are trying to do.
Related
Is it possible the "Swap out" draggable items using InteractJS, when dragging a draggable item from a "origin" to a "target" zone?
I cannot find any reference in their Documentation https://interactjs.io/docs about this specific use case
To explain better the situation and goal I made this rough fiddle:
https://jsfiddle.net/09afor6w/
It has 2 draggable "boxes" each in a "parent box". When dragging the first box to the second, the second should automatically swap locations with the first, instead of staying put, or at least not allow the dragged element to be superposed to the element already there.
I assumed they would have a specific "swap" feature but it does not seem so.
With the "restrict" method, I can only restrict size and area of (size and drag), but not control that no items should overlap and thus maybe use this as a workaround to create a "swap" experience.
The goal behind this is creating a UI where the user can drag and drop single form elements into different places in a restricted, "gridded" area and resize the form elements.
When dragging elements from A to B, the element from the target area should change location to the "origin" area of the dragged item, that's all.
So if there is an easier, lighter way to do this, I am also happy to hear about.
This is the code I use.
HTML:
<div class="contain-all">
<div class="contain-some">
<div class="grid-snap">
Move this box to the white target area below
</div>
</div>
<div class="contain-some">
<div class="grid-snap">
This box should automatically swap place with the moved box
</div>
</div>
</div>
JS:
var elements = document.getElementsByClassName('grid-snap');
$(elements).each(function(){
var x = 0; var y = 0
interact(this)
.resizable({
// resize from all edges and corners
edges: { left: true, right: true, bottom: true, top: true },
listeners: {
move (event) {
var target = event.target
var x = (parseFloat(target.getAttribute('data-x')) || 0)
var y = (parseFloat(target.getAttribute('data-y')) || 0)
// update the element's style
target.style.width = event.rect.width + 'px'
target.style.height = event.rect.height + 'px'
// translate when resizing from top or left edges
x += event.deltaRect.left
y += event.deltaRect.top
target.style.transform = 'translate(' + x + 'px,' + y + 'px)'
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
},
modifiers: [
// keep the edges inside the parent
interact.modifiers.restrictEdges({
outer: 'parent'
}),
// minimum size
interact.modifiers.restrictSize({
min: { width: 100, height: 50 }
})
],
inertia: true
})
.draggable({
listeners: { move: window.dragMoveListener },
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: '#formthing',
}),
interact.modifiers.snap({
targets: [
interact.snappers.grid({ x: 30, y: 30 })
],
range: Infinity,
relativePoints: [ { x: 0, y: 0 } ]
}),
]
})
.on('dragmove', function (event) {
x += event.dx
y += event.dy
event.target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'
})
});
Hello I'm searching "Object Layout library" its working on JavaScript.
I want to implement function for my web app like these feature below (look at this link).
https://imgur.com/mJq3HiV
I already searched information but I couldn't find a good module. Do you know a library something like that?
Okay, you are looking for interact.js here is the npm link.
Read the docs to learn, see the snippet bellow to see if is that what you want.
function dragMoveListener(event) {
var target = event.target
// keep the dragged position in the data-x/data-y attributes
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)'
// update the posiion attributes
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
window.onload = () => {
interact('.resize-drag')
.resizable({
// resize from all edges and corners
edges: { left: true, right: true, bottom: true, top: true },
listeners: {
move(event) {
var target = event.target
var x = (parseFloat(target.getAttribute('data-x')) || 0)
var y = (parseFloat(target.getAttribute('data-y')) || 0)
// update the element's style
target.style.width = event.rect.width + 'px'
target.style.height = event.rect.height + 'px'
// translate when resizing from top or left edges
x += event.deltaRect.left
y += event.deltaRect.top
target.style.webkitTransform = target.style.transform =
'translate(' + x + 'px,' + y + 'px)'
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
target.textContent = Math.round(event.rect.width) + '\u00D7' + Math.round(event.rect.height)
}
},
modifiers: [
// keep the edges inside the parent
interact.modifiers.restrictEdges({
outer: 'parent'
}),
// minimum size
interact.modifiers.restrictSize({
min: { width: 100, height: 50 }
})
],
inertia: true
})
.draggable({
listeners: {
// call this function on every dragmove event
move: dragMoveListener,
// call this function on every dragend event
end(event) {
var textEl = event.target.querySelector('p')
textEl && (textEl.textContent =
'moved a distance of ' +
(Math.sqrt(Math.pow(event.pageX - event.x0, 2) +
Math.pow(event.pageY - event.y0, 2) | 0))
.toFixed(2) + 'px')
}
},
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
]
})
}
.resize-drag {
background-color: #29e;
color: white;
font-size: 20px;
font-family: sans-serif;
border-radius: 8px;
padding: 20px;
touch-action: none;
width: 120px;
/* This makes things *much* easier */
box-sizing: border-box;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
<div class="resize-drag">
Resize from any edge or corner
</div>
I am using InteractJs and I almost have it working but when I put the star on a tree that was small before it goes to the top of the small tree.
So when you drag the star on a tree the other trees get smaller. When you drag it to another tree the trees get normal height again but the star goes to the top of the small tree height that it used to be.
interact('.draggable')
.draggable({
onmove: function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
},
onend: function (event) {
var textEl = event.target.querySelector('p');
textEl && (textEl.textContent =
'moved a distance of '
+ (Math.sqrt(event.dx * event.dx +
event.dy * event.dy)|0) + 'px');
}
})
.inertia(true)
.restrict({
drag: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
});
interact('.draggable').snap({
mode: 'anchor',
anchors: [],
range: Infinity,
elementOrigin: { x: 0.5, y: 2 },
endOnly: true
});
// enable draggables to be dropped into this
interact('.tree').dropzone({
// only accept elements matching this CSS selector
accept: '#star',
// Require a 75% element overlap for a drop to be possible
overlap: 0.75,
// listen for drop related events:
ondropactivate: function (event) {
// add active dropzone feedback
event.target.classList.add('drop-active');
},
ondragenter: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
clearInterval(interval); // stop star rotation
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: .5,
height: "160px"
});
var dropRect = interact.getElementRect(event.target),
dropCenter = {
x: dropRect.left + dropRect.width / 2,
y: dropRect.top + dropRect.height / 2
};
event.draggable.snap({
anchors: [ dropCenter ]
});
},
ondragleave: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: 1,
height: "186px"
});
event.draggable.snap(false);
},
ondrop: function (event) {
//Dropped event
},
ondropdeactivate: function (event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
})
//Start star rotation
var angle = 0;
var interval = setInterval(function(){
angle+=1;
$("#star img").rotate(angle);
},50)
jsfiddle: http://jsfiddle.net/hpq7rpnh/4/
Library: http://interactjs.io/
I am new to interactjs and I am trying to make the star drop on top of the tree (see jsfiddle) if it is snapped inside the dropzone. How would I do this?
Javascript:
interact('.draggable')
.draggable({
onmove: function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
},
onend: function (event) {
var textEl = event.target.querySelector('p');
textEl && (textEl.textContent =
'moved a distance of '
+ (Math.sqrt(event.dx * event.dx +
event.dy * event.dy)|0) + 'px');
}
})
.inertia(true)
.restrict({
drag: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
});
// enable draggables to be dropped into this
interact('.tree').dropzone({
// only accept elements matching this CSS selector
accept: '#star',
// Require a 75% element overlap for a drop to be possible
overlap: 0.75,
// listen for drop related events:
ondropactivate: function (event) {
// add active dropzone feedback
event.target.classList.add('drop-active');
},
ondragenter: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: .5,
height: "160px"
});
},
ondragleave: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: 1,
height: "186px"
});
},
ondrop: function (event) {
//Dropped event
},
ondropdeactivate: function (event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
})
.snap({
mode: 'anchor',
grid: { x: 20, y: 20 },
range: Infinity
});
Library:
http://interactjs.io/
Fiddle:
http://jsfiddle.net/hpq7rpnh/2/
The above won't work with the updated API. I forked a pen of Taye (the author of interact.js) and made it working.
See a possible solution here:https://codepen.io/eljefedelrodeodeljefe/pen/vybegM
if I see this right, one needs to set the target on dragenter, in any case the solution with the new API is, imo, much more verbose from an integrator POV.
event.draggable.draggable({
snap: {
targets: [dropCenter]
}
});
If there are still people struggling with this, this worked well for me!
https://github.com/taye/interact.js/issues/79
interact('.draggable')
.draggable({
onmove: function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
},
onend: function (event) {
var textEl = event.target.querySelector('p');
textEl && (textEl.textContent =
'moved a distance of '
+ (Math.sqrt(event.dx * event.dx +
event.dy * event.dy)|0) + 'px');
}
})
.inertia(true)
.restrict({
drag: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
});
interact('.draggable').snap({
mode: 'anchor',
anchors: [],
range: Infinity,
elementOrigin: { x: 0.5, y: 2 },
endOnly: true
});
// enable draggables to be dropped into this
interact('.tree').dropzone({
// only accept elements matching this CSS selector
accept: '#star',
// Require a 75% element overlap for a drop to be possible
overlap: 0.75,
// listen for drop related events:
ondropactivate: function (event) {
// add active dropzone feedback
event.target.classList.add('drop-active');
},
ondragenter: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
clearInterval(interval); // stop star rotation
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: .5,
height: "160px"
});
var dropRect = interact.getElementRect(event.target),
dropCenter = {
x: dropRect.left + dropRect.width / 2,
y: dropRect.top + dropRect.height / 2
};
event.draggable.snap({
anchors: [ dropCenter ]
});
},
ondragleave: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
$('.tree:not(.drop-target)').find('img').animate({
opacity: 1,
height: "186px"
});
event.draggable.snap(false);
},
ondrop: function (event) {
//Dropped event
},
ondropdeactivate: function (event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
})
//Start star rotation
var angle = 0;
var interval = setInterval(function(){
angle+=1;
$("#star img").rotate(angle);
},50)
Fiddle:
http://jsfiddle.net/hpq7rpnh/3/
The only thing I couldn't figure out is that the star gets on the small tree top position if you drag it to another tree while it's small.
I am trying to use the jQuery plugin: Floating boxes with easing and motion-blur in jQuery By: Marcell Jusztin.
I have it working just fine and understand how to tweak most attributes, but I am a Javascript rookie and really do not understand the mechanics involved in changing how it uses math to place the elements I want to animate. What I want to do is change the set x and y offset coordinates (which are in pixels of course) to a set of percentages so that the elements will dynamically scale in position based on screen resolution. Here is the script in its entirety:
jQuery.fn.floatingBox = function ( userOptions ) {
options = jQuery.extend ({
parent : 'backdrop',
stage : 'backdrop',
scale : 0.3,
xOffset : 0,
yOffset : 0,
blur : false,
isText : false,
blurColor : '#888',
frameRate : 40,
}, userOptions);
var parent = options.parent;
var stage = options.stage;
var scale = options.scale;
var xOffset = options.xOffset;
var yOffset = options.yOffset;
var blur = options.blur;
var isText = options.isText;
var blurColor = options.blurColor;
var frameRate = options.frameRate;
var midX = $('#' + stage).width() / 2;
var midY = $('#' + stage).height() / 2;
var _x = midX;
var _y = midY;
var xx = midX;
var yy = midY;
var objectId = $(this).attr('id');
$('#' + objectId).css('position','absolute');
shadowAmount = 0;
window["timer" + objectId] = window.setInterval(update,frameRate);
$('#' + parent).mousemove(function(event){
_x = event.pageX;
_y = event.pageY;
if( shadowAmount < 5 && blur == true ) shadowAmount += scale;
});
factor = scale * 0.5;
function update() {
xx += (((_x - midX) * -scale) - xx) * factor;
yy += (((_y - midY) * -scale) - yy) * factor;
$('#' + objectId).css('left', xx + xOffset + $('#' + parent).position().left);
$('#' + objectId).css('top', yy + yOffset + $('#' + parent).position().top);
if(blur){
if(!isText){
$('#' + objectId).css('box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-moz-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-webkit-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
$('#' + objectId).css('-o-box-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
}else{
$('#' + objectId).css('text-shadow', '0px 0px ' + shadowAmount + 'px ' + blurColor );
}
if(shadowAmount > 0 ) shadowAmount -= scale;
}
}
}
Here is the script that initiates the javascript in the HTML document:
<script type="text/javascript">
jQuery(function(){
$('#biglogo').floatingBox({
scale : 0.09,
blur : false,
isText : false,
xOffset : 400,
yOffset: 200,
});
$('#biglogo2').floatingBox({
scale : 0.08,
blur : false,
isText : false,
xOffset : 405,
yOffset: 205,
});
});
</script>
I have two transparent png files that are layered over each other with a minor offset of 5 pixels (or maybe its considered 10), but would rather the two images be centered in all browser windows and not just mine. The scale indicates how fast and far the elements move. The xOffset and yOffset parameters are of course fixed numbers that don't scale based on browser window size.
I have attempted to research this but ultimately, I'm neither finding that it can't be done, nor that it can because no one response seems to address the specific issue I am having. Perhaps I am not wording it correctly.
Thanks!
From the looks of the script I would say that it already takes the necessary calculations into accout. Try setting the parent and stage options and leave out the offset parameters. I.e
$('#biglogo').floatingBox({
parent: 'container-id',
stage: 'container-id',
scale: 0.09,
blur: false,
isText: false
});
Edit: I created a fiddle with some modifications to the plugin that shows how to get centering working, http://jsfiddle.net/wwBJt/