Diese Frage schließt sich meiner Frage "Wie erstelle ich neue Shapes in TikZ" an.

Ich würde gerne die Flächen der Dreiecke in grau Einfärben und den Bildschirm schwarz (am besten mit Shading). Ich habe versucht mit \pgfusepath{fill} die Flächen zu füllen, aber da ist gleich das ganze Shape eingefärbt worden. Dann habe ich versucht die Paths die ich füllen möchte in ein Scope zu packen, was aber nicht geklappt hat.

Nun zur konkreten Frage: Wie kann ich die Flächen (Screen und Triangles) noch einfärben?

gefragt 26 Feb '14, 16:42

funkytex's gravatar image

funkytex
177337
Akzeptiert-Rate: 0%


Update

Wenn man den Vorschlag von esdd auf das Beispiel umsetzt, liegen die Füllflächen leider über der inneren Hälfte der Umrandungslinien. Um dies zu umgehen kann man mit \tikz@mode die Zeichenmodi laden und mit \iftikz@mode@draw überprüfen, ob nur gefüllt oder auch gezeichnet werden soll.1

Wahrscheinlich kann man die Teile, die im \beforebackgroundpath sind, aus dem \backgroundpath entfernen.

1: Vielleicht muss man die Modes noch wieder deaktivieren, um unvorhersehbares Verhalten zu vermeiden. Bitte um Rückmeldung.

Code

Open in writeLaTeX
\documentclass[paper=20cm:10cm, pagesize]{scrartcl}
\usepackage{tikz}
\pagestyle{empty}

\makeatletter
\pgfdeclareshape{computer}{%
    % inherit anchors
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}

    \backgroundpath{
        %%% DRAW OUTLINE OF SHAPE %%%
        % store lower left in xa/ya and upper right in xb/yb
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y 
        % move to point xb/yb (north east)
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{\pgf@yb}}
        % draw a line between upper right (xb,yb) and upper left (xa,yb)
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xa}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xb}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xb}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.2\pgf@ya}}
        \pgfpathclose
        %%% DRAW SCREEN %%%
        \pgfpathmoveto{\pgfpoint{.85\pgf@xb}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.05\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xb}{.05\pgf@ya}}
        \pgfpathclose
        %%% DRAW UPPER RECTANGLE OF CASE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.5\pgf@ya}}
        \pgfpathclose
        %%% DRAW LEFT TRIANGLE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xa}{\pgf@ya}}
        \pgfpathclose
        %%% DRAW RIGHT TRIANGLE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xb}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
    }
    \beforebackgroundpath{
        \tikz@mode% installs the mode settings
        %%% FILL SCREEN %%%
        \pgfpathmoveto{\pgfpoint{.85\pgf@xb}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.05\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xb}{.05\pgf@ya}}
        \pgfpathclose
        \pgfsetfillcolor{black}
        \iftikz@mode@draw% fill and stroke if draw is choosen
            \pgfusepath{fill, stroke}
        \else% fill only if draw is not choosen
            \pgfusepath{fill}
        \fi
        %%% FILL LEFT TRIANGLE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xa}{\pgf@ya}}
        \pgfpathclose
        %%% DRAW RIGHT TRIANGLE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xb}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
        \pgfsetfillcolor{gray}
        \iftikz@mode@draw
            \pgfusepath{fill, stroke}
        \else
            \pgfusepath{fill}
        \fi
    }
}
\makeatother

\tikzset{
    shape example/.style={
        color=black!30,
        draw,
        fill=yellow!30,
        line width=.1cm,
        inner xsep=2.5cm,
        inner ysep=2.5cm
    }
}

\begin{document}
    \begin{tikzpicture}
        \node[shape example, computer, name=s] at (0,0) {};
        \foreach \anchor/\placement in {north/above, west/left, east/right, south/below}
            \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} node[\placement] {\scriptsize\texttt{(s.\anchor)}};
        \draw[shift=(s.center), white] plot[mark=x] coordinates{(0,0)} node[above] {\scriptsize\texttt{(s.center)}};
        \begin{scope}[xshift=8cm]
            \node[shape example, computer, name=s, draw=none] at (0,0) {};
            \foreach \anchor/\placement in {north/above, west/left, east/right, south/below}
                \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} node[\placement] {\scriptsize\texttt{(s.\anchor)}};
            \draw[shift=(s.center), white] plot[mark=x] coordinates{(0,0)} node[above] {\scriptsize\texttt{(s.center)}};
        \end{scope}
    \end{tikzpicture}
\end{document}

Ergebnis

Ergebnis


Ursprüngliche Antwort:

Pfade benutzen

Du musst die Pfade benutzen, wenn sie fertig sind. PGF scheint dies am Ende automatisch zu tun. Wenn du einzelne Teile unterschiedlich verwenden willst, musst du das aber explizit tun. Dafür dient \pgfusepath{stroke}.

Nur die Füllfarbe definieren

Die Füllfarbe solltest du mit \pgfsetfillcolor setzten. \color setzt ebenfalls die Strichfarbe.

Code

Open in writeLaTeX
\documentclass[a5paper, pagesize]{scrartcl}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{computer}{%
    % inherit anchors
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}

    \backgroundpath{
        %%% DRAW OUTLINE OF SHAPE %%%
        % store lower left in xa/ya and upper right in xb/yb
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y 
        % move to point xb/yb (north east)
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{\pgf@yb}}
        % draw a line between upper right (xb,yb) and upper left (xa,yb)
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xa}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xb}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.3\pgf@xb}{.2\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.2\pgf@ya}}
        \pgfpathclose
        \pgfusepath{stroke}
        %%% DRAW SCREEN %%%
        \pgfsetfillcolor{black}
        \pgfpathmoveto{\pgfpoint{.85\pgf@xb}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.85\pgf@yb}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xa}{.05\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.85\pgf@xb}{.05\pgf@ya}}
        \pgfpathclose
        \pgfusepath{fill,stroke}
        %%% DRAW UPPER RECTANGLE OF CASE %%%
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{.5\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{.5\pgf@ya}}
        \pgfpathclose
        \pgfusepath{stroke}
        %%% DRAW LEFT TRIANGLE %%%
        \pgfsetfillcolor{gray}
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xa}{\pgf@ya}}
        \pgfpathclose
        \pgfusepath{fill,stroke}
        %%% DRAW RIGHT TRIANGLE %%%
        \pgfsetfillcolor{gray}
        \pgfpathmoveto{\pgfpoint{\pgf@xb}{.65\pgf@ya}}
        \pgfpathlineto{\pgfpoint{.5\pgf@xb}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
        \pgfusepath{fill,stroke}
    }
}
\makeatother

\tikzset{
    shape example/.style={
        color=black!30,
        draw,
        fill=yellow!30,
        line width=.1cm,
        inner xsep=2.5cm,
        inner ysep=2.5cm
    }
}

\begin{document}
    \begin{tikzpicture}
        \node[shape example, computer, name=s] at (0,0) {};
        \foreach \anchor/\placement in {north/above, west/left, east/right, south/below}
            \draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} node[\placement] {\scriptsize\texttt{(s.\anchor)}};
        \draw[shift=(s.center), white] plot[mark=x] coordinates{(0,0)} node[above] {\scriptsize\texttt{(s.center)}};
    \end{tikzpicture}
\end{document}
Permanenter link

beantwortet 27 Feb '14, 11:23

sudo's gravatar image

sudo
2.0k51421
Akzeptiert-Rate: 39%

bearbeitet 01 Mär '14, 15:39

Vielen Dank für die Antwort, das hilft mir auf jeden Fall weiter.

