画布中的矩形大小错误 [英] Wrong rectangle size in canvas

查看:83
本文介绍了画布中的矩形大小错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个颜色选择器。渲染有问题。当我调用 c.fillRect(0,0,100,80); 时,该矩形的大小为103x42像素,而不是100x80。怎么了



此外,矩形是抗锯齿的。我需要将位置偏移(0.5,0.5)以避免AA吗?我没有使用任何坐标系转换。

  colorSlider = function($ e,color){
this ._ $ canvas = $('< canvas>< / canvas>');
this._c = this ._ $ canvas [0] .getContext(’2d’);
this._color =颜色|| {r:0,g:0,b:0};
this ._ $ canvas.width(‘310px’);
this ._ $ canvas.height(‘80px’);
$ e.append(this ._ $ canvas);
this._render();
var me = this;
this ._ $ canvas.mousedown(function(e){me._mouseDown.call(me,e)});
this ._ $ canvas.mouseup(function(e){me._mouseUp.call(me,e)});
this ._ $ canvas.mousemove(function(e){me._mouseMove.call(me,e)});
this._dragChannel = 0;
}

colorSlider.prototype._pointInRect = function(x,y,rect){
return x> = rect.x& x< =矩形x +矩形w&& y> =矩形y&& y< =矩形y +矩形h;
}

colorSlider.prototype._findTarget = function(event){
var x = event.offsetX;
var y = event.offsetY;
console.log(x,y,this._rectR);
if(this._pointInRect(x,y,this._rectRThumb)){
return {target:1,value:x-this._rectR.x};
}
if(this._pointInRect(x,y,this._rectGThumb)){
return {target:2,value:x-this._rectG.x};
}
if(this._pointInRect(x,y,this._rectBThumb)){
return {target:3,value:x-this._rectB.x};
}
if(this._pointInRect(x,y,this._rectR)){
return {target:4,value:x-this._rectR.x};
}
if(this._pointInRect(x,y,this._rectG)){
return {target:5,value:x-this._rectG.x};
}
if(this._pointInRect(x,y,this._rectB)){
return {target:6,value:x-this._rectB.x};
}
返回null;
}

colorSlider.prototype._mouseDown = function(event){
this._dragChannel = 0;
var target = this._findTarget(event);
if(target){
switch(target.target){
情况1:
this._dragChannel = 1;
休息时间;
情况2:
this._dragChannel = 2;
休息时间;
情况3:
this._dragChannel = 3;
休息时间;
情况4:
this._color.r = target.value;
休息时间;
情况5:
this._color.g = target.value;
休息时间;
情况6:
this._color.b = target.value;
休息时间;
}
this._render();
}
};

colorSlider.prototype._mouseUp = function(event){
//console.log(’mouseUp’);
};

colorSlider.prototype._mouseMove = function(event){
//console.log('mouseMove',event);
};

colorSlider.prototype.padding = 4;

