2D 画布 :指定"arc()"半径单位



我一直在尝试制作一个包含画布的响应式网站。

在绘制圆形进度条时,正在调用arc()函数,但它radius参数看起来需要以像素为单位,但我需要它作为百分比、vw、vh、em 或任何其他单位 css 建议。

当然,我可以以像素为单位渲染它并使用CSS拉伸它,但它要么被放大和像素化,要么被缩小并浪费资源,要么被扭曲。

我应该怎么做?

经过一番搜索,我偶然发现了这个问题,它帮助我解决了这个问题。

这是我是如何做到的:

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
var vw = w/100;
var vh = h/100;
var pxradius = 50;
var vwradius = pxradius*vw;

不幸的是,我仍然没有百分比和 ems 的解决方案

我现在正在做一些事情,我必须解决完全相同的问题(即以百分比或 ems 为单位设置CanvasRenderingContext2D.arc()半径值)。


这是我的解决方案的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上有演示。


现在,一些解释/评论:emToPixelElementRelativepercentToPixelElementRelative分别转换作为第一个参数传递给它的值em=>px%=>px。两个函数(element)的第二个参数是一个元素,基于该元素将计算尺寸,px中的值(注意:请记住,您将半径而不是直径传递给arc(),对于百分比意味着如果您传递50(%)并将基于canvas元素进行计算 - 圆的直径将是100%,并将填充整个canvas(在方形画布的情况下)),如果未传递参数 — 根据视口的尺寸计算值。第三个参数(width_based)反映计算的值是相对于宽度(如果设置为默认值设置为true)还是相对于高度(如果设置为false)。

percentToPixelParentBasedemToPixelParentBased只是percentToPixelElementRelativeemToPixelElementRelative的包装器,它们基于传递element的父级进行转换。

getFontSize返回传递element的字体大小,或者<body>元素(如果不带参数调用)的字体大小。

getPPI通过本答案中提到的黑客获得当前的 PPI,它接受单个参数 (width_based) 指示是否将其计算基于宽度(如果true- 默认值)或高度(如果false)。

另请注意,我基于以下假设进行em=>px计算:

  • 字体大小以pt为单位(基于本文)
  • 1em等于pt当前字体的大小(基于 pxtoem.com 和这个答案)
  • 转换pt=>px的公式1pt = 72 / ppi(基于此答案)

问题(当然还有答案)/资源,帮助我将这个解决方案放在一起:

  1. 获取当前 PPI:
    • 如何按 id 删除 HTML 元素
    • 如何将元素插入到 HTML 中
    • 如何获得当前 PPI 的一般配方
  2. 获取当前字体大小:
    • 如何获取当前字体大小
    • 获取 HTML 元素(MDN 星期三文档)
  3. 像素转换百分比:
    • 当然,基于Magix上面的回答
  4. 电磁到像素的转换:
    • 什么是电磁 (PXtoEM.com)
    • 如何计算 EM
    • 如何将 pt 转换为 px
  5. 杂项:
    • 使用 PXtoEM.com 链接回答
    • 偏移宽度、
    • 客户端宽度、滚动宽度和高度之间的差异
    • 如何在堆栈溢出标记中制作嵌套列表 =)

最新更新