(27 Feb '14, 19:12) funkytex

In \backgroundpath sollte man nicht vorschreiben, was mit diesem Pfad passiert, d.h. ob er gezeichnet, gefüllt oder zum Beispiel auch weggelassen wird. Das übernehmen dann die Optionen beim Zeichnen des Shapes. Will man bestimmte Dinge immer ausführen lassen, dann muss man einen der anderen Befehle wie \behindbackgroundpath oder \beforebackgroundpath verwenden. Infos zu diesen Befehlen findet man in der Dokumentation zu pgf.

Hier ist mal Beispiel, bei dem der Hintergrund des Textes immer schwarz sein soll, der Abstand zwischen Textbox und Rand (also der inner sep) dagegen entsprechend den Vorgaben für fill gefüllt werden soll.

Open in writeLaTeX
\documentclass[margin=5mm]{standalone}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{myrec}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
   %... and possibly more
  \backgroundpath{%
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}
    \advance \pgf@xa by \pgf@xc
    \advance \pgf@ya by \pgf@yc
    \advance \pgf@xb by -\pgf@xc
    \advance \pgf@yb by -\pgf@yc
    \pgfmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
    \pgflineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfclosepath
  }
  \beforebackgroundpath{
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}
    \advance \pgf@xc by \pgfkeysvalueof{/pgf/inner xsep}
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}
    \advance \pgf@yc by \pgfkeysvalueof{/pgf/inner ysep}
    \advance \pgf@xa by \pgf@xc
    \advance \pgf@ya by \pgf@yc
    \advance \pgf@xb by -\pgf@xc
    \advance \pgf@yb by -\pgf@yc
    \pgfsetfillcolor{black}
    \pgfmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
    \pgflineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfclosepath
    \pgfusepath{fill}
  }
}

\tikzset{
  shape example/.style={
    text=green,
    draw=blue!50,
    fill=yellow!30,
    line width=.1cm,
    minimum size=5cm,
    inner sep=0.3cm
  }
}

\begin{document}
\begin{tikzpicture}
  \node[shape example, myrec, name=s] at (0,0){\Huge Text};
\end{tikzpicture}
\end{document}

alt text

In \beforebackgroundpath lässt sich natürlich auch ein Shading vorgeben:

Open in writeLaTeX
\documentclass[margin=5mm]{standalone}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{myrec}{
  \inheritsavedanchors[from=rectangle]
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
   %... and possibly more
  \backgroundpath{%
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}
    \advance \pgf@xa by \pgf@xc
    \advance \pgf@ya by \pgf@yc
    \advance \pgf@xb by -\pgf@xc
    \advance \pgf@yb by -\pgf@yc
    \pgfmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
    \pgflineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfclosepath
  }
  \beforebackgroundpath{
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}
    \advance \pgf@xc by \pgfkeysvalueof{/pgf/inner xsep}
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}
    \advance \pgf@yc by \pgfkeysvalueof{/pgf/inner ysep}
    \advance \pgf@xa by \pgf@xc
    \advance \pgf@ya by \pgf@yc
    \advance \pgf@xb by -\pgf@xc
    \advance \pgf@yb by -\pgf@yc
    \pgfmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
    \pgflineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
    \pgflineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
    \pgfclosepath
    \pgfdeclarehorizontalshading{myshad}{100bp}
      {color(0cm)=(black!48); color(100bp)=(black)}
    \pgfshadepath{myshad}{20}
  }
}

\tikzset{
  shape example/.style={
    text=green,
    %draw=blue!50,
    fill=blue!20!gray!40,
    line width=.1cm,
    minimum width=8cm,
    minimum height=4.5cm,
    inner sep=0.3cm
  }
}

\begin{document}
\begin{tikzpicture}
  \node[shape example, myrec, name=s] at (0,0){\Huge Text};
\end{tikzpicture}
\end{document}

alt text

Permanenter link

beantwortet 28 Feb '14, 09:53

esdd's gravatar image

esdd
17.7k254256
Akzeptiert-Rate: 62%

Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×728
×27

gestellte Frage: 26 Feb '14, 16:42

Frage wurde gesehen: 12,837 Mal

zuletzt geändert: 01 Mär '14, 15:39