我正在尝试创建一个具有 3D 阴影效果的圆柱体。图片中的圆柱体垂直放置,有一个主体和一个末端。我希望主体被着色,以便它从圆柱体主体左侧的深色到中间的浅色(面向观察者)再到右侧的深色(浅色阴影效果)均匀变化。颜色在垂直方向上应保持不变。如果圆柱体末端也能如此那就太好了,但这并不那么重要。
我做了一些实验。下面的圆柱体 A 有一些阴影效果,但我不知道如何实现它。我甚至不知道将阴影用作节点的参数是否有意义,除非它显然在做一些事情。
圆柱体 B 与我想要的类似,除了阴影效果之外。
这是在 Debian squeeze 上使用 PGF 2.0 和 Tex Live 2009 进行测试的。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,decorations.fractals,shadows}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\begin{document}
\pagestyle{empty}
\begin{tikzpicture}
\tikzset{draw, name=s, shape=cylinder, line width=0.1cm, shape
border rotate=90, aspect=.2, inner xsep=3cm, inner ysep=2cm,
cylinder uses custom fill, cylinder end fill=blue!25, cylinder
body fill=blue!40};
\node [aspect=0.25, shade={left color=red!20,right color=blue!50}] at (1,0) {A};
\node[aspect=0.10] at (10,0) {B};
\end{tikzpicture}
\end{document}
答案1
为了创建独立圆柱体,而不使用预定义的 TikZ 形状,您可以执行以下操作:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\pagestyle{empty}
\begin{tikzpicture}
\coordinate (ll) at (-3,-2);
\coordinate (lr) at (3,-2);
\coordinate (ul) at (-3,2);
\coordinate (ur) at (3,2);
\shade [shading angle=90] (ll) arc (-180:-60:3cm and .75cm) -- +(0,4) arc (-60:-180:3cm and .75cm) -- cycle;
\shade [shading angle=270] (lr) arc (0:-60:3cm and .75cm) -- +(0,4) arc (-60:0:3cm and .75cm) -- cycle;
\draw [thick] (ll) arc (-180:0:3cm and .75cm) -- (ur) arc (0:-180:3cm and .75cm) -- cycle;
\draw [thick, shade, shading angle=30] (ul) arc (-180:180:3cm and .75cm);
\node at (0,-.75){\Huge A};
\end{tikzpicture}
\end{document}
答案2
您可以使用预定义的圆柱形状,然后绘制一个顶部有实心填充的椭圆。使用以下代码,您可以cylinder
像以前一样为形状提供所有选项,let
椭圆中的代码负责处理椭圆的位置、大小和旋转。您只需调整颜色。
let \p<number> = (<coordinate>) in ...
pgf 手册第 150 页(第 14.15 节)描述了该操作:它将由 描述的点分配(<coordinate>)
给局部变量\p<number>
,其中<number>
可以任意选择。变量\x<number>
和\y<number>
然后包含该点的 x 和 y 值。寄存器\n<number>
可用于存储数学运算的结果。
该构造在手册的第 135 页(第 13.5.5 节)中描述:它描述从到 的<coordinate>!<number>!<second coordinate>
线上的一点,其中 0 表示第一点,1 表示第二点,0.5 表示中间的一点。<first coordinate>
<second coordinate>
点(cyl.before top)
、(cyl.after top)
和(cyl.top)
由圆柱形状定义(参见 pgf 手册第 434 页第 48.3 节)。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}
\begin{document}
\begin{tikzpicture}
\node [draw,
shape=cylinder,
name=nodename, % Can be defined arbitrarily
alias=cyl, % Will be used by the ellipse to reference the cylinder
aspect=1.5,
minimum height=3cm,
minimum width=2cm,
left color=blue!30,
right color=blue!60,
middle color=red!20, % Has to be called after left color and middle color
outer sep=-0.5\pgflinewidth, % to make sure the ellipse does not draw over the lines
shape border rotate=90
] at (1,2) {A};
\fill [red!20] let
\p1 = ($(cyl.before top)!0.5!(cyl.after top)$),
\p2 = (cyl.top),
\p3 = (cyl.before top),
\n1={veclen(\x3-\x1,\y3-\y1)},
\n2={veclen(\x2-\x1,\y2-\y1)},
\n3={atan2((\y2-\y1),(\x2-\x1))}
in
(\p1) ellipse [x radius=\n1, y radius = \n2, rotate=\n3];
\end{tikzpicture}
\end{document}
PGF 2.0 版本
对于 PGF 2.0,代码需要稍微进行调整,因为atan2
旧版本中缺少数学函数并且椭圆的语法不同。
该操作let \p = () in ...
在 pgf 2.0 手册(“Let 操作”)第 127 页(第 13.14 节)中进行了描述。
该构造<coordinate>!<number>!<coordinate>
在 pgf 2.0 手册第 116 页第 12.4.3 节中进行了描述。
点 (cyl.before top)、(cyl.after top) 和 (cyl.top) 由圆柱形状定义(参见 pgf 2.0 手册第 326 页第 39.3 节(“几何形状”))。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,calc}
\begin{document}
\begin{tikzpicture}
\node [draw,
shape=cylinder,
name=nodename, % Can be defined arbitrarily
alias=cyl, % Will be used by the ellipse to reference the cylinder
aspect=1.5,
minimum height=3cm,
minimum width=2cm,
left color=blue!30,
right color=blue!60,
middle color=red!20, % Has to be called after left color and middle color
outer sep=-0.5\pgflinewidth, % to make sure the ellipse does not draw over the lines
shape border rotate=90
] at (1,2) {A};
\fill [red!20] let
\p1 = ($(cyl.before top)!0.5!(cyl.after top)$),
\p2 = (cyl.top),
\p3 = (cyl.before top),
\n1={veclen(\x3-\x1,\y3-\y1)},
\n2={veclen(\x2-\x1,\y2-\y1)}
in
(\p1) ellipse (\n1 and \n2);
\end{tikzpicture}
\end{document}
答案3
只是为了好玩。上面的答案很棒。然而,Jan 的回答没有创建节点。杰克的精彩回答分两步构造椭圆。这根本不是坏事,但有人可能想一次性构造它。这里有一个一步完成的方法。我没有想出结束的路径,而是从库中复制的。似乎可以shapes.geometric
(滥用)使用路径图片来“托管”一些可以在其他地方找到的 pgf 代码。我不知道这个网站之前是否提到过这一点,如果是的话,我很乐意给予适当的赞扬,我也不知道是否存在重大陷阱。我只做了非常有限的测试,所以请小心使用它。
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes.geometric}
\begin{document}
\tikzset{cylinder end fill/.style={path picture={
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{-270}{\xradius and \yradius}%
\pgfpathclose
\pgfsetfillcolor{#1}%
\pgfusepath{fill}}
}}
\begin{tikzpicture}
\pgfmathsetmacro{\myaspect}{pi/4}
\node [draw,
shape=cylinder,
aspect=\myaspect,
minimum height=3cm,
minimum width=2cm,
rotate=20,
cylinder end fill=blue,
left color=blue!30,
right color=black,
middle color=blue!80,
shading angle=20,
font=\sffamily,
text width=pi*1cm,
text=white] {Hello world, ducks, koalas and marmots!};
\end{tikzpicture}
\end{document}
旧答案:(不必要的复杂)在这个答案中,基于标准圆柱体声明了一个“新”形状。我没有对其进行广泛的测试,我只是为了学习一些新东西。我学到的新东西在答案的上半部分。
\documentclass{beamer}
\setbeamertemplate{navigation symbols}{}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\makeatletter
% Additional keys for shape "shaded cylinder"
%
% /pgf/cylinder body top shade : Custom shading color for the cylinderbody.
% /pgf/cylinder body middle shade: Custom shading color for the cylinderbody.
% /pgf/cylinder body bottom shade : Custom shading color for the cylinderbody.
%
\newif\ifpgfcylinderusescustomshade
\pgfkeys{/pgf/.cd,
cylinder uses custom shade/.is if=pgfcylinderusescustomshade,
cylinder end fill/.initial=white,
cylinder body top shade/.initial=white,
cylinder body middle shade/.initial=white,
cylinder body bottom shade/.initial=white,
cylinder body shade angle/.initial=0,
}
\pgfdeclareshape{shaded cylinder}{%
\savedmacro\getcylinderpoints{%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
\pgf@x\pgf@xc%
\advance\[email protected]\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
\pgf@y\pgf@yc%
\advance\[email protected]\ht\pgfnodeparttextbox%
\advance\[email protected]\dp\pgfnodeparttextbox%
\ifpgfshapeborderusesincircle%
\pgfmathsetmacro\rotate{\pgfkeysvalueof{/pgf/shape border rotate}}%
\ifdim\pgf@x<\pgf@y%
\pgf@x\pgf@y%
\else%
\pgf@y\pgf@x%
\fi%
\[email protected]\pgf@x%
\[email protected]\pgf@y%
\else%
\pgfmathmod{\pgfkeysvalueof{/pgf/shape border rotate}}{360}%
\ifdim\pgfmathresult pt<0pt\relax%
\pgfmathadd@{\pgfmathresult}{360}%
\fi%
\pgfmathsetcount\c@pgf@counta{+\pgfmathresult}%
\advance\c@pgf@counta45\relax%
\divide\c@pgf@counta90\relax%
\multiply\c@pgf@counta90\relax%
\edef\rotate{\the\c@pgf@counta}%
\ifnum\c@pgf@counta=90\relax%
\pgf@xa\pgf@x%
\pgf@x\pgf@y%
\pgf@y\pgf@xa%
\pgf@yc\pgf@xc%
\else%
\ifnum\c@pgf@counta=270\relax%
\pgf@xa\pgf@x%
\pgf@x\pgf@y%
\pgf@y\pgf@xa%
\pgf@yc\pgf@xc%
\fi%
\fi%
\fi%
\addtosavedmacro\rotate%
\pgf@xa\pgf@x%
\pgf@ya\pgf@y%
\pgfutil@tempdima\pgfshapeaspect\pgf@ya%
\pgfutil@tempdimb\pgf@ya%
%
% Adjust for minimum height.
%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgfutil@tempdimb<.5\pgf@xc\relax%
\[email protected]\pgf@xc%
\pgf@ya\pgfutil@tempdimb%
\fi%
%
% Calculate how far the node contents can extend into the cylinder bottom.
%
\pgf@yb\pgfutil@tempdimb%
\advance\pgf@yb-\pgf@yc%
\pgfmathdivide@{\pgfmath@tonumber{\pgf@yb}}{\pgfmath@tonumber{\pgfutil@tempdimb}}%
\pgfmathasin@{\pgfmathresult}%
\pgfmathcos@{\pgfmathresult}%
\let\angle\pgfmathresult%
\pgf@xb\pgfmathresult\pgfutil@tempdima%
%
% Adjust for minimum width.
%
\[email protected]\pgflinewidth%
\advance\[email protected]\pgf@xa%
\advance\[email protected]\pgfutil@tempdima%
\advance\pgf@x-\pgf@xb%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@x<\pgf@xc%
\advance\pgf@xc-\pgf@x%
\advance\[email protected]\pgf@xc%
\fi%
%
% Add the larger of the outer sep to the radii.
%
\pgf@x\pgfutil@tempdima\relax%
\pgf@y\pgfutil@tempdimb\relax%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}%
\ifdim\pgf@xc>\pgf@yc%
\advance\pgf@x\pgf@xc%
\advance\pgf@y\pgf@xc%
\edef\outersep{\the\pgf@xc}%
\else%
\advance\pgf@x\pgf@yc%
\advance\pgf@y\pgf@yc%
\edef\outersep{\the\pgf@yc}%
\fi%
\edef\xradius{\the\pgf@x}%
\edef\yradius{\the\pgf@y}%
\addtosavedmacro\xradius%
\addtosavedmacro\yradius%
\addtosavedmacro\outersep%
%
\pgfextract@process\cylindercenter{%
\pgf@x\pgfutil@tempdima%
\advance\[email protected]\pgflinewidth%
\advance\pgf@x\pgf@xb%
\[email protected]\pgf@x%
\pgf@y0pt%
}%
\addtosavedmacro\cylindercenter%
%
\pgfextract@process\beforetop{%
\pgf@x\pgf@xa%
\advance\pgf@x\pgfutil@tempdima%
\advance\[email protected]\pgflinewidth%
\pgf@y\pgf@ya%
}%
\pgfextract@process\afterbottom{%
\pgf@x-\pgf@xa%
\advance\pgf@x\pgf@xb%
\pgf@y\pgf@ya%
}%
\addtosavedmacro\beforetop%
\addtosavedmacro\afterbottom%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/outer ysep}}%
\pgfextract@process\beforetopanchor{%
\beforetop%
\advance\pgf@y\pgf@yc%
}%
\pgfextract@process\afterbottomanchor{%
\afterbottom%
\advance\pgf@y\pgf@yc%
}%
\addtosavedmacro\beforetopanchor%
\addtosavedmacro\afterbottomanchor%
%
\beforetopanchor%
\advance\pgf@x\xradius\relax%
\ifdim\pgf@x>\pgf@y%
\edef\externalradius{\the\pgf@x}%
\else%
\edef\externalradius{\the\pgf@y}%
\fi%
\addtosavedmacro\externalradius%
}
\savedanchor\centerpoint{%
\[email protected]\wd\pgfnodeparttextbox%
\[email protected]\ht\pgfnodeparttextbox%
\advance\[email protected]\dp\pgfnodeparttextbox%
}%
\savedanchor\midpoint{%
\[email protected]\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@y{+0.5ex}%
}%
\savedanchor\basepoint{%
\[email protected]\wd\pgfnodeparttextbox%
\pgf@y0pt%
}%
\anchor{center}{\centerpoint}
\anchor{shape center}{%
\getcylinderpoints%
\pgfmathrotatepointaround{\pgfpointadd{\cylindercenter}{\centerpoint}}%
{\centerpoint}{\rotate}%
}%
\anchor{mid}{\midpoint}%
\anchor{mid east}{%
\getcylinderpoints%
\let\pgf@cylinder@referencepoint\midpoint%
\pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
}%
\anchor{mid west}{%
\getcylinderpoints%
\let\pgf@cylinder@referencepoint\midpoint%
\pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
}%
\anchor{base}{\basepoint}%
\anchor{base east}{%
\getcylinderpoints%
\let\pgf@cylinder@referencepoint\basepoint%
\pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
}%
\anchor{base west}{%
\getcylinderpoints%
\let\pgf@cylinder@referencepoint\basepoint%
\pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
}%
\anchor{north}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{0pt}{\externalradius}}%
}%
\anchor{south}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{0pt}{-\externalradius}}%
}%
\anchor{east}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{0pt}}%
}%
\anchor{west}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{0pt}}%
}%
\anchor{north east}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{\externalradius}}%
}%
\anchor{south west}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{-\externalradius}}%
}%
\anchor{south east}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{\externalradius}{-\externalradius}}%
}%
\anchor{north west}{%
\getcylinderpoints%
\pgf@anchor@cylinder@border{\pgfqpoint{-\externalradius}{\externalradius}}%
}%
\anchor{before top}{%
\getcylinderpoints%
\pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor}{\centerpoint}}{\centerpoint}{\rotate}%
}
\anchor{top}{%
\getcylinderpoints%
\pgfmathrotatepointaround{%
\pgfpointadd{%
\beforetop%
\pgf@y0pt\relax%
\advance\pgf@x\xradius\relax%
}{\centerpoint}}{\centerpoint}{\rotate}%
}
\anchor{after top}{%
\getcylinderpoints%
\pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}{\centerpoint}{\rotate}%
}
\anchor{before bottom}{%
\getcylinderpoints%
\pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}{\centerpoint}{\rotate}%
}
\anchor{bottom}{%
\getcylinderpoints%
\pgfmathrotatepointaround{%
\pgfpointadd{%
\afterbottom%
\pgf@y0pt\relax%
\advance\pgf@x-\xradius\relax%
}{\centerpoint}}{\centerpoint}{\rotate}%
}
\anchor{after bottom}{%
\getcylinderpoints%
\pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor}{\centerpoint}}{\centerpoint}{\rotate}%
}
\backgroundpath{%
\getcylinderpoints%
{%
\pgf@x\xradius\relax%
\advance\pgf@x-\outersep\relax%
\edef\xradius{\the\pgf@x}%
\pgf@y\yradius\relax%
\advance\pgf@y-\outersep\relax%
\edef\yradius{\the\pgf@y}%
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
\pgfpathmoveto{\afterbottom}%
\pgfpatharc{90}{270}{\xradius and \yradius}%
\pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
\pgfpatharc{-90}{90}{\xradius and \yradius}%
\pgfpathclose%
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{270}{\xradius and \yradius}%
}%
}%
\behindbackgroundpath{%
\ifpgfcylinderusescustomfill%
\getcylinderpoints%
\pgf@x\xradius\relax%
\advance\pgf@x-\outersep\relax%
\edef\xradius{\the\pgf@x}%
\pgf@y\yradius\relax%
\advance\pgf@y-\outersep\relax%
\edef\yradius{\the\pgf@y}%
{%
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
\pgfpathmoveto{\afterbottom}%
\pgfpatharc{90}{270}{\xradius and \yradius}%
\pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
\pgfpatharc{270}{90}{\xradius and \yradius}%
\pgfpathclose%
\expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder body fill}}%
\pgfusepath{fill}%
%
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{-270}{\xradius and \yradius}%
\pgfpathclose
\expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder end fill}}%
\pgfusepath{fill}%
}%
\fi%
\ifpgfcylinderusescustomshade%
\getcylinderpoints%
\pgf@x\xradius\relax%
\advance\pgf@x-\outersep\relax%
\edef\xradius{\the\pgf@x}%
\pgf@y\yradius\relax%
\advance\pgf@y-\outersep\relax%
\edef\yradius{\the\pgf@y}%
{%
%
\expandafter\pgfdeclareverticalshading{cylindershade}{\yradius}
{color(0bp)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body top shade}});
color(0.5*\yradius)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body middle shade}});
color(\yradius)=(\expandafter{\pgfkeysvalueof{/pgf/cylinder body bottom shade}})}
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
\begin{pgfscope}%
\pgfpathmoveto{\afterbottom}%
\pgfpatharc{90}{270}{\xradius and \yradius}%
\pgfpathlineto{\beforetop\pgf@y-\pgf@y}%
\pgfpatharc{270}{90}{\xradius and \yradius}%
\pgfpathclose%
\typeout{\pgfkeysvalueof{/pgf/cylinder body shade angle}}
\expandafter\pgfshadepath{cylindershade}{\pgfkeysvalueof{/pgf/cylinder body shade angle}}%
\pgfsetfillcolor{white}%
\pgfsetfillopacity{0}%
\pgfusepath{fill}%
\end{pgfscope}
%
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{-270}{\xradius and \yradius}%
\pgfpathclose
\expandafter\pgfsetfillcolor\expandafter{\pgfkeysvalueof{/pgf/cylinder end fill}}%
\pgfusepath{fill}%
}%
\fi%
}%
\anchorborder{%
\pgfextract@process\externalpoint{}%
\getcylinderpoints%
\pgfutil@ifundefined{pgf@cylinder@referencepoint}{\let\referencepoint\centerpoint}{%
\let\referencepoint\pgf@cylinder@referencepoint}%
\pgfextract@process\externalpoint{%
\externalpoint%
\pgf@xa\pgf@x%
\pgf@ya\pgf@y%
\referencepoint%
\advance\pgf@x\pgf@xa%
\advance\pgf@y\pgf@ya%
}%
\pgfmathanglebetweenpoints{\centerpoint}{\externalpoint}%
\pgfmathsubtract@{\pgfmathresult}{\rotate}%
\ifdim\pgfmathresult pt<0pt\relax%
\pgfmathadd@{\pgfmathresult}{360}%
\fi%
\let\externalangle\pgfmathresult%
%
\pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\afterbottomanchor}{\centerpoint}}%
\ifdim\externalangle pt<\pgfmathresult pt\relax%
\pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\beforetopanchor}{\centerpoint}}%
\ifdim\externalangle pt<\pgfmathresult pt\relax%
\pgfmathrotatepointaround{%
\pgfmathpointintersectionoflineandarc%
{\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
{\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
{%
\beforetop%
\pgf@xa\pgf@x%
\centerpoint%
\advance\pgf@x\pgf@xa%
}%
{0}{90}{\xradius and \yradius}%
}{\centerpoint}{\rotate}%
\else%
\pgfpointintersectionoflines{%
\pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor}{\centerpoint}}%
{\centerpoint}{\rotate}}{%
\pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor}{\centerpoint}}%
{\centerpoint}{\rotate}}%
{\referencepoint}{\externalpoint}%
\fi%
\else%
\pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}%
\ifdim\externalangle pt>\pgfmathresult pt\relax%
\pgfmathanglebetweenpoints{\referencepoint}{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}%
\ifdim\externalangle pt>\pgfmathresult pt\relax%
\pgfmathrotatepointaround{%
\pgfmathpointintersectionoflineandarc%
{\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
{\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
{%
\beforetop%
\pgf@xa\pgf@x%
\centerpoint
\advance\pgf@x\pgf@xa%
}%
{270}{360}{\xradius and \yradius}%
}{\centerpoint}{\rotate}%
\else%
\pgfpointintersectionoflines{%
\pgfmathrotatepointaround{\pgfpointadd{\afterbottomanchor\pgf@y-\pgf@y}{\centerpoint}}%
{\centerpoint}{\rotate}}{%
\pgfmathrotatepointaround{\pgfpointadd{\beforetopanchor\pgf@y-\pgf@y}{\centerpoint}}%
{\centerpoint}{\rotate}}%
{\referencepoint}{\externalpoint}%
\fi%
\else%
\pgfmathrotatepointaround{%
\pgfmathpointintersectionoflineandarc%
{\pgfmathrotatepointaround{\externalpoint}{\centerpoint}{-\rotate}}%
{\pgfmathrotatepointaround{\referencepoint}{\centerpoint}{-\rotate}}%
{%
\afterbottom%
\pgf@xa\pgf@x%
\centerpoint
\advance\pgf@x\pgf@xa%
}%
{90}{270}{\xradius and \yradius}%
}{\centerpoint}{\rotate}%
\fi%
\fi%
}
}
\makeatother
\begin{document}
\begin{frame}[t]
\frametitle{}
\begin{tikzpicture}[scale=1., transform shape]
\node [rotate=30,shaded cylinder,draw,thick,aspect=2.,minimum height=5cm,
minimum width=4cm,shape border rotate=30,cylinder uses custom shade,
cylinder body top shade=black,
cylinder body middle shade=blue,
cylinder body bottom shade=blue!30,
cylinder body shade angle=30,
cylinder end fill=blue,text=white,font=\large
] at (0,0){Hello world, how are you doing!};
\end{tikzpicture}
\end{frame}
\end{document}