我有一些画布,我想在每个(现代)浏览器中显示像素完美。默认情况下,具有高DPI屏幕的设备正在缩放我的页面,以便所有内容看起来都合适,但它会破坏我的画布外观。
如何确保画布中的一个像素=屏幕上的一个像素?优选地,这不会影响页面上的其他元素,因为我仍然希望例如要为设备适当缩放的文本。
我已尝试根据window.devicePixelRatio
设置画布尺寸样式。这使画布尺寸合适,但内容看起来更糟。我猜测只是在他们已经错误地放大后才缩小它们。
*如果你关心,因为画布使用抖动而浏览器正在做某种lerp而不是最近邻居
答案 0 :(得分:3)
很简单:
canvas {
image-rendering: pixelated;
}
浏览器支持不是great,但到目前为止,它已经在我测试的所有现代浏览器上运行,所以我很高兴。
只要您的画布以正常尺寸显示,这对普通DPI设备没有影响。此外,根据屏幕的不同,您可以在高DPI设备上获得有趣的工件,但我认为由于这些显示器的工作方式,这是不可避免的。它们仍然比你没有风格的文物更好。
我还尝试使用javascript中的最近邻居将我的所有画布200%放大,然后将它们设置为正常大小的div的背景图像。这就是Apple建议为视网膜设备显示图像的方式,所以我认为它会产生很好的效果。但你仍然最终得到了文物并且它们没有通过放大页面来修复,所以它实际上比上面那个更简单。
答案 1 :(得分:0)
对我来说,只有不同的“像素完美”技术的组合才能帮助存档结果:
以像素比例获取和缩放画布:
pixelRatio = window.devicePixelRatio / ctx.backingStorePixelRatio
在调整大小时缩放画布(避免画布默认拉伸缩放)。
将lineWidth与pixelRatio乘以找到合适的“真实”像素线粗度:
context.lineWidth =厚度* pixelRatio;
检查线条的粗细是否为奇数或偶数。将奇数厚度值的一半pixelRatio添加到行位置。
x = x + pixelRatio / 2;
奇数行将放置在像素的中间。上面的线用于将其移动一点。
function getPixelRatio(context) {
dpr = window.devicePixelRatio || 1,
bsr = context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return dpr / bsr;
}
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
var pixelRatio = getPixelRatio(context);
var initialWidth = canvas.clientWidth * pixelRatio;
var initialHeight = canvas.clientHeight * pixelRatio;
window.addEventListener('resize', function(args) {
rescale();
redraw();
}, false);
function rescale() {
var width = initialWidth * pixelRatio;
var height = initialHeight * pixelRatio;
if (width != context.canvas.width)
context.canvas.width = width;
if (height != context.canvas.height)
context.canvas.height = height;
context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
}
function pixelPerfectLine(x1, y1, x2, y2) {
context.save();
context.beginPath();
thickness = 1;
// Multiple your stroke thickness by a pixel ratio!
context.lineWidth = thickness * pixelRatio;
context.strokeStyle = "Black";
context.moveTo(getSharpPixel(thickness, x1), getSharpPixel(thickness, y1));
context.lineTo(getSharpPixel(thickness, x2), getSharpPixel(thickness, y2));
context.stroke();
context.restore();
}
function pixelPerfectRectangle(x, y, w, h, thickness, useDash) {
context.save();
// Pixel perfect rectange:
context.beginPath();
// Multiple your stroke thickness by a pixel ratio!
context.lineWidth = thickness * pixelRatio;
context.strokeStyle = "Red";
if (useDash) {
context.setLineDash([4]);
}
// use sharp x,y and integer w,h!
context.strokeRect(
getSharpPixel(thickness, x),
getSharpPixel(thickness, y),
Math.floor(w),
Math.floor(h));
context.restore();
}
function redraw() {
context.clearRect(0, 0, canvas.width, canvas.height);
pixelPerfectLine(50,50,250,250);
pixelPerfectLine(120,0,120,250);
pixelPerfectLine(122,0,122,250);
pixelPerfectRectangle(10, 11, 200.3, 43.2, 1, false);
pixelPerfectRectangle(41, 42, 150.3, 43.2, 1, true);
pixelPerfectRectangle(102, 100, 150.3, 243.2, 2, true);
}
function getSharpPixel(thickness, pos) {
if (thickness % 2 == 0) {
return pos;
}
return pos + pixelRatio / 2;
}
rescale();
redraw();
canvas {
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
width: 100vh;
height: 100vh;
}
<canvas id="canvas"></canvas>
未在摘要中触发调整大小事件,因此您可以尝试在github上尝试文件