Woot! Compass has you covered with trigonometric sine and cosine functions and of course the SASSy @for iterator helps, too.
This jsfiddle demonstrates the compiled result.
Your HTML document is composed of a container for the circle, an element for the circle, a container for items placed on the circle, and the items which will appear on the circle.
Your SASS file is composed of the following. Modify the $positions, $ringSize, and $itemSize variables according to your needs:
// Use either Compass' border-radius mix-in or prefixfree plugin
@import "compass/css3/border-radius";
/**
* on-circle takes a radius, position on a circle, number of possible positions and returns top and left properties
*
* $radius {Number} radius of the circle in pixels
* $ordinalPosition {Number} the position of the item on the circle, counting from 1 (North) through N
* $positions {Number} the number of positions on the circle
* $originX {Number} optional X origin point for the circle, defaults to the radius
* $originY {Number} optional Y origin point for the circle, defaults to the radius
* $offsetX {Number} optional X offset for the item, you might use 1/2 of the width of an item, default is 0
* $offsetY {Number} optional Y offset for the item, you might use 1/2 of the height of an item, default is 0
*/
@mixin on-circle ($radius, $ordinalPosition, $positions, $originX: $radius, $originY: $radius, $offsetX: 0, $offsetY: 0) {
/*
Determine the angle for the position:
Multiply the adjusted zero-based index of the position by the degrees-per-position (360 degrees divided by the
number of positions) and subtract 90 degrees (adjusting to begin at North)
*/
$positionAngleDegrees: ($ordinalPosition - 1)*360/$positions - 90;
/*
Convert the angle to radians:
Multiply the angle by pi and then divide by 180 degrees.
NOTE: This step is necessary because of a bug in handling of the degrees unit when doing iterations, AFAICT
*/
$positionAngleRadians: $positionAngleDegrees * pi() / 180;
/*
Apply the parametric equation of the circle,
http://en.wikipedia.org/wiki/Circle#Equations
via:
http://stackoverflow.com/questions/839899/how-do-i-calculate-a-point-on-a-circles-circumference
x = [origin x] + (r * cos angle)
y = [origin y] + (r * sin angle)
*/
top: #{$originY + $offsetY + $radius * sin($positionAngleRadians)}px;
left: #{$originX + $offsetX + $radius * cos($positionAngleRadians)}px;
}
// How many positions will there be on the circle?
$positions: 13;
// How big is the circle (diameter)?
$ringSize: 180;
// How big is an item? Offsets and margins are based on this value
// such that the center of an item is located on the circle, rather than
// the top left point
$itemSize: 28;
body {
margin: 50px;
}
.ring-container {
border: solid 1px black;
display: inline-block;
}
.ring {
position: relative;
// Use border-box so that margin and border are not included and the size of the element containing the
// rendered circle is the circle size + border + ...
box-sizing: border-box;
width: #{$ringSize}px;
height: #{$ringSize}px;
margin: #{$itemSize/2}px;
border: solid 1px black;
// Make any square into a circle by setting the border radius to it's full width/height
@include border-radius(#{$ringSize}px);
}
.ring-positions {
position: relative;
width: #{$ringSize}px;
height: #{$ringSize}px;
top: #{$itemSize/-2}px;
left: #{$itemSize/-2}px;
}
.ring-position {
position: absolute;
width: #{$itemSize}px;
height: #{$itemSize}px;
@include border-radius(#{$itemSize}px);
// Use box-sizing: border-box if you'll have a border
box-sizing: border-box;
border-color: black;
border-style: solid;
}
@for $i from 1 through $positions {
.ring-position-#{$i} {
@include on-circle($radius: $ringSize / 2, $ordinalPosition: $i, $positions: $positions);
// Just for demonstration of placement
border-width: #{$i/2+3}px;
}
}
No comments:
Post a Comment