Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm writing a review for a book at the moment, and I thought I'd be clever and show off what LaTeX is capable of by adding a x-out-of-y stars graphic. Tikz can do many things so I would have thought that a trick like this would be fairly trivial, however it seems that I cannot figure out a macro to draw the shapes at the right size, let alone fancy tricks such as half-filled stars or something similar. I think the code I have so far might be headed in the right direction:

\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{calc,shadows}

\newcommand*\starfill{%
  \tikz[baseline=(key.base),scale=-3]
  \node[star, star points=5, star point ratio=2.25, fill=black, draw](key) {S};  
}

I've tried to start by drawing a single star shape, but ideally I'd like to define like \starsranking{number}{total} that will output the appropriate shaded number of stars out of total. Is this doable? It doesn't sound particularly difficult.

share|improve this question
    
The star, star points=5, star point ratio=2.25 are your own options, aren't there? You should have a look at \foreach. You need two: one from 1 to \starpoints to make the filled stars and one for \starpoints+1 to 5. The half-filled stars should be do-able with an clipped fill-path. –  Martin Scharrer Feb 18 '11 at 9:28

5 Answers 5

up vote 32 down vote accepted

Here's the code for fully filled stars, now slightly improved thanks to Andrew Stacey's answer to the checkerboard question:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\newcommand\score[2]{
\pgfmathsetmacro\pgfxa{#1+1}
\tikzstyle{scorestars}=[star, star points=5, star point ratio=2.25, draw,inner sep=1.3pt,anchor=outer point 3]
  \begin{tikzpicture}[baseline]
    \foreach \i in {1,...,#2} {
    \pgfmathparse{(\i<=#1?"yellow":"gray")}
    \edef\starcolor{\pgfmathresult}
    \draw (\i*1.75ex,0) node[name=star\i,scorestars,fill=\starcolor]  {};
   }
  \end{tikzpicture}
}

\begin{document}
\score{0}{5} A meagre result.

\score{4}{5} Much better

\score{5}{5} Perfect score!

\end{document}

ranking stars with tikz


And here's the much more elaborate, much more pointless, floating point scoring star macro (I'll leave the simple one in as well, it's a lot more usable):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}

\newcommand\score[2]{
\pgfmathsetmacro\pgfxa{#1+1}
\tikzstyle{scorestars}=[star, star points=5, star point ratio=2.25, draw,inner sep=0.15em,anchor=outer point 3]
\begin{tikzpicture}[baseline]
  \foreach \i in {1,...,#2} {
    \pgfmathparse{(\i<=#1?"yellow":"gray")}
    \edef\starcolor{\pgfmathresult}
    \draw (\i*1em,0) node[name=star\i,scorestars,fill=\starcolor]  {};
   }
   \pgfmathparse{(#1>int(#1)?int(#1+1):0}
   \let\partstar=\pgfmathresult
   \ifnum\partstar>0
     \pgfmathsetmacro\starpart{#1-(int(#1))}
     \path [clip] ($(star\partstar.outer point 3)!(star\partstar.outer point 2)!(star\partstar.outer point 4)$) rectangle 
    ($(star\partstar.outer point 2 |- star\partstar.outer point 1)!\starpart!(star\partstar.outer point 1 -| star\partstar.outer point 5)$);
     \fill (\partstar*1em,0) node[scorestars,fill=yellow]  {};
   \fi

,\end{tikzpicture}
}

\begin{document}
\small\score{2}{5} A meagre result.

\Huge{\score{4.4}{5} Wooo!}

\end{document}

enter image description here

share|improve this answer
    
Like I said, very good (even better since I first said it). I didn't realize coordinates could be averaged with the ! like colors can. I had been going for a style approach so that you could type \node[scorestars,portion=0.25] and get 25% of the star filled. Looks like you could use the append after command key for that. –  Matthew Leingang Feb 18 '11 at 16:06
1  
Blast, I've already voted for this before your edit. I think that the floating point version is fantastic. –  Loop Space Feb 18 '11 at 18:24
    
That is brilliant. Wow. –  zoqaeski Feb 20 '11 at 12:11
    
One question though: is it possible to make the stars scale to the text height? So if the text is \large the stars will also be correspondingly bigger? –  zoqaeski Feb 20 '11 at 12:18
    
@zoqaeski: Done! Just use relative lengths ("ex" and "em") for the size and spacing. –  Jake Feb 20 '11 at 20:06

enter image description here

Asymptote version stars.asy:

size(200);
real sc=20;

picture score(real scoreMark=0,guide star=scale(sc)*unitcircle, int maxscore=5, 
  pen linePen=nullpen, pen bgPen=darkblue, pen scorePen=orange){
  picture pic;
  guide[] g;  
  for(int i=0;i<maxscore;++i){
    g.push(shift((2sc*i,0))*star);
  }
  assert(maxscore>0 && scoreMark>=0 && scoreMark<=maxscore,"***** Wrong score.");
  fill(pic,box((-sc,-sc),(maxscore*2sc-sc,sc)),bgPen);
  fill(pic,box((-sc,-sc),(scoreMark*2sc-sc,sc)),scorePen);
  clip(pic,g);
  draw(pic,g,linePen);
  return pic;
}

guide star;
pair p;
for(int i=0;i<5;++i){
  p=rotate(72*i)*N;
  star=star--p;
  star=star--(scale(0.382)*rotate(72*i+36)*N);
}
star=scale(sc)*(star--cycle);

add(score(scoreMark=1,star,maxscore=7),(0,0));
add(score(scoreMark=2,star,maxscore=7,linePen=lightred,bgPen=lightblue),(0,-3sc));
add(score(scoreMark=3.5,star,maxscore=5,linePen=lightred,bgPen=lightblue),(0,-6sc));
add(score(scoreMark=3.75,star,maxscore=4,linePen=olive,bgPen=white,scorePen=lightgreen),(0,-9sc));

add(score(4.2,bgPen=green+opacity(0.3),scorePen=red+opacity(0.5)),(0,3sc));

To get a standalone stars.pdf run asy -f pdf stars.asy.

share|improve this answer
    
+1. Very nice!!! –  stalking is prohibited Apr 14 '13 at 16:32

I have written a package for ConTeXt that draws X out of Y graphics. It is primarily meant to draw numbers in presentations. It offers stars as one of the options:

enter image description here

\usemodule[visualcounter]

\definepalet
  [star-colors]
  [active=yellow,
     past=yellow,
   future=gray]

\definevisualcounter
  [stars]
  [markers]
  [mpsetups=visualcounter::markers:star, 
   width=1.5EmWidth,
   distance=0.25EmWidth,
   palette=star-colors, 
  ]

\starttext

\startTEXpage[offset=2mm]
\startitemize
  \item \usevisualcounter[n=1, last=5]{stars} That's appalling!
  \item \usevisualcounter[n=2, last=5]{stars} A meagre result.
  \item \usevisualcounter[n=4, last=5]{stars} Woo!
\stopitemize
\stopTEXpage
\stoptext

See documentation for more details.

As the primary purpose of this module is to display page numbers, it does not support fractional values.

share|improve this answer

With PSTricks.

enter image description here

\documentclass[preview,border=12pt,varwidth]{standalone}
\usepackage{pstricks}
\usepackage{multido}
\SpecialCoor
\makeatletter
\def\LoadPSVars{\pstVerb{/ptcm {\pst@number\psunit div} bind def}}
\makeatother

\def\points{}
\def\Star{%
    \xdef\points{}% cleaning
    \multido{\iR=0+72,\ir=36+72}{5}{\xdef\points{\points (10pt;\iR)(5pt;\ir)}}
    \expandafter\pspolygon\points}

\def\Rating#1{% #1: percentage
    \psscalebox{0.35}{%
    \begin{pspicture}(11pt,-11pt)(111pt,11pt)
    \LoadPSVars
    \psclip{\pscustom{\psLoop{5}{\translate(20pt,0)\Star}}}
        \psframe*[linecolor=yellow](11pt,-11pt)(!#1 11 add ptcm 11 ptcm)
    \endpsclip
    \pscustom{\psLoop{5}{\translate(20pt,0)\Star}}
    \end{pspicture}}}

\begin{document}
\begin{enumerate}
    \item \Rating{100} PSTricks
    \item \Rating{50} Asymptote
    \item \Rating{20} Metapost
    \item \Rating{5} TikZ
\end{enumerate}
\end{document}

Warning:

  • \rput will not work inside \pscustom. Use \translate instead!
  • standalone discards my ptcm operator defined in the preamble, so I have to load it manually inside pspicture. It is sad!
share|improve this answer
1  
TikZ, I am sorry. It is just an example! –  stalking is prohibited Apr 14 '13 at 10:02

Jake's answer is very good. Here's the extra half star:

\node[scorestars,fill=gray] {};
\path node[scorestars,fill=yellow] (s) {} [clip] (s.south west) rectangle (s.north);
share|improve this answer
1  
... and here's half a vote. Oh, wait, they don't come in half steps yet so you'll have to have a whole one. (Incidentally, why isn't your name in the list of moderator candidates?) –  Loop Space Feb 18 '11 at 13:07
    
@Matthew: Can you please tell a TikZ noob how to include this into Jake's code? –  Hendrik Vogt Feb 18 '11 at 13:15
    
@Andrew: LOL. I only gave half an answer hoping that Jake could run with it and improve his answer. I already spent an hour trying to make a customizable portion of the star filled so I think I should quit for now. –  Matthew Leingang Feb 18 '11 at 13:44
1  
@Matthew: Consider yourself asked. –  Loop Space Feb 18 '11 at 13:47
3  
@Jake: True that. look at the bright side. You've got 70 rep so far out of it. That and $2.25 will buy you a cup of coffee at Starbucks. –  Matthew Leingang Feb 18 '11 at 16:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.