如何实现canvas画布任意宽高时,所绘制的文字都一样清晰。
我在canvas画布上填充了文本,但是文字看起来有点模糊,
然后获取了当前设备的dpr
,来计算设置了画布宽高如下:
canvas.width = (clientWidth + 2 * margin) * dpr;
canvas.height = (clientHeight + 2 * margin) * dpr;
canvas.style.width = clientWidth + 2 * margin + "px";
canvas.style.height = clientHeight + 2 * margin + "px";
在container
容器的宽高为width: 300px;height: 100px;
时,文字内容看起来清晰正常,
但是当container
容器宽高为为其他任意大小时,文字就会变得不清晰。
我想知道的是这是为什么,我需要怎么解决这个异常。
完整的代码如下,可直接复制代码查看效果,调整15、16行代码的数值,复现我所描述的问题
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>比邻商店-bilinStore</title>
<style>
html, body{
height: 100%;
width: 100%;
}
.container{
width: 300px;
height: 100px;
position: relative;
}
</style>
</head>
<body>
<div class="container">
</div>
</body>
<script>
function drawCardBg({
container,
fillStyle = '#003477',
titleWidth = 0.4,
margin = 10,
radiu = 10,
title = 'card',
showborder = false
}) {
const containerNode = document.querySelector(container);
const { clientWidth, clientHeight } = containerNode;
// 获取设备dpi
const dpr = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1;
// 创建高分辨率画布
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// 设置canvas样式属性
canvas.width = (clientWidth + 2 * margin) * dpr;
canvas.height = (clientHeight + 2 * margin) * dpr;
canvas.style.width = clientWidth + 2 * margin + "px";
canvas.style.height = clientHeight + 2 * margin + "px";
canvas.style.position = 'absolute';
canvas.style.top = '50%';
canvas.style.left = '50%';
canvas.style.transform = 'translate(-50%, -50%)';
canvas.style.zIndex = -1;
ctx.scale(dpr, dpr);
// 插入到指定位置
document.querySelector(container).appendChild(canvas);
const [width, height] = [clientWidth + margin, clientHeight + margin];
/**
* 计算标题的宽度
* 这里标题的宽度有两种状态,一种直接指定确定的宽度,另一种指定宽度百分比,
* 在这里计算百分比所占大小
* canvas中只能使用int类型的宽度,最终以px为单位显示
*/
if (titleWidth < 1) titleWidth = width * titleWidth;
const sideWidth = (width - titleWidth) / 2 - 15;
/**
* 绘制整体的背景
*/
ctx.beginPath();
ctx.moveTo(margin + radiu, margin);
// 绘制顶部线条
ctx.lineTo(width - radiu, margin);
// 绘制右上角的圆角
ctx.arc(
width - radiu,
margin + radiu,
radiu,
(Math.PI / 180) * 270,
0,
false,
);
// 绘制右边线条
ctx.lineTo(width, height - 2 * radiu);
// 绘制右下角的圆角
ctx.arc(
width - radiu,
height - radiu,
radiu,
0,
(Math.PI / 180) * 90,
0,
false,
);
/**绘制标题的不规则凹陷区域和下边线条 */
ctx.lineTo(width - sideWidth, height);
ctx.lineTo(width - sideWidth - 15, height - 17);
ctx.lineTo(width - sideWidth - 15 - titleWidth, height - 17);
ctx.lineTo(width - sideWidth - 30 - titleWidth, height);
// 绘制左下角的圆角
ctx.arc(
margin + radiu,
height - radiu,
radiu,
(Math.PI / 180) * 90,
(Math.PI / 180) * 180,
false,
);
// 绘制左边线条
ctx.lineTo(margin, height - radiu);
// 绘制左上角的圆角
ctx.arc(
margin + radiu,
margin + radiu,
radiu,
(Math.PI / 180) * 180,
(Math.PI / 180) * 270,
false,
);
// 设置边框颜色和宽度
if (showborder) {
ctx.strokeStyle = '#00B4CB';
ctx.lineWidth = 2;
ctx.stroke();
}
// 给闭合区域设置边框阴影颜色
ctx.shadowColor = 'rgba(0,255,255,0.8)';
// 阴影的模糊半径
ctx.shadowBlur = margin;
// 闭合路径(以上所绘制的闭合区域)
ctx.closePath();
// 设置闭合区域的填充色,并填充
ctx.fillStyle = fillStyle;
ctx.fill();
ctx.shadowBlur = 0;
const titleIconLOrigin = sideWidth + 20;
/**
* 绘制标题部分左边ICON
*/
ctx.beginPath();
ctx.moveTo(sideWidth + 20, height - 13);
ctx.lineTo(titleIconLOrigin + 20, height - 13);
ctx.lineTo(titleIconLOrigin + 15, height - 6);
ctx.lineTo(titleIconLOrigin + -5, height - 6);
ctx.closePath();
ctx.fillStyle = '#2E90FF';
ctx.fill();
/**
* 绘制标题部分右边ICON
*/
ctx.beginPath();
ctx.moveTo(-30 + titleWidth + titleIconLOrigin, height - 13);
ctx.lineTo(-10 + titleWidth + titleIconLOrigin, height - 13);
ctx.lineTo(-5 + titleWidth + titleIconLOrigin, height - 6);
ctx.lineTo(-25 + titleWidth + titleIconLOrigin, height - 6);
ctx.closePath();
ctx.fillStyle = '#2E90FF';
ctx.fill();
/**
* 绘制标题背景
*/
ctx.beginPath();
ctx.moveTo(titleIconLOrigin + 25, height - 13);
ctx.lineTo(titleWidth + titleIconLOrigin - 35, height - 13);
ctx.lineTo(titleWidth + titleIconLOrigin - 30, height - 6);
ctx.lineTo(titleWidth + titleIconLOrigin - 30, height + 2);
ctx.lineTo(titleIconLOrigin + 20, height + 2);
ctx.lineTo(titleIconLOrigin + 20, height - 6);
ctx.closePath();
ctx.fillStyle = '#2E90FF';
ctx.fill();
ctx.fillStyle = '#fff';
ctx.font = '10px Calibri';
const textWidth = ctx.measureText(title);
ctx.fillText(title, width / 2 - textWidth.width / 2, height - 1);
};
drawCardBg({container: '.container', title: '设备工况'})
</script>
</html>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
整个书写过程是对的,原因在于我再定位这个canvas时使用了transform
使用transform来做居中时,gpu渲染点阵对不上就会模糊
在我这里chrome浏览器效果来看,宽高变化时,字体是没有变化,且没有出现不清晰的情况;
按照你说的,目前只能理解为你自身的显示器问题,跟这个程序无关;
如果你需要字体跟随容器大小而改变,就需要动态改变字体大小