Skip to content

Instantly share code, notes, and snippets.

@pedrosancao
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pedrosancao/cd9aaf46b7657f18010e to your computer and use it in GitHub Desktop.
Save pedrosancao/cd9aaf46b7657f18010e to your computer and use it in GitHub Desktop.
convert pixels to other units of measurement back and forth, according to device DPI
/**
* Convert pixels to other units of measurement, according to device DPI
*
* @author Pedro Sanção <dev at sancao dot co>
* @license MIT
*/
var unitConvert = (function(){
var precision = 0
, _setPrecision = function(p) {
precision = p;
}
, _getElement = function() {
var el = document.createElement('div');
el.style.width = 0;
el.style.visibility = 'hidden';
document.body.appendChild(el);
return el;
}
, _fixFloat = function(n) {
return Number((n).toFixed(precision));
}
;
return {
/**
* approach 1 - increment until find the size
* more precision require a lot of iterations
* is faster with few pixels and low precision (0 or 1)
*/
px2unit_incremental: function(unit, px, precision) {
var el = _getElement()
, pow = Math.pow(10, precision)
, increment = 1 / pow
, width = 0, lastWidth
, iterations = 0
;
_setPrecision(precision);
do {
iterations++;
width = _fixFloat(width + increment);
el.style.width = width + unit;
} while (el.offsetWidth === 0);
width = Math.floor(width * pow * px / el.offsetWidth) / pow;
while (true) {
iterations++;
lastWidth = el.style.width;
el.style.width = width + unit;
if (el.offsetWidth > px) {
el.style.width = lastWidth;
break;
}
width = _fixFloat(width + increment);
}
width = el.style.width;
document.body.removeChild(el);
console.log(iterations + ' iterations');
return width;
},
/**
* approach 2 - use binary search
* faster when higher precisions are required
*/
px2unit: function(unit, px, precision) {
var el = _getElement()
, pow = Math.pow(10, precision)
, increment = 1 / pow
, width = 0, lastWidth, min, max, avg
, iterations = 0
;
_setPrecision(precision);
while (el.offsetWidth <= px) {
iterations++;
lastWidth = width;
width = width ? width * 2 : increment;
el.style.width = width + unit;
}
min = lastWidth;
max = width;
while (_fixFloat(max - min) !== increment) {
iterations++;
avg = Math.round((max + min) / 2 * pow * 10) / pow / 10;
width = _fixFloat(Math.floor(avg * pow) / pow);
el.style.width = width + unit;
if (el.offsetWidth > px) {
max = width;
} else {
min = width;
}
};
document.body.removeChild(el);
console.log(iterations + ' iterations');
return min + unit;
},
unit2px: function(unit) {
var el = _getElement(), width;
el.style.width = unit;
width = el.offsetWidth;
document.body.removeChild(el);
return width;
}
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment