Is There Js Plugin Convert the Matrix Parameter to CSS3 Transform Property

Is there js plugin convert the matrix parameter to css3 transform property?

Numbers you're getting are the result of multiplying Rotation and Translation matrices.

Although for your case you could get by easily by doing the math on paper and getting the formulas you need by hand, for increasing number of terms it would be a teadious task (you need to know the structure of original trasforms in order to reverse them as well).

Here's a link that will help you:

http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/

Why not just set those value you need from Javascript code and therefore eliminate need for geting them from matrix at all?

Get the applied css property-identifiers

Got it...

Quite simple:

var getIdentifier = function(str) {
return str.split('(')[0];
};

getIdentifier( 'rect(300px 0px 0px 300px)' ) // => 'rect'

Matrix : get positive value

You can use Math.abs:

var x = Math.abs(values[5]);

jQuery Drag/Resize with CSS Transform Scale

It's been a while since this question was asked. I have found (actually created) an answer. All it requires is setting callback handlers. No editing jquery-ui needed!

Note: zoomScale in this example is a global variable and the transform is set using animate (aided by jquery.transform.js) like so:

target.animate({
transform: 'scale(' + zoomScale + ')'
});

Take a look at this:

transform scale() fix for resizable:

$(this).resizable({
minWidth: -(contentElem.width()) * 10, // these need to be large and negative
minHeight: -(contentElem.height()) * 10, // so we can shrink our resizable while scaled
resize: function(event, ui) {

var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

ui.size.width = newWidth;
ui.size.height = newHeight;

}
});

transform scale() fix for draggable:

$(this).draggable({
handle: '.drag-handle',
start: function(event, ui) {
ui.position.left = 0;
ui.position.top = 0;
},
drag: function(event, ui) {

var changeLeft = ui.position.left - ui.originalPosition.left; // find change in left
var newLeft = ui.originalPosition.left + changeLeft / (( zoomScale)); // adjust new left by our zoomScale

var changeTop = ui.position.top - ui.originalPosition.top; // find change in top
var newTop = ui.originalPosition.top + changeTop / zoomScale; // adjust new top by our zoomScale

ui.position.left = newLeft;
ui.position.top = newTop;

}
});

Let me know if you find any problems or further improvements on this. :)

Reference: jQuery-UI resizable/draggable with transform: scale() set

Get element -moz-transform:rotate value in jQuery

Here's my solution using jQuery.

This returns a numerical value corresponding to the rotation applied to any HTML element.

function getRotationDegrees(obj) {
var matrix = obj.css("-webkit-transform") ||
obj.css("-moz-transform") ||
obj.css("-ms-transform") ||
obj.css("-o-transform") ||
obj.css("transform");
if(matrix !== 'none') {
var values = matrix.split('(')[1].split(')')[0].split(',');
var a = values[0];
var b = values[1];
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
} else { var angle = 0; }
return (angle < 0) ? angle + 360 : angle;
}

angle1 = getRotationDegrees($('#myDiv'));
angle2 = getRotationDegrees($('.mySpan a:last-child'));

etc...

Fetch the css value of transform directly using jquery

I've got good news and bad news.

I'll start with the bad news: After examining the object that jQuery returns, the matrix object is nothing but a string and there's absolutely no way you can get another object but a string. As much we would like to disagree that it shouldn't be a string: CSS values are strings, hence jQuery returns strings.

So, whether you like it or not, you really have to parse the string in order to get the value. The good news is: I've got two solutions.

Now, if you're VERY sure that the first couple of values are ALWAYS the same you could simply use substring. But, next problem: in Google Chrome, the value -283.589px is being changed to -283.5889892578125.

Honestly, you need a more advanced string parser to get the correct value. I welcome regular expression:

var matrix = $('.selector').css('-moz-transform');
var values = matrix.match(/-?[\d\.]+/g);

This gets all the values of your string.

By selecting the right index, you can get your value:

var x = values[5];

That's the best solution I can provide and I'm positive it's the only possible solution.

How to set a single value of transform while leaving the other values?

There is no way to directly modify a single component of the transform. Sadly, the various possible transforms were implemented as values on the transform attribute, rather than attributes themselves. There is no object model for CSS attribute values - attribute values are always just a string, as far as JavaScript is concerned. It would've been nice if transform was treated as a shorthand attribute for, eg, transform-rotate-y, transform-*, etc, the same way that background is a shorthand attribute for all the background-* attributes. This would've allowed us direct access to the values via JavaScript, but it was not implemented that way, so we are out of luck.

Edit: The simplest way to accomplish this (without studying the spec and doing a bunch of math) would be to nest your elements, applying different transformations to each. If you apply several transformations that won't change, go ahead and combine those on to one element. Any transformation that you do want to change, use a separate element:

Works here: jsfiddle.net/mkTKH/15


Edit: My original solution below won't work. In testing it out I discovered that getComputedStyle() converts the transform into a matrix(). An early draft of the spec says:

The transform property of the style object returned by getComputedStyle contains a single CSSTransformValue with a type of CSS_MATRIX. The 6 parameters represent the 3x2 matrix that is the result of applying the individual functions listed in the transform property.


So, you have to parse it. If you want to change just one portion of an attribute value, you can use a regular expression to parse the value:

var rotateY = "rotateY(" + deg + "deg)";
var transform = el.style.webkitTransform.replace(/\brotateY([^)]+)\b/, rotateY);
el.style.webkitTransform = transform;

I'd create a reusable function:

function setTransformValue(el, name, value) {
var currentValue = new RegExp(name + "([^)]+)");
var style = window.getComputedStyle ? getComputedStyle(el) : el.currentStyle;
var currentTransform = style.transform ||
style.webkitTransform ||
style.MozTransform ||
style.msTransform ||
style.OTransform;
var transform;
if (currentValue.test(currentTransform )) {
transform = currentTransform.replace(currentValue, name + "(" + value + ")");
}
else {
transform = currentTransform + " " + name + "(" + value + ")";
}
el.style.transform = transform;
}

Untested.

jQuery positioning with CSS3 transform: scale

I put my content into iframe, and I applied transformation on iframe - it works properly :)

EDIT: Previous version of my solution turn out to be buggy. But if someone would like to check it I save the snippet

/* * jQuery UI FIX * Take focus on window.transformScale */
/* * Offset fix */(function() {
function getWindow(elem) { return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView; }
jQuery.fn.offset = function( options ) {
// Preserve chaining for setter if ( arguments.length ) { return options === undefined ? this : this.each( function( i ) { jQuery.offset.setOffset( this, options, i ); } ); }
var docElem, win, rect, doc, elem = this[ 0 ];
if ( !elem ) { return; }
// Support: IE <=11 only // Running getBoundingClientRect on a // disconnected node in IE throws an error if ( !elem.getClientRects().length ) { return { top: 0, left: 0 }; }
var transform = $(document.body).css('transform'); $(document.body).css('transform', 'none');
rect = elem.getBoundingClientRect();
$(document.body).css('transform', transform);
// Make sure element is not hidden (display: none) if ( rect.width || rect.height ) { doc = elem.ownerDocument; win = getWindow( doc ); docElem = doc.documentElement;
return { top: rect.top + (win.pageYOffset - docElem.clientTop) / window.transformScale, left: rect.left + (win.pageXOffset - docElem.clientLeft) / window.transformScale, }; }
// Return zeros for disconnected and hidden elements (gh-2310) return rect;};
})();

