Managing dragging on rotated elements - javascript

it's my first post here, so be gentle with me ;)
I'm trying to make a simple editor using MooTools (still 1.2.5 though..). Every element has a drag corner to make it resizable.
The whole thing works really great, until the element is rotated. After giving it -moz-transform: rotate(Xdeg) property the drags are going crazy (simple example: http://jsfiddle.net/HTg57/1/)
I know why this happens - although element is rotated all events come as the element would be in normal position.
The question is - are there somewhere any libs which can handle this problem?
I think that I know how to solve the problem by myself, but it will take time, which I don't have.
So - are there any ready solutions to make dragging work properly when element is rotated?

not sure what you mean by 'work properly' but you really should look at this, which makes more sense (behaviour wise): http://jsfiddle.net/dimitar/HTg57/2/
var Box = new Class({
mEl: null,
mDragEl: null,
mDrag: null,
initialize: function(pEl) {
this.mEl = pEl;
this.createDrag();
},
createDrag: function() {
this.mDragEl = new Element('div', {
'class': 'drag'
}).inject(this.mEl);
this.mEl.makeResizable({
handle: this.mDragEl,
limit: {
x: [60,300],
y: [60,300]
}
});
}
});
new Box(document.getElement('div.box'));
new Box(document.getElement('div.rotate'));
it takes advantage of the element.makeResizable with a handle and a size limiter. it works fine when element is rotated as well. have fun...

Related

Creating a sliding image gallery that does not glitch on image change

I have created a sliding image gallery and when the button is pushed it slides the picture across and updates the image attribute for the relevant sections.
However this works perfectly like 50% of the time. The other times there is a second glitch and the images then go in place as expected.
I have attached the javascript methods for the animate method and the array change method. I have looked elsewhere and cannot see anyone else with a similar issue or where I am going wrong, especially when it doesn't happen often.
imageGallery.leftSelect.onclick = function () {
window.setTimeout(imageGallery.rightClick, 250);
imageGallery.animateImages('.image1', '.imageRight');
imageGallery.animateImages('.imageRight', '.imageNoneRight');
imageGallery.animateImages('.imageLeft', '.image1');
imageGallery.animateImages('.imageNoneLeft', '.imageLeft');
};
animateImages: function (classFrom, classTo) {
var classMoving = $(classFrom);
var classGoingTo = $(classTo);
classMoving.animate({
top: classGoingTo.css('top'),
left: classGoingTo.css('left'),
width: classGoingTo.css('width'),
opacity: classGoingTo.css('opacity'),
}, 258, function () {
console.log('Animated');
classMoving.css({"width":'', "opacity":'', "top":'', "left":'', });
});
},
rightClick: function () {
imageGallery.imagesDisplay.push(imageGallery.imagesDisplay.shift());
imageGallery.imageNoneLeft.setAttribute('src', imageGallery.imagesDisplay[2]);
imageGallery.imageLeft.setAttribute('src', imageGallery.imagesDisplay[1]);
imageGallery.imageMain.setAttribute('src', imageGallery.imagesDisplay[0]);
imageGallery.imageRight.setAttribute('src', imageGallery.imagesDisplay[10]);
imageGallery.imageNoneRight.setAttribute('src', imageGallery.imagesDisplay[9]);
},
Can someone assist, I really need this to work?
If there is anything not clear or you need more code let me know.
Thanks,
First things first, the culprit was the setAttribute of all images i.e. whatever you were doing inside the rightClick and leftClick functions were the reasons why you were seeing a glitch. Changing src of an img tag produces the glitch.
But then we cannot simply remove it because your approach relies heavily on this swapping of images.
I had to breakdown and really understand your approach first. The way it worked was that you would animate, for example, image1 (the centered one) to move to the position of imageLeft upon click on the rightCarousel button. On that same click, you had a setTimeout of almost the duration of the animation to call rightClick function. This rightClick function then swaps the images so that image1 can always remain at the center and only images can come and go after animation. This was the problem.
What I had to change was that all image tags i.e. imageNoneLeft, imageLeft, image1, imageRight & imageNoneRight would change each others classes such that their position remains changed after animations.
Also, I had to add another animateImages line inside your leftSelect and rightSelect callbacks to animate the furthest images i.e. imageNoneLeft & imageNoneRight to animate to each other's positions with respect to the click of the buttons.
Take a look at this jsFiddle. It will help you understand a lot better. And let me know if you have any questions.
JavaScript:
var imageGallery={
prefix:'https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/',
imagesDisplay:['JS.jpg','PIXI.jpg','GSAP.jpg','JS.jpg','PIXI.jpg','GSAP.jpg','JS.jpg','PIXI.jpg','GSAP.jpg','JS.jpg','PIXI.jpg'],
rightSelect:document.querySelector('.rightCarousel'),
leftSelect:document.querySelector('.leftCarousel'),
imageMain:document.querySelector('.image1'),
imageLeft:document.querySelector('.imageLeft'),
imageRight:document.querySelector('.imageRight'),
imageNoneLeft:document.querySelector('.imageNoneLeft'),
imageNoneRight:document.querySelector('.imageNoneRight'),
init:function(){
imageGallery.imagesDisplay.push(imageGallery.imagesDisplay.shift());
imageGallery.imageNoneLeft.setAttribute('src',imageGallery.prefix+imageGallery.imagesDisplay[2]);
imageGallery.imageLeft.setAttribute('src',imageGallery.prefix+imageGallery.imagesDisplay[1]);
imageGallery.imageMain.setAttribute('src',imageGallery.prefix+imageGallery.imagesDisplay[0]);
imageGallery.imageRight.setAttribute('src',imageGallery.prefix+imageGallery.imagesDisplay[10]);
imageGallery.imageNoneRight.setAttribute('src',imageGallery.prefix+imageGallery.imagesDisplay[9]);
},
animateImages:function(classFrom,classTo){
var classMoving=$(classFrom);
var classGoingTo=$(classTo);
classMoving.animate({
top:classGoingTo.css('top'),
left:classGoingTo.css('left'),
width:classGoingTo.css('width'),
opacity:classGoingTo.css('opacity')
},258,function(){
$(this).removeClass(classFrom.substr(1));
$(this).addClass(classTo.substr(1));
$(this).removeAttr('style');
});
}
};
imageGallery.init();
imageGallery.leftSelect.onclick=function(){
imageGallery.animateImages('.imageNoneRight','.imageNoneLeft');
imageGallery.animateImages('.imageRight','.imageNoneRight');
imageGallery.animateImages('.image1','.imageRight');
imageGallery.animateImages('.imageLeft','.image1');
imageGallery.animateImages('.imageNoneLeft','.imageLeft');
};
imageGallery.rightSelect.onclick=function(){
imageGallery.animateImages('.imageNoneLeft','.imageNoneRight');
imageGallery.animateImages('.imageLeft','.imageNoneLeft');
imageGallery.animateImages('.image1','.imageLeft');
imageGallery.animateImages('.imageRight','.image1');
imageGallery.animateImages('.imageNoneRight','.imageRight');
};

KineticJS images not working locally, sometimes work online

I'm testing KineticJS right now. I tried adding an image to the canvas following this tutorial. I changed a bit the code but it's relatively the same.
What's confusing is that locally it's not working at all...no images are displayed and no errors at all. Online is a different story, images are loaded BUT sometimes it looks like the images are not loading.
This is what I have: http://codepen.io/semajtwin/pen/nIafc
I thought maybe it was the browser as well, I tried on three different browsers (Chrome, Firefox and Internet explorer) but still ended up with the same result.
I just can't figure out what's wrong really.
Thanks in advance for any help.
#RobinvdA is correct that you need to give the images time to load.
Your draw draw_img(); and draw_img2(); are being called before the images are fully loaded.
The fix is to put the draw_img code inside onload, like this:
Here's some refactored code and a Demo: http://jsfiddle.net/m1erickson/fLPZt/
// declare sun_img outside `onload` so it's accessible later
var sun_img;
// create a Kinetic.Image of the sun
var sunReady = false;
var sunImage = new Image();
sunImage.onload = function () {
sun_img = new Kinetic.Image({
x: 0,
y: 0,
width: 200,
height: 200,
image: sunImage,
draggable: true
});
layer.add(sun_img);
layer.draw();
};
sunImage.src = "http://2.bp.blogspot.com/-GDMbp9j3iSo/Tgh24-ighVI/AAAAAAAAAgE/a4glfYd5-68/s200/radiantsunheliumballoon.jpg";

HTML5 Drag and Drop events and setDragImage browser support

I'm working on a small jQuery plugin that mimics the jQuery UI draggable/droppable behavior with native HTML5 drag and drop events.
A feature I'd want to add is the ability to specify the node which will serve as the drag proxy.
I did a bit of research, and according to MDN, to do this requires the use of setDragImage(), passing an image or an element.
What is the support for setDragImage in different browsers?
I've noticed there's a plugin named jquery.event.drag which takes a different than I expected to this problem.
Would this feature require me to make some kind of workaround like the above plugin, or should this be possible out-of-the-box in most or all browsers using setDragImage?
EDIT
After playing around a bit with this functionality, it would seem that this function is quite limited.
Besides having no support in quite a few browsers, using an arbitrary DOM element as the helper requires it to be in the DOM tree and visible, and so you have the element itself on the body, and a copy of it as the handler. This is mostly unwanted for this sort of plugin.
Further more, rendering is also problematic even when the right terms are met. When trying to create a helper from <span>TEST</span>, the helper itself only showed a white rectangle with the dimensions of the span.
Are these issues that were to be expected according to the specs? Could they be fixed in code or would they require a workaround?
setDragImage is IMO a vital feature for any non trivial drag and drop use case. e.g consider a multi select list where a drag needs to include all the selected items and not just the row that the drag gesture was made on. it's odd that the thing you want to set needs to be visible in the DOM but even worse is that this method is not implemented at all in IE as of version 11.
However, with a bit of effort I was able to get it working reasonably satisfactorily. The custom drag image node can be removed from the DOM in a timeout 0 function. so add it to the DOM in dragstart then use it in set drag image and then remove it. This works perfectly in FF but in chrome the drag image node will flicker before the timeout fires. One way to prevent this is to position it such that the actual browser generated drag image will appear in exactly the same place, this is not as bad as it sounds since you can control the position of the custom drag image relative to the cursor.
I was playing with this recently and was able to get it working on IE as well. the trick there is to get IE to drag the custom drag image node and not the node that dragstart fired on. you can do this with the IE specific dragDrop() method.
The final thing to be aware of is that on windows there is a 300px limit on the width of the custom drag image node this applies to all draggables not just the custom node actually. so the browser applies a heavy radial gradient if the drag image is too big.
http://jsfiddle.net/stevendwood/akScu/21/
$(function() {
(function($) {
var isIE = (typeof document.createElement("span").dragDrop === "function");
$.fn.customDragImage = function(options) {
var offsetX = options.offsetX || 0,
offsetY = options.offsetY || 0;
var createDragImage = function($node, x, y) {
var $img = $(options.createDragImage($node));
$img.css({
"top": Math.max(0, y-offsetY)+"px",
"left": Math.max(0, x-offsetX)+"px",
"position": "absolute",
"pointerEvents": "none"
}).appendTo(document.body);
setTimeout(function() {
$img.remove();
});
return $img[0];
};
if (isIE) {
$(this).on("mousedown", function(e) {
var originalEvent = e.originalEvent,
node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);
node.dragDrop();
});
}
$(this).on("dragstart", function(e) {
var originalEvent = e.originalEvent,
dt = originalEvent.dataTransfer;
if (typeof dt.setDragImage === "function") {
node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);
dt.setDragImage(node, offsetX, offsetY);
}
});
return this;
};
}) (jQuery);
$("[draggable='true']").customDragImage({
offsetX: 50,
offsetY: 50,
createDragImage: function($node) {
return $node.clone().html("I'm a custom DOM node/drag image").css("backgroundColor", "orange");
}
}).on("dragstart", function(e) {
e.originalEvent.dataTransfer.setData("Text", "Foo");
});
});