colorSlider.prototype._render = function(){
var padding = this.padding;
var厚度= 16;
var c = this._c;
var w = 255;
var h = this ._ $ canvas.height();

c.clearRect(0,0,this ._ $ canvas.width(),this ._ $ canvas.height());

var梯度= c.createLinearGradient(padding,0,w,0);
c.fillStyle =渐变;

gradient.addColorStop(0,this.colorToHex({r:0,g:this._color.g,b:this._color.b}));
gradient.addColorStop(1,this.colorToHex({r:255,g:this._color.g,b:this._color.b}));
c.fillRect(填充,填充,w,厚度);
c.lineWidth = 0;
c.fillRect(0,0,100,80);
this._rectR = {x:填充,y:填充,w:w,h:厚度};

梯度= c.createLinearGradient(padding,0,w,0);
c.fillStyle =渐变;
gradient.addColorStop(0,this.colorToHex({r:this._color.r,g:0,b:this._color.b}));
gradient.addColorStop(1,this.colorToHex({r:this._color.r,g:255,b:this._color.b}));
c.fillRect(填充,填充+厚度+ 2 *填充,w,厚度);
this._rectG = {x:填充,y:填充+厚度+ 2 *填充,w:w,h:厚度};

梯度= c.createLinearGradient(padding,0,w,0);
c.fillStyle =渐变;
gradient.addColorStop(0,this.colorToHex({r:this._color.r,g:this._color.g,b:0}));
gradient.addColorStop(1,this.colorToHex({r:this._color.r,g:this._color.g,b:255}));
c.fillRect(填充,填充+ 2 *(厚度+ 2 *填充),w,厚度);
this._rectB = {x:padding,y:padding + 2 *(thickness + 2 * padding),w:w,h:thickness};

c.lineWidth = 2;
c.fillStyle =白色;
c.strokeStyle =#888888;

this._rectRThumb = {x:padding + this._color.r-2,y:padding / 2,w:8,h:20,r:2};
this.drawRoundedRectangle(c,this._rectRThumb);

this._rectGThumb = {x:填充+ this._color.g-2,y:填充/ 2 + 2 *填充+厚度,w:8,h:20,r:2};
this.drawRoundedRectangle(c,this._rectGThumb);

this._rectBThumb = {x:填充+ this._color.b-2,y:填充/ 2 + 2 *(2 *填充+厚度),w:8,h:20,r :2};
this.drawRoundedRectangle(c,this._rectBThumb);
};

colorSlider.prototype.colorToHex = function(color){
var c ='#'
+(color.r + 256).toString(16).substr(1 ,2)
+(color.g + 256).toString(16).substr(1、2)
+(color.b + 256).toString(16).substr(1,2 );
console.log(c);
返回c;
};

// http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas
colorSlider.prototype.drawRoundedRectangle =函数(c,rect){
var x = rect.x;
var y = rect.y;
var width = rect.w;
var height = rect.h;
var radius = rect.r;
c.beginPath();
c.moveTo(x +半径,y);
c.lineTo(x +宽度-半径,y);
c.quadraticCurveTo(x +宽度,y,x +宽度,y +半径);
c.lineTo(x +宽度,y +高度-半径);
c.quadraticCurveTo(x +宽度,y +高度,x +宽度-半径,y +高度);
c.lineTo(x +半径,y +高度);
c.quadraticCurveTo(x,y + height,x,y + height-radius);
c.lineTo(x,y + radius);
c.quadraticCurveTo(x,y,x +半径,y);
c.closePath();
c.stroke();
c.fill();
};

index.html

 < script> 
$(function(){
$(#directionLight,#ambientLight)。each(function(){
new colorSlider($(this));
}) ;

});
< / script>

< body>
< div>定向光< / div>
< div id = directionLight>< / div>
< div>环境光< / div>
< div id = ambientLight>< / div>
< / body>


解决方案

首先要知道的是 canvas 元素具有内部尺寸 = 内部坐标空间中的像素数(由 width 高度属性和属性)。它还具有外部尺寸 style.width style.height ),即图片在网页中所占的像素数。缩放固有像素以适应外部空间。



这令人困惑,因为 img 也具有固有尺寸和外部尺寸,但属性的名称与 canvas 完全不同。如果在图像上设置宽度高度,则基本上与设置样式相同。宽度 style.height ;他们都设置了外部尺寸来缩放页面中的图像。同时,您只能使用新的 naturalWidth 获得 img 内部尺寸 naturalHeight (仅适用于HTML5浏览器)属性。



如果两个 img 和 canvas ,图像将以与固有尺寸相同的尺寸进行布局(即比例因子为1)。 / p>

现在,当您使用jQuery时, $(canvas).width('310px') $(canvas).css('310px'),用于设置外部尺寸。您必须调用 $(canvas).prop('width',310)或简单地设置 canvas.width = 310 设置固有宽度。