/* * Position fix */(function() {
var cachedScrollbarWidth, max = Math.max, abs = Math.abs, rhorizontal = /left|center|right/, rvertical = /top|center|bottom/, roffset = /[\+\-]\d+(\.[\d]+)?%?/, rposition = /^\w+/, rpercent = /%$/, _position = $.fn.position;
function getOffsets( offsets, width, height ) { return [ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) ];}
function parseCss( element, property ) { return parseInt( $.css( element, property ), 10 ) || 0;}
function getDimensions( elem ) { var raw = elem[ 0 ]; if ( raw.nodeType === 9 ) { return { width: elem.width() / window.transformScale, height: elem.height() / window.transformScale, offset: { top: 0, left: 0 } }; } if ( $.isWindow( raw ) ) { return { width: elem.width() / window.transformScale, height: elem.height() / window.transformScale, offset: { top: elem.scrollTop(), left: elem.scrollLeft() } }; } if ( raw.preventDefault ) { return { width: 0, height: 0, offset: { top: raw.pageY, left: raw.pageX } }; } return { width: elem.outerWidth() / window.transformScale, height: elem.outerHeight() / window.transformScale, offset: elem.offset() };}
jQuery.fn.position = function( options ) { if ( !options || !options.of ) { return _position.apply( this, arguments ); }
// Make a copy, we don't want to modify arguments options = $.extend( {}, options );
var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, target = $( options.of ), within = $.position.getWithinInfo( options.within ), scrollInfo = $.position.getScrollInfo( within ), collision = ( options.collision || "flip" ).split( " " ), offsets = {};
dimensions = getDimensions( target ); if ( target[ 0 ].preventDefault ) {
// Force left top to allow flipping options.at = "left top"; } targetWidth = dimensions.width; targetHeight = dimensions.height; targetOffset = dimensions.offset;
// Clone to reuse original targetOffset later basePosition = $.extend( {}, targetOffset );
// Force my and at to have valid horizontal and vertical positions // if a value is missing or invalid, it will be converted to center $.each( [ "my", "at" ], function() { var pos = ( options[ this ] || "" ).split( " " ), horizontalOffset, verticalOffset;
if ( pos.length === 1 ) { pos = rhorizontal.test( pos[ 0 ] ) ? pos.concat( [ "center" ] ) : rvertical.test( pos[ 0 ] ) ? [ "center" ].concat( pos ) : [ "center", "center" ]; } pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
// Calculate offsets horizontalOffset = roffset.exec( pos[ 0 ] ); verticalOffset = roffset.exec( pos[ 1 ] ); offsets[ this ] = [ horizontalOffset ? horizontalOffset[ 0 ] : 0, verticalOffset ? verticalOffset[ 0 ] : 0 ];
// Reduce to just the positions without the offsets options[ this ] = [ rposition.exec( pos[ 0 ] )[ 0 ], rposition.exec( pos[ 1 ] )[ 0 ] ]; } );
// Normalize collision option if ( collision.length === 1 ) { collision[ 1 ] = collision[ 0 ]; }
if ( options.at[ 0 ] === "right" ) { basePosition.left += targetWidth; } else if ( options.at[ 0 ] === "center" ) { basePosition.left += targetWidth / 2; }
if ( options.at[ 1 ] === "bottom" ) { basePosition.top += targetHeight; } else if ( options.at[ 1 ] === "center" ) { basePosition.top += targetHeight / 2; }
atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); basePosition.left += atOffset[ 0 ]; basePosition.top += atOffset[ 1 ];
return this.each( function() { var collisionPosition, using, elem = $( this ), elemWidth = elem.outerWidth() / window.transformScale, elemHeight = elem.outerHeight() / window.transformScale, marginLeft = parseCss( this, "marginLeft" ), marginTop = parseCss( this, "marginTop" ), collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, position = $.extend( {}, basePosition ), myOffset = getOffsets( offsets.my, elem.outerWidth() / window.transformScale, elem.outerHeight() / window.transformScale );
if ( options.my[ 0 ] === "right" ) { position.left -= elemWidth; } else if ( options.my[ 0 ] === "center" ) { position.left -= elemWidth / 2; }
if ( options.my[ 1 ] === "bottom" ) { position.top -= elemHeight; } else if ( options.my[ 1 ] === "center" ) { position.top -= elemHeight / 2; }
position.left += myOffset[ 0 ]; position.top += myOffset[ 1 ];
collisionPosition = { marginLeft: marginLeft, marginTop: marginTop };
$.each( [ "left", "top" ], function( i, dir ) { if ( jQuery.ui.position[ collision[ i ] ] ) { jQuery.ui.position[ collision[ i ] ][ dir ]( position, { targetWidth: targetWidth, targetHeight: targetHeight, elemWidth: elemWidth, elemHeight: elemHeight, collisionPosition: collisionPosition, collisionWidth: collisionWidth, collisionHeight: collisionHeight, offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], my: options.my, at: options.at, within: within, elem: elem } ); } } );
if ( options.using ) {
// Adds feedback as second argument to using callback, if present using = function( props ) { var left = targetOffset.left - position.left, right = left + targetWidth - elemWidth, top = targetOffset.top - position.top, bottom = top + targetHeight - elemHeight, feedback = { target: { element: target, left: targetOffset.left, top: targetOffset.top, width: targetWidth, height: targetHeight }, element: { element: elem, left: position.left, top: position.top, width: elemWidth, height: elemHeight }, horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" }; if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { feedback.horizontal = "center"; } if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { feedback.vertical = "middle"; } if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { feedback.important = "horizontal"; } else { feedback.important = "vertical"; } options.using.call( this, props, feedback ); }; }
elem.offset( $.extend( position, { using: using } ) ); } );};
})();