Twitter widgets customization

I'm doing a page here with Twitter widgets on the side. Well I'm really a newbie in using this widget and I don't have a single idea on customizing it this is how far I've gone. First it will appear like this:
Names will appear one by one every 30 seconds from top going down background is transparent. Please disregard the borders (sorry I can't give a decent picture)
Well then What I wanted to do is for it to appear like this one:
Well from top to down it will become bottom to top displaying around 5 or 6 names and font is also adjusted smallest to biggest and positioned left and right alternating position.
Any Ideas? I would also appreciate if you could give me a little lesson here. :)
EDIT: I forgot HTML and I'm using a Javascript on this one.
for _slide looks like this:
_slide: function(el) {
var that = this;
var height = getFirst(el).offsetHeight;
if (this.runOnce) {
new Animate(el, 'height', {
from: 380,
to: height,
time: 500,
callback: function()
{
that._fade.call(that, el);
}
}
).start();
}
return this;
},
Thanks!
Okay as you cant give any indication as to which widget you're using is difficult to help you reverse the order of the <li>'s specific to your widget, but here's how youd do it using jquery:
output = '<ul id="after">';
$($("li").get().reverse()).each(function() {
output += '<li>'+$(this).text()+'</li>';
});
$('body').append(output+'</ul>');
$("#after li:even").css({"float":"left", "clear":"right"});
$("#after li:odd").css({"float":"right", "clear":"left"});
$("#after li:nth-child(2)").css({"width":"320px", "font-size":"90%"});
$("#after li:nth-child(3)").css({"width":"260px", "font-size":"80%"});
$("#after li:nth-child(4)").css({"width":"180px", "font-size":"70%"});
$("#after li:nth-child(5)").css({"width":"100px", "font-size":"60%"});
See the coded example here - http://jsfiddle.net/ajthomascouk/6MQew/1

