这和这答案提供了一个漂亮的代码来绘制钢琴及其音域。我尝试学习它们来绘制一个简单朴素的钢琴图,并在琴键上写上键名(A、B、C、C#),但代码中嵌套了太多其他要求,以至于我无法理解。有人能帮助我理解代码并从中得出一个简单的钢琴图吗?
代码 -
\documentclass[border=0.25cm]{standalone}
\usepackage{etex}
\usepackage{tikz}
\usepackage{musixtex}
\usetikzlibrary{fit}
\begin{document}
\begin{tikzpicture}
\def\lastnotename{origin}
\newbox\notebox
\coordinate (origin) at (0,0);
\coordinate (stave) at (origin);
\foreach \octave [evaluate={\t=int(\octave*7-7);}] in {0, ..., 5}{
\foreach \pitch [count=\c from 0, evaluate={\x=int(\octave*7+\c+1);}] in {A,...,G}{
\ifnum\t>6
\tikzset{extract anchor/.style={anchor=south west, at=(\lastnotename.south east)}}
\else
\tikzset{extract anchor/.style={anchor=north west, at=(\lastnotename.north east)}}
\fi
\edef\notename{\pitch-\octave}
\node (\notename) [inner sep=0pt, outer sep=0pt,text width=1cm, extract anchor/.try] {%
\begin{music}
\instrumentnumber{1}
\instrumentnumber{2}
\nostartrule
\setstaffs1{1}
\setstaffs2{1}
\ifnum\x>1
\setclefsymbol1{\empty}
\setclefsymbol2{\empty}
\fi
\setclef1{\bass}
\setclef2{\treble}
\startextract
\transpose\t
\ifnum\t>7
\ifnum\t>14
\Notes \nextinstrument \ql{\pitch} \en
\else
\Notes \nextinstrument \qu{\pitch} \en
\fi
\else
\Notes \qu{\pitch} \en
\fi
\zendextract
\end{music}};
\xdef\lastnotename{\pitch-\octave}
}}
\node (stave) [fit={(A-0) (G-5)}] {};
\newif\ifblacknote
\foreach \octave in {0,...,5}
\foreach \pitch [count=\p, evaluate={\t={"la", "si", "so", "r\`e","mi", "fa", "sol"}[\p-1];}] in {A,...,G}{
\node [anchor=base] at ([xshift=0.25cm, yshift=-0.25cm]stave.south -| \pitch-\octave.south) {\t};
\draw ([xshift=0.25cm, yshift=-1cm]stave.south -| \pitch-\octave.south west) rectangle ++(1cm,-4cm);
\blacknotefalse
\ifcase\p
\or
\blacknotetrue
\or
\or
\blacknotetrue
\or
\blacknotetrue
\or
\or
\blacknotetrue
\or
\ifnum\octave<5
\blacknotetrue
\fi
\else
\fi
\ifblacknote
\fill ([xshift=0.25cm, yshift=-1cm]stave.south -| \pitch-\octave.south east) ++(-0.25cm,0) rectangle ++(0.5cm,-2.5cm);
\fi
}
\end{tikzpicture}
\end{document}
答案1
如果我正确理解了这些要求,那么musictex
可以删除该部分。为了进一步简化,可以使用常规的双 for 循环计算 5 个八度和 7 个音高的键的坐标。可以使用计算出的 x 坐标将音高数组中的字母打印在键上,对于黑键,也可以使用类似的方法,在音高字母上添加一个升号。
剩下的就是对键和音高标签的位置进行一些调整。请注意,由于原始代码中的新键被绘制为矩形,因此矩形的左线将与前一个键的右线重叠。通常这不是问题,但是当音符名称以白色印在黑键上时,下一个白键将出现在音符名称的上方。为了解决这个问题,白键被绘制为三条线,只有顶部、右侧和底部。对于第一个键,在循环之前绘制了一条额外的左线。
梅威瑟:
\documentclass[border=0.25cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\coordinate (origin) at (0,0);
\coordinate (stave) at (origin);
% left line of first key
\draw (0.25,-1) -- (0.25,-5);
\newif\ifblacknote
\foreach \octave in {0,...,5}
\foreach \pitch [count=\p] in {A,...,G}{
% calculate x position from octave and pitch
\pgfmathparse{\octave*7+\p+0.25}
\edef\myx{\pgfmathresult}
% draw three lines for top, right, bottom of this key
\draw (\myx,-1) -- (\myx,-5);
\draw (\myx,-1) -- ($(\myx,-1)+(-1,0)$);
\draw (\myx,-5) -- ($(\myx,-5)+(-1,0)$);
% print pitch on line
\node [anchor=base,xshift=-15] at (\pgfmathresult,-4.5) {\pitch};
\blacknotefalse
\ifcase\p
\or
\blacknotetrue
\or
\or
\blacknotetrue
\or
\blacknotetrue
\or
\or
\blacknotetrue
\or
\ifnum\octave<5
\blacknotetrue
\fi
\else
\fi
\ifblacknote
% recalculate x
\pgfmathparse{\octave*7+\p}
\fill ([xshift=0.25cm, yshift=-1cm]stave.south -| \pgfmathresult,0) ++(-0.25cm,0) rectangle ++(0.5cm,-2.5cm);
% print pitch on black key
\node [anchor=base,xshift=0.25cm,white] at (\pgfmathresult,-2.5) {\textbf{\pitch}${}^\sharp$};
\fi
}
\end{tikzpicture}
\end{document}
结果(部分截图):
编辑:在黑键上添加降号。代码:
% recalculate x
\pgfmathparse{\octave*7+\p}
\edef\myx{\pgfmathresult}
% calculate flats
\pgfmathparse{array({"B","C","D","E","F","G","A"},\p-1)}
\edef\nextnote{\pgfmathresult}
\fill ([xshift=0.25cm, yshift=-1cm]stave.south -| \myx,0) ++(-0.25cm,0) rectangle ++(0.5cm,-2.5cm);
% print pitch on black key
\node [anchor=base,xshift=0.25cm,white] at (\myx,-2.5) {\textbf{\pitch}${}^\sharp$};
\node [anchor=base,xshift=0.25cm,white] at (\myx,-3.0) {\textbf{\nextnote}${}^\flat$};
编辑:一个八度,音符名称的不同字符。
\documentclass[border=0.5cm]{standalone}
\usepackage{fontspec}
\setmainfont[Script=Devanagari,Mapping=devanagarinumerals]{Shobhika}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{ulem}
\begin{document}
\begin{tikzpicture}
\coordinate (origin) at (0,0);
\coordinate (stave) at (origin);
% left line of first key
\draw (0.25,-1) -- (0.25,-5);
\newif\ifblacknote
\foreach \pitch [count=\p] in {सा,रे,ग,म,प,ध,नी}{
% calculate x position from octave and pitch
\pgfmathparse{\p+0.25}
\edef\myx{\pgfmathresult}
% draw three lines for top, right, bottom of this key
\draw (\myx,-1) -- (\myx,-5);
\draw (\myx,-1) -- ($(\myx,-1)+(-1,0)$);
\draw (\myx,-5) -- ($(\myx,-5)+(-1,0)$);
% print pitch on line
\node [anchor=base,xshift=-15] at (\pgfmathresult,-4.5) {\pitch};
\blacknotefalse
\ifcase\p
\or
\blacknotetrue
\or
\blacknotetrue
\or
\or
\blacknotetrue
\or
\blacknotetrue
\or
\blacknotetrue
\or
\else
\fi
\ifblacknote
\fill ([xshift=0.25cm, yshift=-1cm]stave.south -| \p,0) ++(-0.25cm,0) rectangle ++(0.5cm,-2.5cm);
% print pitch on black key
\pgfmathparse{array({"\underline{रे}","\underline{ग}",,"मऺ","\underline{ध}","\underline{नी}"},\p-1)}
\edef\nextnote{\pgfmathresult}
\node [anchor=base,xshift=0.25cm,white] at (\p,-2.5) {\nextnote};
\fi
}
\end{tikzpicture}
\end{document}
答案2
如果你仔细观察音乐键盘(钢琴、风琴、大键琴等),你可能会对所看到的东西感到惊讶:在任何一组七个相邻的自然(白色)键中,没有两个形状是相同的。确实,C 和 E 键互为镜像(F 和 B 键也是如此),但七个相邻的自然键之间都不能互换。事实上,这些键的尺寸和位置构成了一个有趣且非常实用(尽管可能出乎意料)的线性规划示例。网上有一些关于此问题的有用讨论:https://www.mathpages.com/home/kmath043.htm,http://www.quadibloc.com/other/cnv05.htm和 http://datagenetics.com/blog/may32016/index.html。
以下内容来自http://datagenetics.com/blog/may32016/index.html代码相当简单(感谢 Ti钾Z!——我最早的绘画是用铅笔和尺子在计算尺的帮助下完成的)这样可以相对轻松地进行编辑和实验。有无数其他方法可以实现这一点,但这种方法的优点是所有黑键都具有相同的宽度,所有白键(自然键)都具有相同的宽度——有些键盘布局不一定如此。
\documentclass[tikz,border=3mm]{standalone}
\usepackage{xparse}
\usetikzlibrary{calc}
\newlength{\CtoBwd}%% Width of 7 adjacent white (natural) keys
\newlength{\Whitewd}%% Width of a natural key
\newlength{\Blackwd}%% Width of a black key
\newlength{\Whitefrontht}%% Distance from front of white key to black key
\newlength{\Backwdi}%% <<-- See below
\newlength{\Backwdii}%% <<-- See below
\newlength{\Backwdiii}%% <<-- See below
\newlength{\FronttoBack}%% Total length of a natural key
\newlength{\Blackht}%% Length of a black key
%% http://datagenetics.com/blog/may32016/index.html
\NewDocumentCommand{\drawaccidental}{mmmm}{% Lower left, sharp name, flat name, coordinate name for upper right of accidental
\draw[fill=black] (#1)
rectangle node[white,text width=\Backwdii,align=center]
{\bfseries\huge#2${}^\sharp$\\[1ex]#3${}^\flat$}
++ (\Blackwd,\Blackht)coordinate (#4);
}
\NewDocumentCommand{\drawname}{m}{% Coordinate name of lower left of key and name of key
\node at ($(#1) + (\Whitewd/2,\Whitefrontht/2)$) {\bfseries\Huge#1};
}
%% f b = \Backwdi
%% cs ds fs gs as = \Backwdii
%% d g a = \Backwdii
%% c e = \Backwdiii
\NewDocumentCommand{\drawkeyboard}{}{%
\draw (0,0)coordinate(C) -- ++(0,\FronttoBack) -- ++(\Backwdiii,0) --
++(0,-\Blackht)coordinate(CS) -| (\Whitewd,0)coordinate(D) -- cycle;
\drawaccidental{CS}{C}{D}{CS0}
\drawname{C}
\draw (D) -- ++(0,\Whitefrontht) -| (CS0) -- ++(\Backwdii,0) -- ++(0,-\Blackht)coordinate(DS)
-| (2\Whitewd,0)coordinate(E) -- cycle;
\drawaccidental{DS}{D}{E}{DS0}
\drawname{D}
\draw (E) -- ++(0,\Whitefrontht) -| (DS0) -- ++(\Backwdiii,0) -- ++(0,-\FronttoBack)coordinate(F)
-- cycle;
\drawname {E}
\draw (F) -- ++(0,\FronttoBack) -- ++(\Backwdi,0) -- ++(0,-\Blackht)coordinate(FS)
-| (4\Whitewd,0)coordinate(G) -- cycle;
\drawaccidental{FS}{F}{G}{FS0}
\drawname{F}
\draw (G) -- ++(0,\Whitefrontht) -| (FS0) -- ++(\Backwdii,0) -- ++(0,-\Blackht)coordinate(GS)
-| (5\Whitewd,0)coordinate(A) -- cycle;
\drawaccidental{GS}{G}{A}{GS0}
\drawname{G}
\draw (A) -- ++(0,\Whitefrontht) -| (GS0) -- ++(\Backwdii,0) -- ++(0,-\Blackht)coordinate(AS)
-| (6\Whitewd,0)coordinate(B) -- cycle;
\drawaccidental{AS}{A}{B}{AS0}
\drawname{A}
\draw (B) -- ++(0,\Whitefrontht) -| (AS0) -- ++(\Backwdi,0) -- ++(0,-\FronttoBack) -- cycle;
\drawname{B}
}
\begin{document}
\setlength{\CtoBwd}{6.5in} %% This varies between 160mm to 167mm depending upon manufacturer
\pgfmathsetlengthmacro{\tmpwd}{\CtoBwd/5880}\typeout{\tmpwd!!!!}
\setlength{\Whitewd}{\dimexpr \tmpwd*840\relax}
\setlength{\Blackwd}{\dimexpr \tmpwd*490\relax}
\setlength{\Blackht}{3.75in}
\setlength{\Whitefrontht}{2in}
\setlength{\FronttoBack}{\dimexpr \Whitefrontht + \Blackht\relax}
\setlength{\Backwdi}{\dimexpr\tmpwd*455\relax}
\setlength{\Backwdii}{\dimexpr\tmpwd*490\relax}
\setlength{\Backwdiii}{\dimexpr\tmpwd*525\relax}
\begin{tikzpicture}[rounded corners=4pt]
\foreach \oct in {0,...,3}{% for 4 octaves; vary at will
\begin{scope}[xshift=\oct*\CtoBwd]
\drawkeyboard
\end{scope}
}
\end{tikzpicture}
\end{document}
我有许多使用其他布局的插图,最初是我准备帮助我的键盘学生的。