Я сейчас над чем-то работаю, где мне пришлось решить ту же проблему (т.е. установить значения радиуса для _ 1_ в процентах или ems).
Вот код JavaScript моего решения:
function percentToPixelParentBased(percent, element, width_based=true) {
return percentToPixelElementRelative(percent, element.parentElement, width_based);
}
function emToPixelParentBased(em_value, element) {
return emToPixelElementRelative(em_value, element.parentElement);
}
function percentToPixelElementRelative(percent, element=false, width_based=true) {
if (element) {
if (width_based) {
var dimension = element.style.width || element.offsetWidth;
} else {
var dimension = element.style.height || element.offsetHeight;
}
} else {
if (width_based) {
var dimension = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
} else {
var dimension = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
}
}
var pixels_in_percent = dimension / 100;
return pixels_in_percent * percent;
}
function emToPixelElementRelative(em_value, element=false) {
var font_size = getFontSize(element);
var ppi = getPPI();
var px_in_pt = 72 / ppi; /* 1pt is 1/72 of an inch */
var value_in_pt = em_value * font_size;
return value_in_pt * px_in_pt;
}
function getFontSize(element=false) {
if (element) {
return parseFloat(getComputedStyle(element).fontSize);
} else {
/* getting font size from body */
return parseFloat(getComputedStyle(document.body).fontSize);
}
}
function getPPI() {
var inch_div_html = "<div id='inch-div' style='height: 1in; left: -100%; position: absolute; top: -100%; width: 1in;'></div>";
document.body.insertAdjacentHTML( 'afterbegin', inch_div_html);
var device_pixel_ratio = window.devicePixelRatio || 1;
var ppi_test_div = document.getElementById('inch-div');
var ppi = ppi_test_div.offsetWidth * devicePixelRatio;
document.body.removeChild(ppi_test_div);
return ppi;
}
Чтобы немного потрудиться, есть демонстрация на JSFiddle.
Теперь немного пояснений / замечаний: каждый из emToPixelElementRelative
и percentToPixelElementRelative
преобразует значение, переданное ему в качестве первого аргумента em=>px
и %=>px
соответственно. Второй аргумент обеих функций (element
) - это элемент, на основе которого будут вычисляться значения в px
(NB: имейте в виду, что вы передаете радиус, а не диаметр в arc()
, что для процентов означает, что если вы передадим 50 (%) и будем основывать вычисления на элементе canvas
- диаметр круга будет 100% и заполнит весь canvas
(в случае квадратного холста)), если аргумент не передан - значения рассчитываются на основе размеров области просмотра. Третий аргумент (width_based
) отражает, должны ли вычисляться значения относиться к ширине (если установлено true
, что по умолчанию) или высоте (если установлено false
).
percentToPixelParentBased
и emToPixelParentBased
- это просто оболочки для percentToPixelElementRelative
и emToPixelElementRelative
, которые основывают преобразование на родительском элементе переданного element
.
getFontSize
возвращает размер шрифта для переданного element
или для элемента <body>
, если вызывается без аргументов.
getPPI
получает текущий PPI через своего рода упомянутый хак в этом ответе он принимает единственный аргумент (width_based
), указывающий, следует ли основывать его вычисления на ширине (если true
- по умолчанию) или высоте (если false
).
Также обратите внимание, что я основывал em=>px
расчеты на следующих предположениях:
Вопросы (и ответы на них, конечно) / ресурсы, которые помогли мне собрать это решение:
- Getting current PPI:
- Getting current font size:
- Percent to pixel conversion:
- Em to pixel conversion:
- Misc:
person
Community
schedule
18.11.2017