HTML5 - Canvas, drawImage() рисует изображение размытым

Я пытаюсь нарисовать следующее изображение на холсте, но оно выглядит размытым, несмотря на определение размера холста. Как вы можете видеть ниже, изображение четкое и четкое, тогда как на холсте оно размытое и пиксельное.

enter image description here

и вот как это выглядит (левый является оригиналом, а правый - нарисованным холстом и размытым).

enter image description here

Что я делаю не так?

console.log('Hello world')

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32

playerImg.onload = function() {
  ctx.drawImage(playerImg, 0, 0, 32, 32);
};
#canvas {
  background: #ABABAB;
  position: relative;
  height: 352px;
  width: 512px;
  z-index: 1;
}
<canvas id="canvas" height="352" width="521"></canvas>

Ответ 1

Причина этого происходит из-за Anti Aliasing. Просто установите imageSmoothingEnabled как false

context.imageSmoothingEnabled = false;

Вот jsFiddle verson

jsFiddle: https://jsfiddle.net/mt8sk9cb/

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'

playerImg.onload = function() {
  ctx.imageSmoothingEnabled = false;
  ctx.drawImage(playerImg, 0, 0, 256, 256);
};

Ответ 2

Ваша проблема заключается в том, что ваши ограничения css canvas{width:512} и свойство canvas width=521 заставят ваш браузер перепрограммировать весь холст.

Чтобы избежать этого, удалите эти объявления css.

var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()

// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32

playerImg.onload = function() {
  ctx.drawImage(playerImg, 0, 0, 32, 32);
};
#canvas {
  background: #ABABAB;
  position: relative;
  z-index: 1;
}
<canvas id="canvas" height="352" width="521"></canvas>

Ответ 3

Следующий код работает для меня:

img.onload = function () {
  canvas.width = img.width;
  canvas.height = img.height;
  context.drawImage(img, 0, 0, img.width, img.height, 0, 0, img.width, img.height);
};
img.src = e.target.result;  // your src

Ответ 4

В дополнение к ответу @canvas.

context.imageSmoothingEnabled = false;

Отлично работает. Но в моем случае при изменении размера холста это свойство возвращается к значению true.

window.addEventListener('resize', function(e){
    context.imageSmoothingEnabled = false;
}, false)

Ответ 5

Поскольку я сталкивался с этим более ранним постом по некоторым из моих проблем, здесь еще больше понимания размытых изображений для наложения поверх решения 'imageSmoothingEnabled'.

Это более конкретно для случая использования рендеринга для конкретного монитора, и только некоторые люди столкнулись с этой проблемой, если они пытались визуализировать графику с качеством сетчатки на холсте с неутешительными результатами.

По сути, мониторы высокой плотности означают, что вашему холсту необходимо учитывать эту дополнительную плотность пикселей. Если вы ничего не сделаете, canvas будет отображать только достаточное количество информации о пикселях в своем контексте, чтобы учесть соотношение пикселей 1.

Поэтому для многих современных мониторов, у которых есть коэффициенты> 1, вы должны изменить свой контекст холста, чтобы учесть эту дополнительную информацию, но сохранить свой холст нормальной ширины и высоты.

Для этого вы просто устанавливаете ширину и высоту контекста рендеринга равными: целевой ширине и высоте * window.devicePixelRatio.

canvas.width = target width * window.devicePixelRatio;
canvas.height = target height * window.devicePixelRatio;

Затем вы устанавливаете стиль холста, чтобы размер холста соответствовал нормальным размерам:

canvas.style.width = '${target width}px';
canvas.style.height = '${target height}px';

В последний раз вы отображаете изображение с максимальным размером контекста, который позволяет изображение. В некоторых случаях (например, при визуализации изображений в формате SVG) вы все равно можете получить лучшее качество изображения, визуализируя изображение с размерами в пикселях:

ctx.drawImage(
    img, 0, 0, 
    img.width * window.devicePixelRatio, 
    img.height * window.devicePixelRatio
  );

Итак, чтобы показать это явление, я сделал скрипку. Вы НЕ увидите разницы в качестве холста, если вы используете монитор pixelRatio, близкий к 1.

https://jsfiddle.net/ufjm50p9/2/

Ответ 6

Простой наконечник: нарисуйте с .5 в x и y. например drawImage (, 0.5, 0.5): D Там вы получите четкие края: D