I'm implementing a color picker. There is problem with the rendering. When I call c.fillRect(0, 0, 100, 80); the size of that rectangle is 103x42 px instead of 100x80. What is wrong here?

Also, rectangles are antialiased. Do I need offset the position by (0.5, 0.5) to avoid AA? I didn't use any kind of the coordinate system transformations.

colorSlider = function($e, color) {
    this._$canvas = $('<canvas></canvas>');
    this._c = this._$canvas[0].getContext('2d');
    this._color = color || { r: 0, g: 0, b: 0 };
    this._$canvas.width('310px');
    this._$canvas.height('80px');
    $e.append(this._$canvas);
    this._render();
    var me = this;
    this._$canvas.mousedown(function(e) { me._mouseDown.call(me, e) });
    this._$canvas.mouseup(function(e) { me._mouseUp.call(me, e) });
    this._$canvas.mousemove(function(e) { me._mouseMove.call(me, e) });
    this._dragChannel = 0;
}

colorSlider.prototype._pointInRect = function(x, y, rect) {
    return x >= rect.x && x <= rect.x + rect.w && y >= rect.y && y <= rect.y + rect.h;
}

colorSlider.prototype._findTarget = function(event) {
    var x = event.offsetX;
    var y = event.offsetY;
    console.log(x, y, this._rectR);
    if (this._pointInRect(x, y, this._rectRThumb)) {
        return { target: 1, value: x - this._rectR.x };
    }
    if (this._pointInRect(x, y, this._rectGThumb)) {
        return { target: 2, value: x - this._rectG.x };
    }
    if (this._pointInRect(x, y, this._rectBThumb)) {
        return { target: 3, value: x - this._rectB.x };
    }
    if (this._pointInRect(x, y, this._rectR)) {
        return { target: 4, value: x - this._rectR.x };
    }
    if (this._pointInRect(x, y, this._rectG)) {
        return { target: 5, value: x - this._rectG.x };
    }
    if (this._pointInRect(x, y, this._rectB)) {
        return { target: 6, value: x - this._rectB.x };
    }
    return null;
}

colorSlider.prototype._mouseDown = function(event) {
    this._dragChannel = 0;
    var target = this._findTarget(event);
    if (target) {
        switch (target.target) {
            case 1:
                this._dragChannel = 1;
                break;
            case 2:
                this._dragChannel = 2;
                break;
            case 3:
                this._dragChannel = 3;
                break;
            case 4:
                this._color.r = target.value;
                break;
            case 5:
                this._color.g = target.value;
                break;
            case 6:
                this._color.b = target.value;
                break;
        }
        this._render();
    }
};

colorSlider.prototype._mouseUp = function(event) {
    //console.log('mouseUp');
};

colorSlider.prototype._mouseMove = function(event) {
    //console.log('mouseMove', event);
};

colorSlider.prototype.padding = 4;

