我是一个使用HTML5
的n00b,正在使用canvas
渲染形状、颜色和文本。在我的应用程序中,我有一个视图适配器,它动态创建一个画布,并用内容填充它。这真的很好用,除了我的文本呈现得非常模糊/模糊/拉伸。我已经看过很多其他的关于为什么用CSS
定义宽度和高度会导致这个问题的帖子,但我用javascript
来定义它。
相关代码(查看Fiddle):
var width = 500;//FIXME:size.w;
var height = 500;//FIXME:size.h;
var canvas = document.createElement("canvas");
//canvas.className="singleUserCanvas";
canvas.width=width;
canvas.height=height;
canvas.border = "3px solid #999999";
canvas.bgcolor = "#999999";
canvas.margin = "(0, 2%, 0, 2%)";
var context = canvas.getContext("2d");
//////////////////
//// SHAPES ////
//////////////////
var left = 0;
//draw zone 1 rect
context.fillStyle = "#8bacbe";
context.fillRect(0, (canvas.height*5/6)+1, canvas.width*1.5/8.5, canvas.height*1/6);
left = left + canvas.width*1.5/8.5;
//draw zone 2 rect
context.fillStyle = "#ffe381";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*2.75/8.5, canvas.height*1/6);
left = left + canvas.width*2.75/8.5 + 1;
//draw zone 3 rect
context.fillStyle = "#fbbd36";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5;
//draw target zone rect
context.fillStyle = "#004880";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*0.25/8.5, canvas.height*1/6);
left = left + canvas.width*0.25/8.5;
//draw zone 4 rect
context.fillStyle = "#f8961d";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5 + 1;
//draw zone 5 rect
context.fillStyle = "#8a1002";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width-left, canvas.height*1/6);
////////////////
//// TEXT ////
////////////////
//user name
context.fillStyle = "black";
context.font = "bold 18px sans-serif";
context.textAlign = 'right';
context.fillText("User Name", canvas.width, canvas.height*.05);
//AT:
context.font = "bold 12px sans-serif";
context.fillText("AT: 140", canvas.width, canvas.height*.1);
//AB:
context.fillText("AB: 94", canvas.width, canvas.height*.15);
//this part is done after the callback from the view adapter, but is relevant here to add the view back into the layout.
var parent = document.getElementById("layout-content");
parent.appendChild(canvas);
<div id="layout-content"></div>
我看到的结果(在Safari中)比在Fiddle中显示的要扭曲得多:
矿山
小提琴
我做错了什么?每个文本元素都需要单独的画布吗?是字体的问题吗?是否需要首先在HTML5布局中定义画布?有打字错误吗?我迷路了。
发布于 2013-03-28 02:03:37
画布元素独立于设备或监视器的像素比率运行。
在iPad 3+上,这个比率是2。这实际上意味着你的1000px宽度画布现在需要填充2000px才能与iPad显示屏上声明的宽度匹配。对我们来说幸运的是,这是由浏览器自动完成的。另一方面,这也是为什么您在图像和画布元素上看到的清晰度较少的原因,这些图像和画布元素是直接适合其可见区域的。因为您的画布只知道如何填充1000px,但被要求绘制到2000px,所以浏览器现在必须智能地填充像素之间的空白,以便以适当的大小显示元素。
我强烈建议你阅读来自HTML5Rocks的this article,它更详细地解释了如何创建高清元素。
tl;dr?下面是一个示例(基于上面的tut),我在自己的项目中使用它来生成一个具有适当分辨率的画布:
var PIXEL_RATIO = (function () {
var ctx = document.createElement("canvas").getContext("2d"),
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
})();
createHiDPICanvas = function(w, h, ratio) {
if (!ratio) { ratio = PIXEL_RATIO; }
var can = document.createElement("canvas");
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
return can;
}
//Create canvas with the device resolution.
var myCanvas = createHiDPICanvas(500, 250);
//Create canvas with a custom resolution.
var myCustomCanvas = createHiDPICanvas(500, 200, 4);
希望这能有所帮助!
发布于 2013-03-27 22:44:50
已解决!
我决定看看是什么改变了我在javascript
中设置的宽度和高度属性,以了解这对画布大小有何影响--但它没有。它改变了分辨率。
为了获得我想要的结果,我还必须设置canvas.style.width
属性,该属性更改canvas
的物理大小
canvas.width=1000;//horizontal resolution (?) - increase for better looking text
canvas.height=500;//vertical resolution (?) - increase for better looking text
canvas.style.width=width;//actual width of canvas
canvas.style.height=height;//actual height of canvas
发布于 2020-12-03 19:16:39
虽然@MyNameIsKo的答案仍然有效,但它在2020年已经有点过时了,可以改进:
function createHiPPICanvas(w, h) {
let ratio = window.devicePixelRatio;
let cv = document.createElement("canvas");
cv.width = w * ratio;
cv.height = h * ratio;
cv.style.width = w + "px";
cv.style.height = h + "px";
cv.getContext("2d").scale(ratio, ratio);
return cv;
}
总的来说,我们做了以下改进:
backingStorePixelRatio
引用,因为这些引用并没有以任何重要的方式在任何浏览器中实现(事实上,只有Safari返回undefined
以外的其他东西,这个版本在Safari中仍然可以完美地工作);window.devicePixelRatio
替换了所有的比例代码,window.devicePixelRatio
还意味着我们少声明了一个全局属性-万岁!!window.devicePixelRatio
上的|| 1
回退,因为它是没有意义的:所有不支持该属性的浏览器也不支持.setTransform
或.scale
,所以这个函数对它们不起作用,不管回退与否;.scale
代替.setTransform
,因为传入一个宽度和高度比传入一个转换矩阵更直观一些。createHiDPICanvas
重命名为createHiPPICanvas
。正如@MyNameIsKo自己在他们的答案中提到的那样,DPI (每英寸点数)是打印术语(因为打印机由彩色墨水的小点组成图像)。类似地,显示器使用像素来显示图像,因此对于我们的用例来说,PPI (每英寸像素)是一个更好的缩写。这些简化的一个很大的好处是,这个答案现在可以在没有// @ts-ignore
的TypeScript中使用(因为TS没有backingStorePixelRatio
的类型)。
https://stackoverflow.com/questions/15661339
复制相似问题