Skip to content

Commit c806458

Browse files
committed
Ensure cross-hair rendered upon moving pixel sized shape is sharp [2038]
1 parent f2c9a4c commit c806458

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

src/components/shapes/draw.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,13 +435,14 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer) {
435435
var visualCues = shapeLayer.selectAll('.visual-cue').data([0]);
436436

437437
// Enter
438+
var strokeWidth = 1;
438439
visualCues.enter()
439440
.append('path')
440441
.attr({
441442
'fill': '#fff',
442443
'fill-rule': 'evenodd',
443444
'stroke': '#000',
444-
'stroke-width': 1
445+
'stroke-width': strokeWidth
445446
})
446447
.classed('visual-cue', true);
447448

@@ -457,6 +458,9 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer) {
457458
shapeOptions.y0 :
458459
helpers.extractPathCoords(shapeOptions.path, constants.paramIsY)[0]);
459460

461+
anchorX = helpers.transformPosForSharpStrokeRendering(anchorX, strokeWidth);
462+
anchorY = helpers.transformPosForSharpStrokeRendering(anchorY, strokeWidth);
463+
460464
var crossHairPath = 'M' + (anchorX - 1) + ',' + (anchorY - 1) +
461465
'l-8,0 l0,-2 l8,0 l0,-8 l2,0 l0,8 l8,0 l0,2 l-8,0 l0,8 l-2,0 Z';
462466

src/components/shapes/helpers.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,26 @@ exports.getPixelToData = function(gd, axis, isVertical) {
9696

9797
return pixelToData;
9898
};
99+
100+
/**
101+
* Based on the given stroke width, transforms the passed
102+
* position value to represent either a full or half pixel.
103+
*
104+
* In case of an odd stroke width (e.g. 1), this measure ensures
105+
* that a stroke positioned at the returned position isn't rendered
106+
* blurry due to anti-aliasing.
107+
*
108+
* In case of an even stroke width (e.g. 2), this measure ensures
109+
* that the position value is transformed to a full pixel value
110+
* so that anti-aliasing doesn't take effect either.
111+
*
112+
* @param {number} pos The raw position value to be transformed
113+
* @param {number} strokeWidth The stroke width
114+
* @returns {number} either an integer or a .5 decimal number
115+
*/
116+
exports.transformPosForSharpStrokeRendering = function(pos, strokeWidth) {
117+
var strokeWidthIsOdd = Math.round(strokeWidth % 2) === 1;
118+
var posValAsInt = Math.round(pos);
119+
120+
return strokeWidthIsOdd ? posValAsInt + 0.5 : posValAsInt;
121+
};

0 commit comments

Comments
 (0)