colorSlider.prototype._render = function() {
    var padding = this.padding;
    var thickness = 16;
    var c = this._c;
    var w = 255;
    var h = this._$canvas.height();

    c.clearRect(0, 0, this._$canvas.width(), this._$canvas.height());

    var gradient = c.createLinearGradient(padding, 0, w, 0);
    c.fillStyle = gradient;

    gradient.addColorStop(0, this.colorToHex({ r: 0, g: this._color.g, b: this._color.b }));
    gradient.addColorStop(1, this.colorToHex({ r: 255, g: this._color.g, b: this._color.b }));
    c.fillRect(padding, padding, w, thickness);
    c.lineWidth = 0;
    c.fillRect(0, 0, 100, 80);
    this._rectR = { x: padding, y: padding, w: w, h: thickness };

    gradient = c.createLinearGradient(padding, 0, w, 0);
    c.fillStyle = gradient;
    gradient.addColorStop(0, this.colorToHex({ r: this._color.r, g: 0, b: this._color.b }));
    gradient.addColorStop(1, this.colorToHex({ r: this._color.r, g: 255, b: this._color.b }));
    c.fillRect(padding, padding + thickness + 2 * padding, w, thickness);
    this._rectG = { x: padding, y: padding + thickness + 2 * padding, w: w, h: thickness };

    gradient = c.createLinearGradient(padding, 0, w, 0);
    c.fillStyle = gradient;
    gradient.addColorStop(0, this.colorToHex({ r: this._color.r, g: this._color.g, b: 0 }));
    gradient.addColorStop(1, this.colorToHex({ r: this._color.r, g: this._color.g, b: 255 }));
    c.fillRect(padding, padding + 2 * (thickness + 2 * padding), w, thickness);
    this._rectB = { x: padding, y: padding + 2 * (thickness + 2 * padding), w: w, h: thickness };

    c.lineWidth = 2;
    c.fillStyle = "white";
    c.strokeStyle = "#888888";

    this._rectRThumb = { x: padding + this._color.r - 2, y: padding / 2, w: 8, h: 20, r: 2 };
    this.drawRoundedRectangle(c, this._rectRThumb);

    this._rectGThumb = { x: padding + this._color.g - 2, y: padding / 2 + 2 * padding + thickness, w: 8, h: 20, r: 2 };
    this.drawRoundedRectangle(c, this._rectGThumb);

    this._rectBThumb = { x: padding + this._color.b - 2, y: padding / 2 + 2 * (2 * padding + thickness), w: 8, h: 20, r: 2 };
    this.drawRoundedRectangle(c, this._rectBThumb);
};

colorSlider.prototype.colorToHex = function(color) {
    var c = '#'
    + (color.r + 256).toString(16).substr(1, 2)
    + (color.g + 256).toString(16).substr(1, 2)
    + (color.b + 256).toString(16).substr(1, 2);
    console.log(c);
    return c;
};

// http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas
colorSlider.prototype.drawRoundedRectangle = function(c, rect) {
    var x = rect.x;
    var y = rect.y;
    var width = rect.w;
    var height = rect.h;
    var radius = rect.r;
    c.beginPath();
    c.moveTo(x + radius, y);
    c.lineTo(x + width - radius, y);
    c.quadraticCurveTo(x + width, y, x + width, y + radius);
    c.lineTo(x + width, y + height - radius);
    c.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    c.lineTo(x + radius, y + height);
    c.quadraticCurveTo(x, y + height, x, y + height - radius);
    c.lineTo(x, y + radius);
    c.quadraticCurveTo(x, y, x + radius, y);
    c.closePath();
    c.stroke();
    c.fill();
};

index.html

<script>
$(function() {
    $("#directionalLight,#ambientLight").each(function() {
        new colorSlider($(this));
    });

});
</script>

<body>
<div>Directional light</div>
<div id="directionalLight"></div>
<div>Ambient light</div>
<div id="ambientLight"></div>
</body>

解决方案

The first thing to know is that a canvas element has intrinsic dimensions = number of pixels in the inside coordinate space (set by the width and height attributes and properties). It also has extrinsic dimensions (style.width and style.height) which is the number of pixels that the image takes within the webpage. The intrinsic pixels are scaled to fit the extrinsic space.

It's confusing because an img also has intrinsic and extrinsic dimensions, but the names of the properties are completely different from canvas. If you set width and height on an image, it's basically the same as setting style.width or style.height; they both set the extrinsic dimensions to scale the image within the page. Meanwhile, you can only get the intrinsic dimensions of an img using the new naturalWidth and naturalHeight (HTML5 browsers only) properties.

If the extrinsic dimensions are not set on both img and canvas, the image will be laid out at the same size as the intrinsic dimensions (i.e., scale factor would be 1).

Now, when you use jQuery, $(canvas).width('310px') is the same as $(canvas).css('310px'), which sets the extrinsic dimensions. You have to call $(canvas).prop('width', 310) or simply set canvas.width = 310 to set the intrinsic width.

这篇关于画布中的矩形大小错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