I have an image that needs to be rotated. This image is oriented either landscape or portrait.
I have an HTML5 form to accept the degrees of rotation with a step 90 each click. When this value changes, the image should rotate and resize. It should always be 770px wide, but can be as tall as it needs to be.
I've written the following event handler, but it doesn't work the way I'd expect.
Use Case: When the image is portrait, it's initial values are 770x1027 (w x h). When rotating it 90 degrees, I would expect the below function to rotate the image, set the width = 1027 and height = 770. But what I'm seeing is that both width and height are being set to 770. What am I not seeing?
$("#degrees").change(function(){
var element$ = $("#photo-submission"),
w = element$.width(),
h = element$.height(),
deg = $(this).val();
element$.removeAttr("style").attr({
"style": "-webkit-transform:rotate("+ deg +"deg); width: "+ h +"px; height: "+ w + "px;"
})
});
You seem to have switched your width and height.
element$.removeAttr("style").attr({
"style": "-webkit-transform:rotate("+ deg +"deg); width: "+ w +"px; height: "+ h + "px;"
})
How about trying it with the jQuery method actually made for changing CSS properties, that way it would be easier to keep track of your variables and place them in the right places :
$("#degrees").change(function(){
var el = $("#photo-submission"),
w = el.width(),
h = el.height(),
deg = this.value;
el.css({
'-webkit-transform' : 'rotate(' +deg+ 'deg)',
width : w,
height : h
});
});
FIDDLE
The real advantage of this is that you don't have to set the width and height to what it already is, which is basically what you're doing, so this is enough
$("#degrees").change(function(){
$("#photo-submission").css({
'-webkit-transform' : 'rotate(' + this.value + 'deg)'
});
});
Related
I need help showing/hiding text on a button click (specifically an arrow). I have a block of text that I have hidden and I need to slide it down in a time consistent with the arrow rotating 180 degrees. I also want it to do this only for the post above the arrow that was clicked. The solution I have come up with in this fiddle has many problems.
Here is the code:
$(function () {
var angle = -180,
height = "100%";
$(".down-arrow").click(function () {
$(".down-arrow").css({
'-webkit-transform': 'rotate(' + angle + 'deg)',
'-moz-transform': 'rotate(' + angle + 'deg)',
'-o-transform': 'rotate(' + angle + 'deg)',
'-ms-transform': 'rotate(' + angle + 'deg)',
});
$(".blog-post").animate({
'height' : height
});
angle -= 180;
height = "50px";
});
});
And these are the issues I am having:
It slides down way too fast
Once it slides back up it won't slide down again.
It does it for every post
This would be more dynamic and clean to use:
First we will take height's of all the .blog-post div's in an array.
Now making height: 50px of the div, after once we know actual height of all the div's. Which will helpful in making div smooth slide as we know height's.
Next on click of arrow class, we will toggle class which holds transform:rotate properties. Along with that we would check corresponding .blog-post div's height. So if it is more than 50px we would make it 50px, else we would take it's actual height from array and give to it.
Here is the JS/JQuery Code:
var totalNum = $('.blog-post').length; // Counting number of .blog-post div on page.
var i, myArray = [];
for (i = 0; i < totalNum; i++) {
var curHeight = $('.blog-post:eq(' + i + ')').outerHeight();
myArray.push(curHeight);
}
$('.blog-post').css('height', '50px');
$('.down-arrow').click(function () {
$(this).toggleClass('invert');
var index = $('.down-arrow').index(this);
var heightCheck = $('.blog-post:eq(' + index + ')').outerHeight();
if (heightCheck < 51) {
$('.blog-post:eq(' + index + ')').css('height', myArray[index] + 'px');
} else {
$('.blog-post:eq(' + index + ')').css('height', '50px');
}
});
Working : Fiddle
If you still do not understand feel free to ask.
I guess you should convert the 100% to pixels (with $(this).parent().innerHeight() or something like that, then it works well.
You should build some sort of toggle: keep track of which blog-post/arrow is up and which one is down (flag the blog posts or the arrows with some sort of class) and based on that, you should let it slide up or down.
Of course, you're referring to the post with a css selector. You should use a combination of $(this), .next() and .prev() functions in order to get the right post(s).
"It slides down way too fast"
Just set an animation duration. See the jquery.animate() documentation.
It seems that jquery is pretty buggy when it comes to animating using percentages. http://bugs.jquery.com/ticket/10669 http://bugs.jquery.com/ticket/9505 Try using pixels instead of percentage http://jsfiddle.net/8obybt1d/1/
"Once it slides back up it won't slide down again."
Because you are not changing the value of height back to hundred%
A rough piece of code:
if (height == "50px") {
height = "100%";
}
else {
height == "50px"
}
"It does it for every post"
Try using the 'this' keyword.
To solve point 2:
$(".blog-post").animate({
...
height = (height === "50px") ? height = "100%": height = "50px";
});
I'm trying to create a jQuery script that changes background-position x px to the left or right according to mouse movements (starting from background-position:center).
Here's what I have so far: http://jsfiddle.net/multiformeingegno/KunZ4/530/
$("#salone").bind('mousemove', function (e) {
$(this).css({
backgroundPosition: e.pageX + 'px ' + e.pageY + 'px'
});
});
Problem is it doesn't start from background-position:center and when I move the mouse the background-image starts from mouse position and reveals the white background.
I'd like it to move from the center to the left/right according to mouse movements. And also adjust the speed of the background-position change (animate?).
Just subtract the position you want to start from:
backgroundPosition: (e.pageX-650) + 'px ' + (e.pageY-410) + 'px'
to change the speed adjust the factor for the mouse position:
backgroundPosition: (e.pageX*2-650) + 'px ' + (e.pageY*2-410) + 'px'
Is double as fast.
http://jsfiddle.net/KunZ4/538/
For the calculation of the background center you could just take the image path, append it to an invisible image and get the width and height.
var url = $('#myDiv').css('background-image').replace('url(', '').replace(')', '').replace("'", '').replace('"', '');
var bgImg = $('<img />');
bgImg.hide();
scope = this;
bgImg.bind('load', function()
{
scope.height = $(this).height();
scope.width = $(this).width();
});
$('#myDiv').append(bgImg);
bgImg.attr('src', url);
var centerX = scope.width/2;
var centerY = scope.height/2;
No you can use centerX and centerY to center your image.
Took the center calculation from here:
How do I get background image size in jQuery?
Imagine I have the below element appended to the document :
<html>
<head>
<style>
#resizable {
position: absolute;
top: 30px;
left: 30px;
background: url(http://www.some243x350image.jpg) no-repeat;
height: 243px;
width: 350px;
background-size: contain;
}
</style>
</head>
<body>
<div id="resizable"></div>
</body>
</html>
I'd like to be able to resize the above div proportionally, without any max/min height/width limits.
Below is the code I've written (Working Example : http://jsfiddle.net/7wYAh/) but it has two main bugs :
1. The div's height and width do not change proportionally all the time (even though the image obviously does, given that I'm using background-size: contain;.
2. There are sudden increases/decreases in the height/width of the element the moment the element is "grabbed".
I'm not using an aspect ratio variable. What I'm doing is that I choose randomly whether to resize based on height or width every time. So if the height changes then I'll resize the width based on the height increase. And vice versa. Isn't that proportional as well? Meaning that if the height increases by 2px, I'll increase the width by 2px as well and vice versa.
Looking for an answer to my problem I found this post but I don't want to use width/height limits and I don't understand the use of the ratio.
So can you spot anything wrong with this code (assume that the elementCanBeResized is set to true whenever the mouse grabs the bottom right corner of the div) :
Working Example : http://jsfiddle.net/7wYAh/
var $element = $('#resizable');
var previousResizeX, previousResizeY, resizeDistanceX, resizeDistanceY;
$(window).mousemove(function (mouseCoordinates)
{
if (!elementCanBeResized)
{
return;
}
if (typeof previousResizeX === 'undefined')
{
previousResizeX = mouseCoordinates.pageX;
previousResizeX = mouseCoordinates.pageY;
}
else
{
var newResizeX = mouseCoordinates.pageX;
var newResizeY = mouseCoordinates.pageY;
// resizing proportionally based on width change
if (newResizeX !== previousResizeX)
{
resizeDistanceX = newResizeX - previousResizeX;
previousResizeX = newResizeX;
previousResizeY += resizeDistanceX;
newWidth = $element.width() + resizeDistanceX;
newHeight = $element.height() + resizeDistanceX;
}
// resizing proportionally based on height change
else if (newResizeY !== previousResizeY)
{
resizeDistanceY = newResizeY - previousResizeY;
previousResizeY = newResizeY;
previousResizeX += resizeDistanceY;
newHeight = $element.height() + resizeDistanceY;
newWidth = $element.width() + resizeDistanceY;
}
$element.css({
height: newHeight,
width: newWidth
});
}
});
I assume that you want to resize by clicking at some point and then 'dragging' de mouse. Okay.
To question 2: You are storing the point where you click in previousResizeX. But I don't see you cleaning its value after the release of the button. If you don't set previousResizeX to 'undefined' again, next time you click there will be a 'sudden change' of width/height because newResizeX will be the distance between the place where you pressed the mouse the first time and its current position.
To question 1: You are increasing the width/height the same number of pixels every time, that's why your div doesn't resize proportionally. I explain: if you start with a div that's 200 x 100, its width is the double of the height. When you duplicate its width, to be proportional you have to duplicate the height. But if you drag your mouse 100px, you'll end with a (200+100) x (100 + 100) div, which is 300 x 200. The image's width is no longer the double of its height. You need to calculate the ratio between width and height at the beginning:
var ratio = $element.height() / $element.width();
...
resizeDistanceX = newResizeX - previousResizeX;
resizeDistanceY = resizeDistanceX * ratio;
previousResizeX = newResizeX;
previousResizeY += resizeDistanceY;
newWidth = $element.width() + resizeDistanceX;
newHeight = $element.height() + resizeDistanceY;
...
//For Y
resizeDistanceY = newResizeY - previousResizeY;
resizeDistanceX = resizeDistanceY / ratio;
previousResizeY = newResizeY;
previousResizeX += resizeDistanceX;
newHeight = $element.height() + resizeDistanceY;
newWidth = $element.width() + resizeDistanceX;
And remember to set resizeDistanceX and resizeDistanceY once the mouse is released.
Hope this helps you.
Something I've wanted to learn for quite a time now, but haven't been able to figure out.
http://jsfiddle.net/Mobilpadde/Xt7ag/
Then you move the mouse, it follows, which is the easy part, but I want to rotate too, like always look in the direction of the mouse, but not so static, more like, if you move your mouse up, it should kinda rotate first, and then you move the mouse further away, it should begin to follow again (If you know what I mean).
Is that something simple to do, or 3k lines? (Or maybe a jQuery plugin?)
Hiya I got it something more closer by using an old post of mine : demo http://jsfiddle.net/Z3pGQ/3/
I am still working, will flick you more smoother version or if you can improve before me:
Old post: Rotating an element based on cursor position in a separate element
Hope it helps, I am trying to make it smoother now, cheers
Sample code
$(document).ready(function() {
$(document).mousemove(function(e) {
$(".firefly").css({
"top": (e.pageY * 2) + "px",
"left": (e.pageX * 2 + 130) + "px"
});
})
})
var img = $(".firefly");
if (img.length > 0) {
var offset = img.offset();
function mouse(evt) {
var center_x = (offset.left) + (img.width() / 2);
var center_y = (offset.top) + (img.height() / 2);
var mouse_x = evt.pageX;
var mouse_y = evt.pageY;
var radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
var degree = (radians * (180 / Math.PI) * -1) + 90;
img.css('-moz-transform', 'rotate(' + degree + 'deg)');
img.css('-webkit-transform', 'rotate(' + degree + 'deg)');
img.css('-o-transform', 'rotate(' + degree + 'deg)');
img.css('-ms-transform', 'rotate(' + degree + 'deg)');
}
$(document).mousemove(mouse);
}
Image
This is going to involve a lot more math than I want to do right now, but you can apply rotations with css easily. Here are the properties for mozilla and webkit, you can see the rest of the (IE,Opera...) at this page. Here is your function with a 120deg rotation applied. You will still need to calculate the proper rotation, and adjust the left and top accordingly.
$(document).mousemove(function(e){
$(".firefly").css({
"top":(e.pageY*2)+"px",
"left":(e.pageX*2+130)+"px",
"-moz-transform": "rotate(120deg)",
"-webkit-transform": "rotate(120deg)"});
})
There is a jQuery plugin for that http://pixelscommander.com/en/iphone-development/rotate-html-elements-with-mouse/
This seems like it should be quite simple, but for some reason I can't quite wrap my brain around it. I have an image inside a "viewport" div, of which the overflow property is set to hidden.
I've implemented a simple zooming and panning with jQuery UI, however I am having trouble getting the zoom to appear to originate from the center of the viewport. I did a little screencast from Photoshop the effect I'm trying to reproduce: http://dl.dropbox.com/u/107346/share/reference-point-zoom.mov
In PS you can adjust the scaling reference point an the object will scale from that point. Obviously this is not possible with HTML/CSS/JS, so I'm trying to find the appropriate left and top CSS values to mimic the effect.
Here is the code in question, with a few unnecessary bits removed:
html
<div id="viewport">
<img id="map" src="http://dl.dropbox.com/u/107346/share/fake-map.png" alt="" />
</div>
<div id="zoom-control"></div>
javascript
$('#zoom-control').slider({
min: 300,
max: 1020,
value: 300,
step: 24,
slide: function(event, ui) {
var old_width = $('#map').width();
var new_width = ui.value;
var width_change = new_width - old_width;
$('#map').css({
width: new_width,
// this is where I'm stuck...
// dividing by 2 makes the map zoom
// from the center, but if I've panned
// the map to a different location I'd
// like that reference point to change.
// So instead of zooming relative to
// the map image center point, it would
// appear to zoom relative to the center
// of the viewport.
left: "-=" + (width_change / 2),
top: "-=" + (width_change / 2)
});
}
});
Here is the project on JSFiddle: http://jsfiddle.net/christiannaths/W4seR/
Here's the working solution. I will explain the logic at the next edit.
Function Logic:
Summary: Remember the center position of the image, relatively.
The calculations for width and height are similar, I will only explain the height calculationThe detailled explanation is just an example of function logic. The real code, with different variable names can be found at the bottom of the answer.
Calculate the center (x,y) of the #map, relative to #viewport. This can be done by using the offset(), height() and width() methods.
// Absolute difference between the top border of #map and #viewport
var differenceY = viewport.offset().top - map.offset().top;
// We want to get the center position, so add it.
var centerPosition = differenceY + viewport.height() * 0.5;
// Don't forget about the border (3px per CSS)
centerPosition += 3;
// Calculate the relative center position of #map
var relativeCenterY = centerPosition / map.height();
// RESULT: A relative offset. When initialized, the center of #map is at
// the center of #viewport, so 50% (= 0.5)
// Same method for relativeCenterX
Calculate the new top and left offsets:
// Calculate the effect of zooming (example: zoom 1->2 = 2)
var relativeChange = new_width / old_width;
// Calculate the new height
var new_height = relativeChange * old_height;
// Calculate the `top` and `left` CSS properties.
// These must be negative if the upperleft corner is outside he viewport
// Add 50% of the #viewport's height to correctly position #map
// (otherwise, the center will be at the upperleft corner)
var newTopCss = -relativeCenterY * new_height + 0.5 * viewport.height();
Change the CSS property
map.css("top", newTopCss);
Demo: http://jsfiddle.net/W4seR/12/
var map = $('#map');
var viewport = $('#viewport');
// Cache the size of the viewport (300x300)
var viewport_size = {
x: viewport.width(),
y: viewport.height()
};
map.draggable();
$('#zoom-control').slider({
min: 300,
max: 1020,
value: 300,
step: 24,
create: function() {
map.css({
'width': 300,
'left': 0,
'top': 0
});
},
slide: function(event, ui) {
var old_width = map.width();
var old_height = map.height();
var viewport_offset = viewport.offset();
var offset = map.offset();
offset = {
top: viewport_offset.top - offset.top + .5*viewport_size.y +3,
left: viewport_offset.left - offset.left + .5*viewport_size.x +3
};
// Relative offsets, relative to the center!
offset.top = offset.top / old_height;
offset.left = offset.left / old_width;
var new_width = ui.value;
var relative = new_width / old_width;
var new_height = relative * old_height;
offset = {
top: -offset.top * new_height + .5*viewport_size.y,
left: -offset.left * new_width + .5*viewport_size.x
};
var css_properties = {
width: new_width,
left: offset.left,
top: offset.top
};
map.css(css_properties);
trace((map.position().left));
}
});
I have always relied on the kindness of strangers. Pertinent changes:
// Calculate the offset as a percentage, accounting for the height of the window
var x_offset = ((map.position().left-150))/(old_width/2);
var y_offset = ((map.position().top-150))/(old_width/2);
var css_properties = {
width: new_width,
// Set the offset based on the existing percentage rather than 1/2
// then readjust for the height of the window
left: (new_width * x_offset /2 ) + 150 + "px",
top: (new_width * y_offset /2 ) + 150 + "px"
};
Replace the hardcoded 150 with a variable set on viewport instantiation if necessary.
Here is a quick working version:
http://jsfiddle.net/flabbyrabbit/chLkZ/
Probably not the neatest solution but seems to work nicely, hope it helps.
Update: sorry this only works if zoom is 0 when the map is moved.