使用chemfig
课堂beamer
教学时,我需要用不同的颜色显示双键的两个“单键”。应该可以针对不同幻灯片上的给定双键以及同一分子中的不同双键更改这些颜色。
\documentclass{beamer}
\usepackage{chemfig}
\begin{document}
\begin{frame}<1-4>{}
\alt<1>{\def\blue{white}}{\def\blue{blue}}
\alt<1-2>{\def\red{white}}{\def\red{red}}
\alt<1-3>{\def\green{white}}{\def\green{green}}
\chemfig[][scale=0.65]{OH-[::150](=[::-60]O)-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]=^[::60](-[::60,,,,\red]-[::-60,,,,\red]=^[::60,,,,\red](-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green])-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red])-[::-60]=^[::60](-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue])-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]}
\end{frame}
\end{document}
我需要(从右侧开始)第一个黑色双键的下部为红色,第二个黑色双键的下部为蓝色,红色双键的右侧为绿色。但在某些幻灯片上,我需要其中一些(双键的一半)为白色(或更好的是透明 - 完全不可见),以及从它们开始的分子分支。
有人知道提示吗?
非常感谢
托马斯
答案1
这个功能在 chemfig 中不是硬编码的,但是通过修饰,它变得容易:
\documentclass{article}
\usepackage{chemfig}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{clrdbl/.style args={#1 and #2}{%
draw=none,%
decoration={%
markings,%
mark=at position 0 with {\coordinate (CFstart@) at (0,0);},
mark=at position 1 with {%
\draw[color=#1]([yshift=\CF@double@sep/2]CFstart@)--(0,\CF@double@sep/2);
\draw[color=#2]([yshift=-\CF@double@sep/2]CFstart@)--(0,-\CF@double@sep/2);
}
},
postaction={decorate}
}
}
\makeatother
\begin{document}
\chemfig{A=B-[,,,,clrdbl=red and blue]C-[,,,,clrdbl=green and purple]D}
\end{document}
编辑:这是任意键的另一种解决方案。它不会在 chemfig 代码中重新定义任何内容:
\documentclass{article}
\usepackage{chemfig}
\makeatletter
\tikzset{clrdbl/.code 2 args={\tikzset{color=#1}\global\CF@add@tocs\CF@current@bondstyle{,color=#2}}}
\makeatother
\begin{document}
\chemfig{A-[:-30]=^[:30,,,,clrdbl={red}{blue}]-[:-30]=^[:30,,,,clrdbl={green}{purple}]-[:-30]=^[:30]D}
\end{document}
答案2
好的,我找到了一个适合我的解决方案。它似乎适用于正常双键(=
)、移位双键(=^
和=_
)甚至三键。
- 首先,我们必须重新定义
chemfig
包的三个宏。- 我们将它们(从
chemfig.tex
)复制到一个文件中,我们称之为bondsredef.tex
,它应该在命令或之后但在命令或之前的\input
某个时间点,如果您使用它们的话。\usepackage{chemfig}
\enablebondjoin
\disablebondjoin
- 原来,宏是使用命令来定义的,
\CF@def
但是命令拒绝多次定义一个宏,所以我们需要使用简单的宏\def
来定义。 - 为了更容易定位,下面的代码中只显示宏
\CF@draw@bond
和的重新定义,只是描述。\CF@draw@axisbond@nojoin
\CF@draw@axisbond@join
- 重新定义时会发生什么?在这三个宏中,都使用了宏
\CF@draw@bond@i
(直接或间接),它使用 TiKZ 来绘制键。我们告诉它的所有实例使用样式left single bond
、right single bond
或axis single bond
。为了实现这一点,我们- 通过
\CF@draw@bond
替换或通过修改定义\CF@draw@bond@i
\CF@draw@bond@i[left single bond]
\CF@draw@bond@i[right single bond]
如代码所示。这解决了左侧的颜色变化和正常双键(和三键)的右侧部分,以及左侧部分或者双键的右侧部分(非轴部分)偏移了=^
或=_
。 - 修改
\CF@draw@axisbond@nojoin
和\CF@draw@axisbond@join
定义只需\CF@draw@bond@i
用以下方式替换所有实例\CF@draw@bond@i[axis single bond]
这解决了移位双键轴向部分的颜色变化,以及三键中间“单键”(如果您愿意,也可以解决真正的单键)的颜色变化。 - 定义样式
left single bond
,right single bond
并axis single bond
在文件的第一行将bondsredef.tex
其定义为空样式。
- 通过
- 如上所述输入文件。如果使用命令
\enablebondjoin
或\disablebondjoin
,则必须在输入文件之后执行,因为它们通过 来将\CF@draw@axisbond
宏映射到\CF@draw@axisbond@nojoin
或。如果在重新定义之后没有执行此操作,仍将映射到 中定义的原始宏。\CF@draw@axisbond@join
\let
\CF@draw@axisbond
chemfig.tex
- 我们将它们(从
- 其次,对于要更改的双键和三键,我们在文档中键的第五个可选参数中定义相应的样式。在 中
beamer
,要更改帧的不同幻灯片之间的颜色,我们使用宏\red
(或任何名称)而不是颜色名称(例如)red
。这些宏是使用根据覆盖规范定义颜色的beamer
宏定义的。\alt
现在,代码。首先,bondsredef.tex
:
\tikzset{left single bond/.style={}}\tikzset{right single bond/.style={}}\tikzset{axis single bond/.style={}}
\makeatletter
\def\CF@draw@bond#1#2#3#4#5{% #1=type de liaison #2 et #3:nom de noeuds de d\'ebut et fin #4 et #5: contenu des atomes de d\'ebut et fin
\CF@set@offset\CF@start@offset#4%
\CF@set@offset\CF@end@offset#5%
\let\CF@current@bondstyle\CF@bond@style
\unless\ifx\CF@current@tikz\@empty\CF@expadd@tocs\CF@current@bondstyle{\expandafter,\CF@current@tikz}\fi
\path(#2)--(#3)coordinate[pos=0](#2@)coordinate[pos=1](#3@);%
\CF@compute@nodevect{#2@}{#3@}%
\pgfmathparse{\CF@start@offset/\CF@len@vector}\let\CF@start@coeff\pgfmathresult
\pgfmathparse{1-\CF@end@offset/\CF@len@vector}\let\CF@end@coeff\pgfmathresult
\path(#2@)--(#3@)coordinate[pos=\CF@start@coeff](#2@@)coordinate[pos=\CF@end@coeff](#3@@);%
\unless\ifx\CF@movebond@name\@empty% on doit poser un noeud sur la liaison
\path(#2@@)--(#3@@)coordinate[overlay,pos=\CF@movebond@coeff](\CF@movebond@name);
\let\CF@movebond@name\@empty
\fi
\ifcase#1\relax
\errmessage{Package \CF@package@name\space Error: unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}%
\or% 1 = liaison simple
\CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe
\or% 2 = liaison double
\ifCF@incycle
\ifnum\CF@doublebond@type=\z@
\let\CF@doublebond@type\@ne
\fi
\ifnum\CF@split@state>\z@
\let\CF@doublebond@type\tw@
\fi
\pgfmathparse{\CF@double@sep*tan(180/\CF@cycle@num)}%
\let\CF@doublebond@lengthcorrection\pgfmathresult
\fi
\ifcase\CF@doublebond@type
\CF@create@normnodes{#2@@}{#3@@}{\CF@double@sep/2}{\CF@double@sep/2}%
\CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
\CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
\let\CF@joinbond\z@
\or
\CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
\CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
\begingroup% ajuste \'eventuellement les longueurs des liaisons doubles
\ifCF@incycle
\ifdim\CF@start@offset=\z@
\CF@edefadd@tocs\CF@current@bondstyle{,shorten <=\CF@doublebond@lengthcorrection pt}%
\fi
\ifdim\CF@end@offset=\z@
\CF@edefadd@tocs\CF@current@bondstyle{,shorten >=\CF@doublebond@lengthcorrection pt}%
\fi
\fi
\CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
\endgroup
\or
\CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
\CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
\begingroup% ajuste \'eventuellement les longueurs des liaisons doubles
\ifCF@incycle
\ifdim\CF@start@offset=\z@
\CF@edefadd@tocs\CF@current@bondstyle{,shorten \ifnum\CF@split@state=\z@<=-\else>=\fi\CF@doublebond@lengthcorrection pt}%
\fi
\ifdim\CF@end@offset=\z@
\CF@edefadd@tocs\CF@current@bondstyle{,shorten \ifnum\CF@split@state=\z@>=-\else<=\fi\CF@doublebond@lengthcorrection pt}%
\fi
\fi
\CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
\endgroup
\fi
\or% 3 = liaison triple
\CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
\CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
\CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
\CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
\or% 4 = liaison Cram pleine de #2 vers #3
\CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
\expandafter\filldraw\expandafter[\CF@current@bondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
\let\CF@joinbond\z@
\or% 5 = liaison Cram creuse de #3 vers #2
\CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
\expandafter\filldraw\expandafter[\CF@current@bondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
\let\CF@joinbond\z@
\or% 6 = liaison Cram pointill\'ee de #2 vers #3
\scope
\CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
\clip(#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
\expandafter\draw\expandafter[\CF@current@bondstyle,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#2@@)--(#3@@);
\endscope
\let\CF@joinbond\z@
\or% 7 = liaison Cram pointill\'ee de #3 vers #2
\scope
\CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
\clip(#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
\expandafter\draw\expandafter[\CF@current@bondstyle,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#3@@)--(#2@@);
\endscope
\let\CF@joinbond\z@
\or% 8 = liaison Cram triangle \'evid\'e de #2 vers #3
\CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
\expandafter\draw\expandafter[\CF@current@bondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
\let\CF@joinbond\z@
\or% 9 = liaison Cram triangle \'evid\'e de #3 vers #1
\CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
\expandafter\draw\expandafter[\CF@current@bondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
\let\CF@joinbond\z@
\else
\errmessage{Package \CF@package@name\space Error: unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}%
\fi
\let\CF@start@offset\@empty
\let\CF@end@offset\@empty
\let\CF@previous@tikz\CF@current@tikz
\let\CF@previous@bondangle\CF@previous@angle
\def\CF@previous@bond{#1}%
}
%===============================================
\def\CF@draw@axisbond@nojoin#1#2{\CF@draw@bond@i[axis single bond](#1@@)--(#2@@);}
\def\CF@draw@axisbond@join#1#2{%
...
very long definition that I do not copy
...
}
现在,该文件:
\documentclass{beamer}
\usepackage{chemfig}
\input{bondsredef}
\begin{document}
\begin{frame}<1-4>{}
\alt<1>{\def\blue{white}}{\def\blue{blue}}
\alt<1-2>{\def\red{white}}{\def\red{red}}
\alt<1-3>{\def\green{white}}{\def\green{green}}
\chemfig[][scale=0.65]{OH-[::150](=[::-60]O)-[::60]~[::-60,,,,left single bond/.style={blue},axis single bond/.style={red},right single bond/.style={green}]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]=^[::60,,,,left single bond/.style={\red}](-[::60,,,,\red]-[::-60,,,,\red]=^[::60,,,,\red,left single bond/.style={\green}](-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green])-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red])-[::-60]=^[::60,,,,left single bond/.style={\blue}](-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue])-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]}
\end{frame}
\end{document}