在HTML5画布上绘制1条像素线总是有问题的。(请参阅http://jsbin.com/voqubexu/1/edit?js,output)
绘制垂直/水平线的方法是x + 0.5,y + 0.5(参考Canvas line behaviour when 0 < lineWidth < 1)。
要在全球范围内执行此操作,ctx.translate(0.5, 0.5);
将是一个好主意。
但是,对于对角线,此方法不起作用。它总是给出2像素线。有没有办法阻止这种浏览器行为?如果没有,是否有可以解决此问题的软件包?
答案 0 :(得分:5)
您所指的“更宽”行来自浏览器自动完成的抗锯齿。
消除锯齿用于显示视觉上较少锯齿的线条。
如果没有逐像素绘制,目前无法禁用浏览器绘制的消除锯齿功能。
您可以使用 Bresenham的线算法通过设置单个像素来绘制线条。当然,设置单个像素会导致性能降低。
以下是示例代码和演示:http://jsfiddle.net/m1erickson/3j7hpng0/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=imgData.data;
bline(50,50,250,250);
ctx.putImageData(imgData,0,0);
function setPixel(x,y){
var n=(y*canvas.width+x)*4;
data[n]=255;
data[n+1]=0;
data[n+2]=0;
data[n+3]=255;
}
// Refer to: http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
function bline(x0, y0, x1, y1) {
var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
var dy = Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
var err = (dx>dy ? dx : -dy)/2;
while (true) {
setPixel(x0,y0);
if (x0 === x1 && y0 === y1) break;
var e2 = err;
if (e2 > -dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
答案 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上尝试文件