I have been working on a game project for a while and have hit a snag with a particular control. I have decided to change some of the mechanics a bit to deal with this. I had written a chunk of code to make an object rotate with my mouse movement but now I need to make my object rotate on keypress.
I want to make it rotate 45 degrees clockwise when I press the right arrow key, and 45 degrees counter clockwise on left arrow key press. I have the input key call all written up I just need to translate my old code to the new code.
This is my existing code
window.onmouseclick = function(event) {
var box = hypeDocument.getElementById('bolt')
cx = event.pageX; // Mouse X
cy = event.pageY; // Mouse Y
bx = parseInt(hypeDocument.getElementById('group').style.left);
by = parseInt(hypeDocument.getElementById('group').style.top);
tx = hypeDocument.getElementProperty(box, 'left') +
(hypeDocument.getElementProperty(box, 'width')/2) + bx;
ty = hypeDocument.getElementProperty(box, 'top') +
(hypeDocument.getElementProperty(box, 'height')/2) + by;
angle = Math.atan2((cy-ty),(cx-tx)) * (180/Math.PI) ; // AHHHH MATH!
hypeDocument.setElementProperty(box, 'rotateZ', angle)
}
hypeDocument.setElementProperty(box, 'rotateZ', angle) // hype api code for
box.style.webkitTransform = "rotate(" + angle + "deg)";
box.style.mozTransform = "rotate(" + angle + "deg)";
box.style.transform = "rotate(" + angle + "deg)";
This is the code I want to change, as I state in the comment the last line is hype api for the 3 box styles below it to help anybody who reads this understand what that line is.
I'm not sure about the hypedocument markup, but I put this together for you. Can you extract the meaningful parts re: the keycodes to make it work with your project?
window.addEventListener('keyup',function(e) {
var keyCode = e.keyCode,
dir = '',
box = document.getElementById('box');
if (keyCode == 39) {
dir = 'left';
} else if (keyCode == 37) {
dir = 'right';
}
box.setAttribute('data-dir','');
setTimeout(function() {
box.setAttribute('data-dir',dir);
})
})
#box {
width: 100px;
height: 100px;
background: black;
transform: rotate(0);
}
[data-dir="left"] {
animation: left .5s forwards;
}
[data-dir="right"] {
animation: right .5s forwards;
}
#keyframes left {
from {
transform: rotate(0);
}
to {
transform: rotate(90deg);
}
}
#keyframes right {
to {
transform: rotate(-90deg);
}
}
<div id="box"></div>
Related
The problem is solved when adding angles individually and then using ttheta(without calling a function to add angles and than using ttheta), but can anyone tell about why using function here is wrong or what problem is this function causing
The issue is solved by using this:
dtransform = window.getComputedStyle(leg1, null).getPropertyValue("transform");
values = dtransform.split('(')[1].split(')')[0].split(',');
dtheta = Math.round(Math.atan2(values[1], values[0]) * (180 / Math.PI));
dtransform1 = window.getComputedStyle(leg2, null).getPropertyValue("transform");
values1 = dtransform1.split('(')[1].split(')')[0].split(',');
dtheta1 = Math.round(Math.atan2(values1[1], values1[0]) * (180 / Math.PI));
ttheta = dtheta + dtheta1;
Instead of using function.
What I am trying to achieve is to get value of end points of an element when it is rotated from left and top of browser.
X & Y values are max-distance of end points of shoe
I get right values at some points and wrong at some. I tried to add angle from the parent element but that also don't solve the problem.
This is the related answer from which I had taken help
To check values are right or wrong I added an event to get clientX of mouse click. And values of element positions are taken when Try button is clicked.
Am I doing something wrong, any insights will be really helpful
let leg1 = document.querySelector(".Leg1Shoe")
let leg2 = document.querySelector(".Leg1Part")
let animeAll = document.querySelectorAll(".allClass")
let animePause = false
let ttheta = 0;
function getPos() {
if (!animePause) {
animeAll.forEach(e => {
e.classList.add("AnimatePaused");
})
animePause = true;
} else {
animeAll.forEach(e => {
e.classList.remove("AnimatePaused");
})
animePause = false;
}
let h, w, x, dx, tx, y, dy, ty = "";
leg1.style.outline = "1px solid red"
h = leg1.offsetHeight;
w = leg1.offsetWidth;
x = leg1.getBoundingClientRect().left;
y = leg1.getBoundingClientRect().top;
func2(leg2);
func2(leg1);
dx = (Number(h * (Math.sin(ttheta * (Math.PI / 180)))) + Number(w * (Math.cos(ttheta * (Math.PI / 180))))).toFixed(2);
dy = (Number(w * (Math.sin(ttheta * (Math.PI / 180)))) + Number(h * (Math.cos(ttheta * (Math.PI / 180))))).toFixed(2);
tx = (Number(x) + Number(Math.abs(dx))).toFixed(2);
ty = (Number(y) + Number(Math.abs(dy))).toFixed(2);
console.log("X:" + tx, "Y:" + ty);
}
function func2(e) {
let dtransform, dtheta, values = "";
dtransform = window.getComputedStyle(e, null).getPropertyValue("transform");
if (dtransform != "none") {
values = dtransform.split('(')[1].split(')')[0].split(',');
dtheta = Math.round(Math.atan2(values[1], values[0]) * (180 / Math.PI));
} else {
dtheta = 0;
};
ttheta = Number(ttheta) + Number(dtheta);
}
leg1.addEventListener('click', mousePos);
function mousePos(e) {
console.log("X:" + e.clientX, "Y:" + e.clientY)
}
.Leg1Part {
position: relative;
left: 100px;
top: 43px;
width: 20px;
height: 75px;
background-color: green;
transform-origin: top center;
animation: animateLeg1Part 5.0s linear infinite alternate;
}
#keyframes animateLeg1Part {
0% {
transform: rotate(40deg);
}
25% {
transform: rotate(25deg);
}
50% {
transform: rotate(10deg);
}
75% {
transform: rotate(30deg);
}
100% {
transform: rotate(60deg);
}
}
.Leg1Shoe {
position: absolute;
left: 0px;
top: 73px;
width: 40px;
height: 20px;
background-color: blue;
transform-origin: center left;
animation: animateLeg1Shoe 5.0s linear infinite alternate;
}
#keyframes animateLeg1Shoe {
0% {
transform: rotate(15deg);
}
50% {
transform: rotate(-20deg);
}
100% {
transform: rotate(30deg);
}
}
.AnimatePaused {
animation-play-state: paused;
}
<div class="Leg1Part allClass">
<div class="Leg1Shoe allClass"></div>
</div>
<button onclick="getPos()">Try</button>
Thanks for help in advance
This is not a simple answer that can give you a complete solution, but just an outline of the process you can follow.
You get the transformation matrices for the "leg" and the "shoe", as you already do, by calling getPropertyValue("transform") This gives you a string like this: matrix(-0.568718, 0.822533, -0.822533, -0.568718, 0, 0), this is a shortened form of a 3x3 transformation matrix:
| cos(theta) -sin(theta) 0 |
| sin(theta) cos(theta) 0 |
| 0 0 1 |
Parse the string and create a 2d array for this matrix. Note: since you don't have any translation (two zeros in the last column) you can operate on 2x2 matrices.
Multiple the transformation matrices for the "leg" and the "shoe". It's a tedious process, and you can use the mathjs library to help.
Multiply the resulting transformation matrix by the vector of each point's original coordinates. This will give you the coordinates of the point with all rotations applied.
Here are some references:
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix()
https://en.wikipedia.org/wiki/Affine_transformation
http://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf
https://en.wikipedia.org/wiki/Matrix_multiplication_algorithm
I am currently trying to figure out a way to rotate an object along axis relative to the user and not relative to the object. I'm doing this with Javascript (jQuery) and CSS transform rotate.
I have built a codepen for to test it out.
var bX = 0; //bufferX (user scroll input)
var bY = 0; //bufferY (user scroll input)
var cX = 0; //currentX (effective X rotation)
var cY = 0; //currentY (effective Y rotation)
var bBX = 0; // same second rotation properties
var bBY = 0;
var cBX = 0;
var cBY = 0;
var cBZ = 0; // currentZ (effective Z rotation)
var pi = 3.1416
// Fidget animation
function fidget() {
if (!(bX + bY == 0)) {
var dX = bX * 0.1; // how much we rotate this frame
var dY = bY * 0.1;
cX = (cX + dX) % (2 * pi); // set rotation value
cY = (cY + dY) % (2 * pi);
bX -= dX; // update buffer
bY -= dY;
}
$('#one').css('transform', 'rotateX(' + cX + 'rad) rotateY(' + cY + 'rad)');
window.requestAnimationFrame(fidget);
}
function fidgetB() {
if (!(bBX + bBY == 0)) {
var dBX = bBX * 0.1;
cBX = (cBX + dBX) % (2 * pi);
var rBY = Math.cos(cBX); //Y ratio
var rBZ = Math.sin(cBX); //Z ratio
var dBY = bBY * 0.1; // deltaY
var dBZ = bBY * 0.1;
cBY = (cBY + rBY * dBY) % (2 * pi); // current
cBZ = (cBZ - rBZ * dBZ) % (2 * pi);
bBX -= dBX; // buffer
bBY -= (dBY);
}
$('#two').css('transform', 'rotateX(' + cBX + 'rad) rotateY(' + cBY + 'rad) rotateZ(' + cBZ + 'rad)');
window.requestAnimationFrame(fidgetB);
}
var init = function () {
// Fidget
requestAnimationFrame(fidget);
requestAnimationFrame(fidgetB);
// scroll detection script
!function(window,document){var prefix="",_addEventListener,support;function _addWheelListener(elem,eventName,callback,useCapture){elem[_addEventListener](prefix+eventName,"wheel"==support?callback:function(originalEvent){!originalEvent&&(originalEvent=window.event);var event={originalEvent:originalEvent,target:originalEvent.target||originalEvent.srcElement,type:"wheel",deltaMode:"MozMousePixelScroll"==originalEvent.type?0:1,deltaX:0,deltaY:0,deltaZ:0,preventDefault:function(){originalEvent.preventDefault?originalEvent.preventDefault():originalEvent.returnValue=!1}};return"mousewheel"==support?(event.deltaY=-.025*originalEvent.wheelDelta,originalEvent.wheelDeltaX&&(event.deltaX=-.025*originalEvent.wheelDeltaX)):event.deltaY=originalEvent.deltaY||originalEvent.detail,callback(event)},useCapture||!1)}window.addEventListener?_addEventListener="addEventListener":(_addEventListener="attachEvent",prefix="on"),support="onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll",window.addWheelListener=function(elem,callback,useCapture){_addWheelListener(elem,support,callback,useCapture),"DOMMouseScroll"==support&&_addWheelListener(elem,"MozMousePixelScroll",callback,useCapture)}}(window,document);
window.addWheelListener(window, function (e) {
e.preventDefault();
bY -= e.deltaX / window.innerWidth;
bX += e.deltaY / window.innerWidth;
bBY -= e.deltaX / window.innerWidth;
bBX += e.deltaY / window.innerWidth;
});
};
jQuery(document).ready(function ($) {
init();
});
html, html * {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color:white;
text-align: center;
font-size: 6vmin;
font-family: sans-serif;
}
#intro {
position:absolute;
width: 100%;
height: 100%;
-webkit-perspective: 200vmax;
perspective: 200vmax;
-webkit-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
transform-style: preserve-3d;
}
#one {
left: 33%;
}
#two {
left: 66%;
}
.square {
background-color: black;
width: 50vmin;
height: 50vmin;
line-height: 50vmin;
top: 50%;
margin-top: -25vmin;
margin-left: -25vmin;
transform-style: preserve-3d;
position: absolute;
-webkit-backface-visibility: visible;
backface-visibility: visible;
-webkit-transform-origin: 50% 37%;
transform-origin: 50% 37%;
/* -webkit-animation: rotate 25s linear infinite;
animation: rotate 25s linear infinite; */
pointer-events: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="intro">
<div id="one" class="square">Object</div>
<div id="two" class="square">User</div>
</div>
[https://codepen.io/rsepierre/pen/XqVJKR][1]
To control the rotation of any of those square you scroll with the mousewheel/touchpad (shift+wheel to scroll Y axis. Would add touchsupport when sorted out)
The left square's rotation is relative to the object:
if you only scroll left<->right, no problem, it works. Same for up<->down.
Now if you lay the item flat (scroll 90° down<->up ) and then you try to rotate on the other axis ( left<->right ), it will rotate on itself. Which mean that to the user it will appear like a Z-axis rotation (like a clock).
The right square's rotation is my attempt to make the rotation
relative to the user :
if you scroll left<->right, no problem, it works. Same for up<->down.
if you lay the item flat again (scroll 90° down<->up ) and then you try to rotate on the other axis ( scroll left<->right ), it will rotate relative to the user.
The item rotates on the "Z" axis, but will appears like a Y axis rotation from the users perspective.
And it is actualy working :
IF you only make scroll up<->down by 90° steps and never get in between.
Even if you get a 89° angle instead of a 90° angle when you scroll up<->down, it will slowly become a mess.
My best bet for a solution :
I came to understand that 3D rotations are not commutative (the order in which you apply rotations will impact the final result, this is why only the Y-axis rotation gets screwed up, and the X-axis rotation never does).
One easy fix would be to just add each new user input into a new rotation (rotateX(100) rotateY(5) rotateY(20) rotateX(105)... indefinitly.
But obviously i'm doing this 60times per second, it would very quickly become the worste CPU/GPU leek you've seen in a while.
Because of this I believe that somehow I should do the all the math behind the scene in JS and apply only one rotate3D(X,Y,Z,angle) css rotation.
Thing is I don't know anything about the math behind rotation matrices.
I found this converter to translate 3D rotation things into others 3D rotation things, but I think I would need to understand what is what to begin to do any math.
Any help much apreciated.
Found this stackoverflow post. It's not exactly the same situation but really the same problem.
Will post updated code when I get there.
meanwhile :
Rotating CSS cube on fixed axes
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I want to continuously rotate an HTML5 image or div using CSS3 animation effects.
Need the javascript to perform all of the basic functions related to this:
1) Set rotation speed of the image.
2) Get the current rotation value, in degrees.
3) Start and stop rotation.
If possible, please provide a working example of the html, css, js. A js class would be lovely.
Thanks very much.
Here is a working example of some of the features that you asked for.
The features that are not present are pretty easy to implement.
It's a very basic implementation.
Please run it on codepen.io otherwise the stylesheet reference will not work.
http://codepen.io/chocobowings/full/qOOzry/
//console.log(document.styleSheets[2]);
// find the right style sheet //
var rule = document.styleSheets[2].cssRules[1];
//console.log(rule);
function change(){
// first remove the old rules //
rule.deleteRule("0%");
rule.deleteRule("100%");
var angle1 = "-360deg"
var angle2 = "720deg"
// then add new rules //
rule.appendRule("0% { border-radius:0%; transform: rotate("+ angle1 + ");}");
rule.appendRule("90% { border-radius:30%; transform: rotate("+ angle2 + ");}");
// log the variable after the changes //
// console.log(rule);
// log the rules new text //
// you can extract from the cssText any information that you need
// console.log(rule.cssRules[0].cssText);
// console.log(rule.cssRules[1].cssText);
}
function get()
{
//console.log(document.styleSheets[2]);
var el = document.getElementById("a");
var st = window.getComputedStyle(el, null);
var tr = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform") ||
"FAIL";
// With rotate(30deg)...
// matrix(0.866025, 0.5, -0.5, 0.866025, 0px, 0px)
console.log('Matrix: ' + tr);
// rotation matrix - http://en.wikipedia.org/wiki/Rotation_matrix
var values = tr.split('(')[1].split(')')[0].split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
var scale = Math.sqrt(a*a + b*b);
console.log('Scale: ' + scale);
// arc sin, convert from radians to degrees, round
var sin = b/scale;
// next line works for 30deg but not 130deg (returns 50);
// var angle = Math.round(Math.asin(sin) * (180/Math.PI));
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
console.log('Rotate: ' + angle + 'deg');
}
.a {
background-color: #344565;
width: 500px;
height: 500px;
position: absolute;
left:30vw;
top: 30vh;
animation: move 20s infinite;
}
#keyframes move {
0% {
border-radius:0%;
transform: rotate(360deg);
}
100% {
border-radius:30%;
transform: rotate(-720deg);
}
}
<button onclick="change()">Change Values</button>
<button onclick="get()">Get Angle</button>
<div class="a" id="a">
</div>
I have a jQuery function that loops. What I want to do is for the $bird_wing_left element to rotate 30 degrees and then rotate back to 0 degree (in an infinite loop).
$(document).ready(function() {
var rotate = 0;
setInterval(function(){
rotate = 30;
$bird_wing_left.css({ transform: "rotate(" + rotate + "deg)" }).delay(1000).queue(function(){
rotate = 0;
$(this).css({ transform: "rotate(" + rotate + "deg)" });
});
}, 3000);
});
The first time it did rotate 30 degrees, then to 0 degrees, then to 30 degrees. However, afterwards, it seems to ignore the callback (which resets the degree value to 0), hence, it just keeps on being at 30 degrees on and on.
What could be the issue?
This is the jsFiddle: https://jsfiddle.net/iamacatperson/86z26hdw/
When you queue a function, within the function you have to dequeue (or call "next", more below) to allow the queue to continue processing (as shown in the examples). Just add $(this).dequeue() within your queue callback:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function() {
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
}).dequeue(); // <====================
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Alternately, since jQuery 1.4 the queue callback has been given an argument (traditionally called next) it can call to keep the queue going:
var $bird_wing_left = $("#wing");
$(document).ready(function() {
var rotate = 0;
setInterval(function() {
rotate = rotate + 30;
$bird_wing_left.css({
transform: "rotate(" + rotate + "deg)"
}).delay(1000).queue(function(next) { // <=====
rotate = rotate - 30;
$(this).css({
transform: "rotate(" + rotate + "deg)"
});
next(); // <=====
});
}, 3000);
});
body {
padding-top: 2em;
}
<div id="wing" style="width: 10em">Bird wing</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Side note: You can use += and -= if you like, e.g. rotate += 30; and rotate -= 30;
Quick fix could be to check rotate variable value before setting it.
if(rotate == 0)
rotate = rotate + 30;
else
rotate = 0;
By default, the css rotate property seems to occur after tag spacing. For instance, if you have two divs in a column and you rotate one, they overlap. It's possible I completely missed some aspect of css or html that handles this issue, have I?
The obvious solution seems to be to write some javascript to manage the placement of elements post rotate. Does a plugin exist that helps handle this spacing? The only thing close I could locate was the jquery-rotate plug, but it does not seems to provide any functionality with regard to spacing.
Relevant html/css demonstrating the spacing problem.
HTML
<div class="red-box rotate-right"></div>
<div class="blue-box"></div>
CSS
.rotate-right {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.red-box{
height: 50px;
width: 100px;
background: red;
}
.blue-box{
height: 50px;
width: 100px;
background: blue;
}
Alright, beware this is ugly to look at.
First, I used code from CSS-Tricks to get the angle of rotation. Then, I use some algebra to find the distance (from the center of the rotated element) to the sides of a box that contains the element. Then I add margins to the edge of the rotated element to create (or remove) extra space where needed. This also takes into account the original margins (if any).
Usage:
After rotating an element, call $(rotatedElement).space([grow],[shrink]). See code comments for argument descriptions.
jQuery.fn.space = function(grow,shrink){
// grow = Grow area around element to fit? (true/false)
// shrink = Shrink area around element to fit? (true/false)
var el = this.get(0);
if(typeof(grow)=='undefined'){
grow = true; // Default to grow extra space when needed
}
if(typeof(shrink)=='undefined'){
shrink = false; // Default to not shrink at all
}
//Get angle of rotated element
var st = window.getComputedStyle(el, null);
var tr = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform");
var v = tr.split('(')[1].split(')')[0].split(',');
var scale = Math.sqrt(v[0]*v[0] + v[1]*v[1]);
var angle = Math.round(Math.atan2(v[1], v[0]) * (180/Math.PI));
//Save or recall original margins
var m = new Array();
if(el.getAttribute('margins')==null){
m[0] = st.getPropertyValue("margin-left").match(/\d+/);
m[1] = st.getPropertyValue("margin-right").match(/\d+/);
m[2] = st.getPropertyValue("margin-top").match(/\d+/);
m[3] = st.getPropertyValue("margin-bottom").match(/\d+/);
el.setAttribute('margins',m[0]+","+m[1]+","+m[2]+","+m[3]);
} else {
m = el.getAttribute('margins').split(',');
console.log(m);
}
//Get center coords
var cx = st.getPropertyValue("width").match(/\d+/)/2;
var cy = st.getPropertyValue("height").match(/\d+/)/2;
//Convert radian values to degrees
function toDeg(angle){
return angle*Math.PI/180;
}
// Coords of the corners
// (starting from top-left and proceeding clockwise)
// relative to the center of the element
// c[cornerID][x|y]
var c = [ [Math.round(cx*Math.cos(toDeg(angle-180))
+ cy*Math.cos(toDeg(angle-90))),
Math.round(cx*Math.sin(toDeg(angle-180))
+ cy*Math.sin(toDeg(angle-90)))],
[Math.round(cx*Math.cos(toDeg(angle))
+ cy*Math.cos(toDeg(angle-90))),
Math.round(cx*Math.sin(toDeg(angle))
+ cy*Math.sin(toDeg(angle-90)))],
[Math.round(cx*Math.cos(toDeg(angle))
+ cy*Math.cos(toDeg(angle+90))),
Math.round(cx*Math.sin(toDeg(angle))
+ cy*Math.sin(toDeg(angle+90)))],
[Math.round(cx*Math.cos(toDeg(angle-180))
+ cy*Math.cos(toDeg(angle+90))),
Math.round(cx*Math.sin(toDeg(angle-180))
+ cy*Math.sin(toDeg(angle+90)))]
];
var elx = ([c[0][0], c[1][0], c[2][0], c[3][0]]).sort(function(a,b){
return(a*1)-(b*1);});
var ely = ([c[0][1], c[1][1], c[2][1], c[3][1]]).sort(function(a,b){
return(a*1)-(b*1);});
var b = [-elx[0], elx[3], -ely[0], ely[3]]; // [Left, Right, Top, Bottom]
if(grow){
if(b[0]-cx>0) el.style.marginLeft = (m[0] + b[0]-cx) + "px";
if(b[1]-cx>0) el.style.marginRight = (m[1] + b[1]-cx) + "px";
/*}
if(growY){ */
if(b[2]-cy>0) el.style.marginTop = (m[2] + b[2]-cy) + "px";
if(b[3]-cy>0) el.style.marginBottom = (m[3] + b[3]-cy) + "px";
}
if(shrink){
if(b[0]-cx<0) el.style.marginLeft = (m[0] + b[0]-cx) + "px";
if(b[1]-cx<0) el.style.marginRight = (m[1] + b[1]-cx) + "px";
/*}
if(shrinkY){ */
if(b[2]-cy<0) el.style.marginTop = (m[2] + b[2]-cy) + "px";
if(b[3]-cy<0) el.style.marginBottom = (m[3] + b[3]-cy) + "px";
}
}
You may wish to split (grow and shrink) into (growX, growY and shrinkX, shrinkY) depending on what's going on in your live site, so you don't break your layout. To do so, just adjust/add the arguments and defaults at the top, and the if(grow)/if(shrink) statements at the bottom.