drawImage()创建模糊的图像

时间:2018-09-26 15:21:58

标签: performance canvas

很抱歉问这个问题,这个问题已经发布了好几次了,但是其他有关模糊图像的回答并不能帮助我解决模糊问题。

因此,我可以使用drawImage()滚动放大/缩小画布。 在我的项目中,我使用PIXI,但是遇到了同样的问题。

我注意到,在drawImage()中放置图像而不是画布会减少模糊。我应该使用画布,因为我想在上面添加图形。

使用图像生成drawImage()

使用画布生成drawImage()

这里是演示:https://jsfiddle.net/wyllisMonteiro/0dvfe1a3/

代码:

var image = new Image();
var canvas = document.createElement( "canvas" );
var src = "https://www.maisons-elytis-lyonouest.fr/wp-content/uploads/Maison-M.-ST-GENIS-LES-OLLIERES-HD-3.jpg";
var isZoomIn = false;

$( document ).ready( function() {

    // load image
    image.addEventListener( "load", function() {

    // create canvas which store image
        canvas.setAttribute( "id", "test" );
        canvas.width = $( window ).width()-5;
        canvas.height = $( window ).height()-5;

        var context = canvas.getContext( "2d" );
        context.imageSmoothingEnabled       = true;
        context.mozImageSmoothingEnabled    = true;
        context.webkitImageSmoothingEnabled = true;

        context.clearRect( 0, 0, canvas.width, canvas.height );
        context.drawImage( image, 0, 0, canvas.width * 1, canvas.height * 1 );

        document.body.append( canvas );

        // Not usefull for the issue
        $( "#test" ).on( "click", function() {
            var ctx = canvas.getContext( "2d" );
            ctx.fillStyle = "green";
            ctx.fillRect(10, 10, 100, 100);
        } );
    } )
    image.src = src;

    document.addEventListener( 'mousewheel', zoomIn );
    document.addEventListener( 'DOMMouseScroll', zoomIn )

    function zoomIn( e ) {
    // define up or down scroll
        var e = window.event || e; // old IE support
        var canvasCtx = e.target.getContext( "2d" );
        var delta = Math.max( -1, Math.min( 1, ( e.wheelDelta || -e.detail ) ) );

        if( delta == 1 ) {
            if( !isZoomIn ) {
               $( "#test" )[0].getContext( "2d" ).drawImage( $( "#test" )[0], -canvas.width / 2, -300, canvas.width * 2, canvas.height * 2 );
               isZoomIn = true;
            }
        } else {
        isZoomIn = false;
            $( "#test" )[0].getContext( "2d" ).drawImage( image, 0, 0, canvas.width * 1, canvas.height * 1 );
        }
    }

} )

2 个答案:

答案 0 :(得分:0)

在这里,我删除了很多代码,以使其保持超级简单

var src = "https://www.maisons-elytis-lyonouest.fr/wp-content/uploads/Maison-M.-ST-GENIS-LES-OLLIERES-HD-3.jpg";
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var image = new Image();
image.addEventListener("load", function() {  
  context.imageSmoothingEnabled = true;
  context.mozImageSmoothingEnabled = true;
  context.webkitImageSmoothingEnabled = true;
  context.drawImage(image, 0, 0, canvas.width, canvas.height);
});
image.src = src;

document.addEventListener('DOMMouseScroll', zoomIn);
document.addEventListener('mousewheel', zoomIn)


function zoomIn(e) {
  var z = 1
  context.drawImage(image, -1620/z, -1540/z, image.width/z, image.height/z);
}
<canvas id="canvas" height="600" width="900"></canvas>

据我所知没有模糊...
您可以尝试将z = 1更改为更高的值(例如1.5),以查看不同的缩放比例。
我要做的唯一不同就是缩放图像的宽度和高度

答案 1 :(得分:0)

您注意到的内容很容易解释:

从画布上绘制时,实际上是在调整原始图像的缩小版本的大小,该像素已被删除。当您绘制原始图像时,所有像素仍然可以执行放大操作。

因此,显然,使用当前在画布上绘制的降级版本时,您会看到更多的伪像。

要避免这种情况,您可以保留画布的副本,并在其上画上完整的图像质量,然后在此高质量的画布上进行绘制操作。
然后,您就可以在任何缩放级别上,在可见的画布上重新绘制此优质画布。

var out = output.getContext('2d'); // the canvas we will see
// create an 'offscreen' canvas
// it will store our high quality scene
var offscreen = document.createElement('canvas');
var off = offscreen.getContext('2d');

// 'img' won't get used anymore out of 'begin'
var img = new Image();
img.onload = begin;
img.src = "https://www.maisons-elytis-lyonouest.fr/wp-content/uploads/Maison-M.-ST-GENIS-LES-OLLIERES-HD-3.jpg";

var zoomed = false;
var mousedown = false;
var rad = 20;
var grad = off.createRadialGradient(rad/2, rad/2, rad, rad/2, rad/2, 0);
grad.addColorStop(0.2, 'transparent');
grad.addColorStop(1, 'gold');

function begin() {
  // first draw at full quality
  offscreen.width = img.width;
  offscreen.height = img.height;
  off.drawImage(img, 0, 0);
  off.fillStyle = grad;
  off.globalCompositeOperation = 'lighter';
  // then draw to the visible canvas
  drawToMain();
}
function drawToMain() {
  // draw our full quality canvas on the distorted, visible one
  if(zoomed) {
    // uniform scale + translate
    out.setTransform(2,0,0,2,-output.width/2, -output.height/2);
  }
  else {
    out.setTransform(1,0,0,1,0,0);
  }
  out.drawImage(offscreen, 0, 0, output.width, output.height);
}

function drawDot(x, y) {
  // we will draw on the offscreen canvas
  // so we need to convert the visible canvas coordinates
  // to the ones of our normal sized 'offscreen' canvas
  var ratio_x = offscreen.width / output.width;
  var ratio_y = offscreen.height / output.height;
  if(zoomed) {
    // apply the camera transforms
    // and non uniform scale (output distortion)
    off.setTransform(ratio_x / 2, 0,0,ratio_y / 2,0,0);
    x += (output.width / 2);
    y += (output.height / 2);
  }
  else {
    // simply distort our offscreen context by setting its scale factor
    off.setTransform(ratio_x, 0, 0, ratio_y, 0, 0);
  }
  // draw a dot.
  // Note that for such a drawing, you'd be better even redraw from scratch every time
  // instead of keeping an offscreen canvas
  // but for demo purposes...
  off.beginPath();
  off.arc(x, y, (rad * (+zoomed + 1)), 0, Math.PI*2);
  off.translate(x - rad /2, y - rad / 2);
  off.fill();
  // render our offscreen canvas on the visible one
  drawToMain();
}

check.onchange = function toggleZoom() {
  zoomed = !zoomed;
  drawToMain();
};

output.onmousemove = function mousemovehandler(evt) {
  if(mousedown) {
    var rect = output.getBoundingClientRect();
    drawDot(evt.clientX - rect.left, evt.clientY - rect.top);
  }
};
output.onmousedown = function mousedownhandler(evt) {
  mousedown = true;
  output.onmousemove(evt);
};
output.onmouseup = function() {
  mousedown = false;
}
<label>zoom<input type="checkbox" id="check"></label><br>
click and drag to draw dots on the canvas<br>
<canvas id="output" width="500" height="500"></canvas>