Simple window system with css3 and html5 is rendering slowly. how to speed it up?

I have this: http://jsfiddle.net/5r3Eh/10/show/ and than http://jsfiddle.net/5r3Eh/18/ but they are quite slow (on chrome 12, a bit better on 13).
Is there any way to do drag-drop of window with out jquery.event.drag-1.5.min.js and if possible without jquery at all? And how to implement it into my simple code http://jsfiddle.net/5r3Eh/10/:
$('#demo4_box').bind('dragstart', function(event) {
return $(event.target).is('.handle');
}).bind('drag', function(event) {
$(this).css({
top: event.offsetY,
left: event.offsetX
});
});
$(".resize").bind('dragstart', function(event) {
var $box = $(this).closest(".box");
$box.data("width", $box.width());
$box.data("height", $box.height());
$box.data("x", event.offsetX);
$box.data("y", event.offsetY);
}).bind("drag", function(event) {
var $box = $(this).closest(".box");
$box.width(Math.max($box.data("width") - $box.data("x") + event.offsetX, $box.data("minwidth")));
$box.height(Math.max($box.data("height") - $box.data("y") + event.offsetY, $box.data("minheight")));
});
The browser is re-drawing the entire background layer every time you drag by a pixel. You can confirm this by using the Chrome developer tools (Timeline): http://i.imgur.com/bzXj5.png
If you disable the box-shadow and re-profile, none of those rendering events fire. So, your problem is that you are causing the entire window to redraw. If you can cut down on that in some way, then your problem is solved.
However, doing this while achieving the look you want may be hard. The only thing I can think of that might work would be drawing a div behind your dialog for the box-shadow to be cast on. This div would be just large enough to receive the shadow, and would need an opaque background. In this case, the redraw may only affect the smaller dive instead of the entire background layer.
The bottom line is that box-shadow is expensive, try to avoid redraws like this.

Categories

Resources