Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Slightly modified compiled coffeescript from this codepen: http://codepen.io/fta/pen/ifnqH. Paste into console on a page that has jQuery to load the two dependent libraries (jquery-ui and numericjs). Then call makeTransformable('#selector-name') to make that element WYSIWYG editable. Use inspector to get the CSS for the transforms.
var selector = 'img' // Replace this with the selector for the element you want to make transformable
jQuery.getScript('//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js', function() {
jQuery.getScript('//cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js', function() {
(function() {
var $, applyTransform, getTransform, makeTransformable;
$ = jQuery;
getTransform = function(from, to) {
var A, H, b, h, i, k_i, lhs, rhs, _i, _j, _k, _ref;
console.assert((from.length === (_ref = to.length) && _ref === 4));
A = [];
for (i = _i = 0; _i < 4; i = ++_i) {
A.push([from[i].x, from[i].y, 1, 0, 0, 0, -from[i].x * to[i].x, -from[i].y * to[i].x]);
A.push([0, 0, 0, from[i].x, from[i].y, 1, -from[i].x * to[i].y, -from[i].y * to[i].y]);
}
b = [];
for (i = _j = 0; _j < 4; i = ++_j) {
b.push(to[i].x);
b.push(to[i].y);
}
h = numeric.solve(A, b);
H = [[h[0], h[1], 0, h[2]], [h[3], h[4], 0, h[5]], [0, 0, 1, 0], [h[6], h[7], 0, 1]];
for (i = _k = 0; _k < 4; i = ++_k) {
lhs = numeric.dot(H, [from[i].x, from[i].y, 0, 1]);
k_i = lhs[3];
rhs = numeric.dot(k_i, [to[i].x, to[i].y, 0, 1]);
console.assert(numeric.norm2(numeric.sub(lhs, rhs)) < 1e-9, "Not equal:", lhs, rhs);
}
return H;
};
applyTransform = function(element, originalPos, targetPos, callback) {
var H, from, i, j, p, to;
from = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = originalPos.length; _i < _len; _i++) {
p = originalPos[_i];
_results.push({
x: p[0] - originalPos[0][0],
y: p[1] - originalPos[0][1]
});
}
return _results;
})();
to = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = targetPos.length; _i < _len; _i++) {
p = targetPos[_i];
_results.push({
x: p[0] - originalPos[0][0],
y: p[1] - originalPos[0][1]
});
}
return _results;
})();
H = getTransform(from, to);
$(element).css({
'transform': "matrix3d(" + (((function() {
var _i, _results;
_results = [];
for (i = _i = 0; _i < 4; i = ++_i) {
_results.push((function() {
var _j, _results1;
_results1 = [];
for (j = _j = 0; _j < 4; j = ++_j) {
_results1.push(H[j][i].toFixed(20));
}
return _results1;
})());
}
return _results;
})()).join(',')) + ")",
'transform-origin': '0 0'
});
return typeof callback === "function" ? callback(element, H) : void 0;
};
makeTransformable = function(selector, callback) {
return $(selector).each(function(i, element) {
var controlPoints, originalPos, p, position;
$(element).css('transform', '');
controlPoints = (function() {
var _i, _len, _ref, _results;
_ref = ['left top', 'left bottom', 'right top', 'right bottom'];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
position = _ref[_i];
_results.push($('<div>').css({
border: '3px solid black',
borderRadius: '3px',
cursor: 'move',
position: 'absolute',
zIndex: 100000
}).appendTo('body').position({
at: position,
of: element,
collision: 'none'
}));
}
return _results;
})();
originalPos = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = controlPoints.length; _i < _len; _i++) {
p = controlPoints[_i];
_results.push([p.offset().left, p.offset().top]);
}
return _results;
})();
$(controlPoints).draggable({
start: (function(_this) {
return function() {
return $(element).css('pointer-events', 'none');
};
})(this),
drag: (function(_this) {
return function() {
return applyTransform(element, originalPos, (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = controlPoints.length; _i < _len; _i++) {
p = controlPoints[_i];
_results.push([p.offset().left, p.offset().top]);
}
return _results;
})(), callback);
};
})(this),
stop: (function(_this) {
return function() {
applyTransform(element, originalPos, (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = controlPoints.length; _i < _len; _i++) {
p = controlPoints[_i];
_results.push([p.offset().left, p.offset().top]);
}
return _results;
})(), callback);
return $(element).css('pointer-events', 'auto');
};
})(this)
});
return element;
});
};
window.makeTransformable = makeTransformable
}).call(this);
makeTransformable(selector);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment