Skip to content

Commit

Permalink
Fix for issue lojjic#64: Prevent rounding in BgPosition calculation a…
Browse files Browse the repository at this point in the history
…nd add special-case logic for perfectly horizontal/vertical angles to prevent them from getting slightly off.
  • Loading branch information
Jason Johnston committed Sep 3, 2010
1 parent 04ed5d5 commit c5352d1
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
22 changes: 15 additions & 7 deletions sources/BackgroundRenderer.js
Expand Up @@ -156,8 +156,8 @@ PIE.BackgroundRenderer = PIE.RendererBase.newRenderer( {
// Positioning - find the pixel offset from the top/left and convert to a ratio
// The position is shifted by half a pixel, to adjust for the half-pixel coordorigin shift which is
// needed to fix antialiasing but makes the bg image fuzzy.
pxX = bgPos.x + bwL + 0.5;
pxY = bgPos.y + bwT + 0.5;
pxX = Math.round( bgPos.x ) + bwL + 0.5;
pxY = Math.round( bgPos.y ) + bwT + 0.5;
fill.position = ( pxX / elW ) + ',' + ( pxY / elH );

// Repeating - clip the image shape
Expand Down Expand Up @@ -192,6 +192,7 @@ PIE.BackgroundRenderer = PIE.RendererBase.newRenderer( {
stops = info.stops,
stopCount = stops.length,
PI = Math.PI,
UNDEF,
startX, startY,
endX, endY,
startCornerX, startCornerY,
Expand Down Expand Up @@ -247,7 +248,7 @@ PIE.BackgroundRenderer = PIE.RendererBase.newRenderer( {

// Normalize the angle to a value between [0, 360)
function normalizeAngle() {
if( angle < 0 ) {
while( angle < 0 ) {
angle += 360;
}
angle = angle % 360;
Expand Down Expand Up @@ -301,8 +302,14 @@ PIE.BackgroundRenderer = PIE.RendererBase.newRenderer( {
deltaX = endX - startX;
deltaY = endY - startY;

if( angle === undefined ) {
angle = -Math.atan2( deltaY, deltaX ) / PI * 180;
if( angle === UNDEF ) {
// Get the angle based on the change in x/y from start to end point. Checks first for horizontal
// or vertical angles so they get exact whole numbers rather than what atan2 gives.
angle = ( !deltaX ? ( deltaY < 0 ? 90 : 270 ) :
( !deltaY ? ( deltaX < 0 ? 180 : 0 ) :
-Math.atan2( deltaY, deltaX ) / PI * 180
)
);
normalizeAngle();
findCorners();
}
Expand All @@ -313,8 +320,9 @@ PIE.BackgroundRenderer = PIE.RendererBase.newRenderer( {
// drawn diagonally from one corner to its opposite corner, which will only appear to the
// viewer as 45 degrees if the shape is equilateral. We adjust for this by taking the x/y deltas
// between the start and end points, multiply one of them by the shape's aspect ratio,
// and get their arctangent, resulting in an appropriate VML angle.
vmlAngle = Math.atan2( deltaX * w / h, deltaY ) / PI * 180;
// and get their arctangent, resulting in an appropriate VML angle. If the angle is perfectly
// horizontal or vertical then we don't need to do this conversion.
vmlAngle = ( angle % 90 ) ? Math.atan2( deltaX * w / h, deltaY ) / PI * 180 : ( angle + 90 );

// VML angles are 180 degrees offset from CSS angles
vmlAngle += 180;
Expand Down
14 changes: 9 additions & 5 deletions sources/BgPosition.js
Expand Up @@ -4,6 +4,10 @@
* @param {Array.<PIE.Tokenizer.Token>} tokens The tokens making up the background position value.
*/
PIE.BgPosition = (function() {

var length_fifty = new PIE.Length( '50%' );


function BgPosition( tokens ) {
this.tokens = tokens;
}
Expand All @@ -21,7 +25,6 @@ PIE.BgPosition = (function() {
var tokens = this.tokens,
len = tokens.length,
length_zero = PIE.Length.ZERO,
length_fifty = new PIE.Length( '50%' ),
type_ident = PIE.Tokenizer.Type.IDENT,
type_length = PIE.Tokenizer.Type.LENGTH,
type_percent = PIE.Tokenizer.Type.PERCENT,
Expand Down Expand Up @@ -76,7 +79,8 @@ PIE.BgPosition = (function() {
},

/**
* Find the coordinates of the background image from the upper-left corner of the background area
* Find the coordinates of the background image from the upper-left corner of the background area.
* Note that these coordinate values are not rounded.
* @param {Element} el
* @param {number} width - the width for percentages (background area width minus image width)
* @param {number} height - the height for percentages (background area height minus image height)
Expand All @@ -88,11 +92,11 @@ PIE.BgPosition = (function() {
pxY = vals[3].pixels( el, height );

return {
x: Math.round( vals[0] === 'right' ? width - pxX : pxX ),
y: Math.round( vals[2] === 'bottom' ? height - pxY : pxY )
x: vals[0] === 'right' ? width - pxX : pxX,
y: vals[2] === 'bottom' ? height - pxY : pxY
};
}
};

return BgPosition;
})();
})();
20 changes: 19 additions & 1 deletion tests/gradient-tests.html
Expand Up @@ -13,6 +13,7 @@
overflow: hidden;
background:url(border.png);
position: relative;
z-index: 0;
zoom: 1;
}

Expand Down Expand Up @@ -167,7 +168,18 @@
-pie-background: linear-gradient(45deg, red, yellow, green, blue);
}


#lineup p {
border: 0;
width: 40%;
height: 50px;
margin-right: 0;
border-radius: 0;
background: -moz-linear-gradient(center bottom,rgb(170,222,249) 0%,rgb(63,158,210) 100%);
-pie-background: linear-gradient(center bottom,rgb(170,222,249) 0%,rgb(63,158,210) 100%);
}
#lineup2 {
margin-left: 0;
}


</style>
Expand Down Expand Up @@ -215,5 +227,11 @@ <h1>Multiple color stops along linear gradient</h1>
<p id="multi6">linear-gradient(45deg, red, yellow, green, blue);</p>
</div>

<div class="section" id="lineup">
<h1>Lining up (<a href="http://github.com/lojjic/PIE/issues/issue/64">issue 64</a>)</h1>
<p id="lineup1">element 1</p>
<p id="lineup2">element 2</p>
</div>

</body>
</html>

0 comments on commit c5352d1

Please sign in to comment.