/* * Draggable fix */(function() {
jQuery.ui.draggable.prototype._refreshOffsets = function( event ) { this.offset = { top: this.positionAbs.top - this.margins.top, left: this.positionAbs.left - this.margins.left, scroll: false, parent: this._getParentOffset(), relative: this._getRelativeOffset() };
this.offset.click = { left: event.pageX / window.transformScale - this.offset.left, top: event.pageY / window.transformScale - this.offset.top };};
jQuery.ui.draggable.prototype._generatePosition = function( event, constrainPosition ) {
var containment, co, top, left, o = this.options, scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), pageX = event.pageX / window.transformScale, pageY = event.pageY / window.transformScale;
// Cache the scroll if ( !scrollIsRootNode || !this.offset.scroll ) { this.offset.scroll = { top: this.scrollParent.scrollTop(), left: this.scrollParent.scrollLeft() }; }
/* * - Position constraining - * Constrain the position to a mix of grid, containment. */
// If we are not dragging yet, we won't check for options if ( constrainPosition ) { if ( this.containment ) { if ( this.relativeContainer ) { co = this.relativeContainer.offset(); containment = [ this.containment[ 0 ] + co.left, this.containment[ 1 ] + co.top, this.containment[ 2 ] + co.left, this.containment[ 3 ] + co.top ]; } else { containment = this.containment; }
var width = 0; var height = 0; if(window.transformScale != 1) { var width = this.helper.outerWidth(); var height = this.helper.outerHeight(); }
if ( pageX - this.offset.click.left < containment[ 0 ] ) { pageX = containment[ 0 ] + this.offset.click.left; } if ( pageY - this.offset.click.top < containment[ 1 ] ) { pageY = containment[ 1 ] + this.offset.click.top; } if ( pageX - this.offset.click.left + width > containment[ 2 ] ) { pageX = containment[ 2 ] + this.offset.click.left - width; } if ( pageY - this.offset.click.top + height > containment[ 3 ] ) { pageY = containment[ 3 ] + this.offset.click.top - height; } }
if ( o.grid ) {
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid // argument errors in IE (see ticket #6950) top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || top - this.offset.click.top > containment[ 3 ] ) ? top : ( ( top - this.offset.click.top >= containment[ 1 ] ) ? top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
left = o.grid[ 0 ] ? this.originalPageX + Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : this.originalPageX; pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || left - this.offset.click.left > containment[ 2 ] ) ? left : ( ( left - this.offset.click.left >= containment[ 0 ] ) ? left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; }
if ( o.axis === "y" ) { pageX = this.originalPageX; }
if ( o.axis === "x" ) { pageY = this.originalPageY; } }
return { top: (
// The absolute mouse position pageY -
// Click offset (relative to the element) this.offset.click.top -
// Only for relative positioned nodes: Relative offset from element to offset parent this.offset.relative.top -
// The offsetParent's offset without borders (offset + border) this.offset.parent.top + ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) ), left: (
// The absolute mouse position pageX -
// Click offset (relative to the element) this.offset.click.left -
// Only for relative positioned nodes: Relative offset from element to offset parent this.offset.relative.left -
// The offsetParent's offset without borders (offset + border) this.offset.parent.left + ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) ) };
};
jQuery.ui.draggable.prototype._mouseStart = function( event ) {
var o = this.options;
//Create and append the visible helper this.helper = this._createHelper( event );
this._addClass( this.helper, "ui-draggable-dragging" );
//Cache the helper size this._cacheHelperProportions();
//If ddmanager is used for droppables, set the global draggable if ( jQuery.ui.ddmanager ) { jQuery.ui.ddmanager.current = this; }
/* * - Position generation - * This block generates everything position related - it's the core of draggables. */
//Cache the margins of the original element this._cacheMargins();
//Store the helper's css position this.cssPosition = this.helper.css( "position" ); this.scrollParent = this.helper.scrollParent( true ); this.offsetParent = this.helper.offsetParent(); this.hasFixedAncestor = this.helper.parents().filter( function() { return $( this ).css( "position" ) === "fixed"; } ).length > 0;
//The element's absolute position on the page minus margins this.positionAbs = this.element.offset(); this._refreshOffsets( event );
//Generate the original position this.originalPosition = this.position = this._generatePosition( event, false ); this.originalPageX = event.pageX / window.transformScale; this.originalPageY = event.pageY / window.transformScale;
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
//Set a containment if given in the options this._setContainment();
//Trigger event + callbacks if ( this._trigger( "start", event ) === false ) { this._clear(); return false; }
//Recache the helper size this._cacheHelperProportions();
//Prepare the droppable offsets if ( jQuery.ui.ddmanager && !o.dropBehaviour ) { jQuery.ui.ddmanager.prepareOffsets( this, event ); }
// Execute the drag once - this causes the helper not to be visible before getting its // correct position this._mouseDrag( event, true );
// If the ddmanager is used for droppables, inform the manager that dragging has started // (see #5003) if ( jQuery.ui.ddmanager ) { jQuery.ui.ddmanager.dragStart( this, event ); }
return true;
};
jQuery.ui.draggable.prototype._mouseDrag = function( event, noPropagation ) {
// reset any necessary cached properties (see #5009) if ( this.hasFixedAncestor ) { this.offset.parent = this._getParentOffset(); }
//Compute the helpers position this.position = this._generatePosition( event, true ); this.positionAbs = this._convertPositionTo( "absolute" );
//Call plugins and callbacks and use the resulting position if something is returned if ( !noPropagation ) { var ui = this._uiHash(); if ( this._trigger( "drag", event, ui ) === false ) { this._mouseUp( new $.Event( "mouseup", event ) ); return false; } this.position = ui.position; }
this.helper[ 0 ].style.left = this.position.left + "px"; this.helper[ 0 ].style.top = this.position.top + "px";
if ( jQuery.ui.ddmanager ) { jQuery.ui.ddmanager.drag( this, event ); }
return false;};
})();
body { position: relative; margin:  0; transform-origin: 0 0 0;}
#root { position: fixed; top: 20px; left: 20px;
width: 500px; height: 500px;
border: solid 2px green;
}
#box { position: absolute; top: 100px; left: 50px;
display: inline-block; width: 50px; height: 50px;
background: yellow; border: solid 2px black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script><script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script><script>/* * EXAMPLE CODE */// this variable is required to make extension workwindow.transformScale = 0.5;
$(document).ready(function() { $(document.body).attr('style', 'transform: scale('+ window.transformScale +')');
$('#root').dblclick(function() { $('#box').position({ my: 'right bottom', at: 'right bottom', of: $('#root') }); })
$('#box').draggable({ containment: $('#root'), });
});</script>
<div id="root"> <div id="box"></div></div>


Related Topics



Leave a reply



Submit