简体   繁体   中英

HTML5 canvas how to scale context.getImageData of image button

I am having an issue with context.getImageData() after I scaled down the canvas. I have canvas added to the HTML page:

 <canvas id="canvas" width="960" height="620"></canvas> 

I have image drawn on that canvas acting like button. I am testing the alpha channel to know if mouse is over the button or not:

 var mx = (e) ? (e.offsetX || e.layerX) : 0; var my = (e) ? (e.offsetY || e.layerY) : 0; var cx = mx - (btn.x * this.ratio - 2; var cy = my - btn.y * this.ratio - 2; var pixels = btn.getContext().getImageData(cx, cy, 1, 1); for (var j : number = 3; j < pixels.data.length; j += 4) { if((pixels.data[j])!=0 && e) { console.log('mouse over'); } } 

The button is sliced from the big image and pre-rendered:

 var btn = createCanvas("img.png", 0, 0, 100, 100); function createCanvas(img, sx , sy , w , h ) { var canvas = document.createElement("canvas"); canvas.width = w; canvas.height = h; var ctx = canvas.getContext("2d"); ctx.drawImage(img, sx, sy, w, h, 0, 0, w, h); return canvas; } 

After that sliced button/image is added to the main canvas.

 this.context.drawImage(btn, 0,0, btn.width, btn.height, 100, 100, btn.width, btn.height); 

It works fine until I start to scale the whole canvas.

 function scale() { var scale = {}; scale.x = window.innerWidth / this.canvas.width; scale.y = window.innerHeight / this.canvas.height; var ratio = scale.x <= scale.y ? scale.x : scale.y; } 

After when I scale down the canvas the button hit/over area is bigger than the button/image itself. It looks it hasn't been scaled and it takes the original width and height. The graphic however is scaled accordingly to the canvas scale. I tried to multiply width and height by the ratio but it scale the image of a button but area where mouse reacts is still bigger than the button. What I should change in the code to have that issue gone?

ps I apologize for my English. :)

EDIT

The function I use to scale the canvas

 window.addEventListener('resize', resize, false);
 window.addEventListener('orientationchange', resize, false); 
 var canvas = $('#canvas');
 var ratio = 1;
 var originalCanvasW = 800;
 var originalCanvasH = 600
 function resize(e)
    {
        var scale = {x: 1, y: 1};
        var s : string = '';
        scale.x = window.innerWidth  /  canvas.width;
        scale.y = window.innerHeight /  canvas.height;

        ratio =  scale.x <= scale.y ? scale.x : scale.y;
        ratio = (ratio > 1) ? 1 : ratio;

        canvas.css('width',originalCanvasW*ratio);
        canvas.css('height',originalCanvasH*ratio);
    }

You are scaling the canvas with CSS. When you do that, you aren't actually affecting the canvas itself, you are just affecting its representation in the DOM of the website. Using CSS to scale a canvas is not recommended in most cases, because it doesn't change the internal drawing resolution which means the canvas will be displayed blurred. But it also results in one canvas-pixel no longer being equivalent to one screen-pixel.

context.getImageData does still use the internal resolution ( width="960" height="620 )for its coordinates, while the mouse coordinates you use are measured in the coordinate system of the webpage the canvas is embedded in.

To solve this problem, there are two possibilities:

  • Factor in the current scaling-factor when you transform screen-pixel coordinates (from mouse-events) to canvas-pixel coordinates (for calls to context-functions).
  • Don't scale the canvas through CSS. Directly change the canvas.width and canvas.height and adjust the context.scale accordingly so that 960px is still the full width of the canvas.

I would recommend the second solution, because it will likely also look much better.

I think I finally managed. @Philipp thank you for the direction and stack overflow for the Related column on the right. I have found that post, stackoverflow.com/questions/14544260/ and I rewrite a bit of the resize function pasted and it worked! I am happy, I have been fighting with that from yesterday.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM