画布中的矩形大小错误
Posted
技术标签:
【中文标题】画布中的矩形大小错误【英文标题】:Wrong rectangle size in canvas 【发布时间】:2012-03-06 09:17:51 【问题描述】:我正在实现一个颜色选择器。渲染有问题。当我调用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 = 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://***.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>
【问题讨论】:
【参考方案1】:首先要知道canvas
元素的内在尺寸 = 内部坐标空间 中的像素数(由width
和@ 设置987654323@ 属性和属性)。它还具有外部尺寸(style.width
和style.height
),即图像在网页内的像素数。内部像素被缩放以适应外部空间。
这很令人困惑,因为 img
也有内在和外在维度,但属性的名称与 canvas
完全不同。如果在图片上设置width
和height
,基本上和设置style.width
或者style.height
是一样的;他们都设置了外部尺寸来缩放页面内的图像。同时,您只能使用新的 naturalWidth
和 naturalHeight
(仅限 HTML5 浏览器)属性获取 img
的固有尺寸。
如果未在img
和canvas
上设置外部尺寸,则图像将以与内部尺寸相同的尺寸布局(即比例因子为 1)。
现在,当您使用 jQuery 时,$(canvas).width('310px')
与设置外部维度的$(canvas).css('310px')
相同。您必须调用$(canvas).prop('width', 310)
或简单地设置canvas.width = 310
来设置内在宽度。
【讨论】:
以上是关于画布中的矩形大小错误的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript中易犯的小错误-------常见错误五:低效的DOM操作
C 代码中的一个小错误,用于在不使用 * 运算符的情况下将 2 位二进制数相乘
JavaScript中易犯的小错误-------常见错误三:内存泄露