Skip to content

Instantly share code, notes, and snippets.

@xziyue
Last active February 2, 2022 00:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xziyue/879009a25e96e2710afa9d54345573dc to your computer and use it in GitHub Desktop.
Save xziyue/879009a25e96e2710afa9d54345573dc to your computer and use it in GitHub Desktop.
% https://tex.stackexchange.com/questions/632271/chat-like-text-bock-in-tikz-environment
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{mathpazo}
\usepackage{tikz}
\usepackage{xcolor}
\usepackage{xparse}
\usepackage{calc}
\usepackage{varwidth}
\usetikzlibrary{positioning,calc}
\ExplSyntaxOn
\def\ChatBlockWidth{8cm}
\def\UserMinWidth{2cm}
\def\UserMaxWidth{6cm}
\def\NumberOfBubbles{8}
\def\SmallestBubbleDiameter{2pt}
\def\ChatInterval{0.3cm}
\def\BubbleScaleCoef{1.3}
\def\BubbleHeight{2cm}
\def\BubbleHShift{1.5cm}
\definecolor{user-1-color}{HTML}{CCF4C6}
\definecolor{user-2-color}{HTML}{FDE9A9}
\definecolor{user-frame-color}{HTML}{5D89B0}
\definecolor{face-eye-color-1}{HTML}{A3C39E}
\definecolor{face-eye-color-2}{HTML}{CABA87}
\newcommand{\ExtractCoordinate}[1]{\path (#1); \pgfgetlastxy{\XCoord}{\YCoord};}%
\tikzset{
chatnode/.style={
draw=user-frame-color,
rounded~corners=4pt,
inner~sep=6pt,
}
}
\tikzset{
pics/smiley-face/.style~n~args={3}{
code={
\begin{scope}[scale=#1]
\draw[draw=user-frame-color, fill=#2] (0,0) circle (1cm);
\draw[draw=user-frame-color, fill=#3] (-0.32,0.2) ellipse (0.08cm~and~0.15cm);
\draw[draw=user-frame-color, fill=#3] (0.32,0.2) ellipse (0.08cm~and~0.15cm);
\draw[draw=user-frame-color] (-0.6, -0.3) to[out=-60, in=-120] (0.6, -0.3);
\end{scope}
}
}
}
% template for bubbles
\cs_set:Npn \__chat_node_template:nnnnn #1#2#3#4#5 {
\exp_not:n {
node[
pos=#1,
fill=#3,
draw=user-frame-color,
circle,
inner~sep=0pt,
outer~sep=0pt,
minimum~width=#2,
xshift={#4},
yshift={#5}
]
{}
}
}
\cs_generate_variant:Nn \__chat_node_template:nnnnn {eennn}
\cs_set:Npn \__chat_pic_template:nnnnnn #1#2#3#4#5#6 {
\exp_not:n {
pic[
pos=#1,
xshift={#5},
yshift={#6}
]
{smiley-face={#2}{#3}{#4}}
}
}
\fp_new:N \l_chat_tmpa_fp
\fp_new:N \l_chat_tmpb_fp
\fp_new:N \l_chat_tmpc_fp
\fp_new:N \l_chat_tmpa_tl
% pos1, pos2, color, in, out, last scale, last x offset , last y offset, eye color
\newcommand{\ChatBubble}[9]{
\fp_set:Nn \l_chat_tmpa_fp {\dim_to_fp:n {\SmallestBubbleDiameter}}
\fp_set:Nn \l_chat_tmpb_fp {1/(\NumberOfBubbles-1)}
\tl_clear:N \l_chat_tmpa_tl
\tl_set:Nn \l_chat_tmpa_tl {\path (#1) to[in=#4,out=#5]}
\int_step_inline:nn {\NumberOfBubbles - 1} {
\tl_put_right:Nx \l_chat_tmpa_tl {
\__chat_node_template:eennn {\fp_eval:n {(##1 - 1) * \l_chat_tmpb_fp}}
{\fp_use:N \l_chat_tmpa_fp~pt}
{#3} {0pt} {0pt}
}
\fp_set:Nn \l_chat_tmpa_fp {\BubbleScaleCoef * \l_chat_tmpa_fp}
}
% the last bubble
\fp_set:Nn \l_chat_tmpa_fp {#6 * \l_chat_tmpa_fp}
% compute the relative scale for the face
\fp_set:Nn \l_chat_tmpc_fp {\l_chat_tmpa_fp~pt/(2cm)}
\tl_put_right:Nx \l_chat_tmpa_tl {
\__chat_pic_template:nnnnnn {1.0} {\fp_use:N \l_chat_tmpc_fp} {#3} {#9}
{#7} {#8}
}
\tl_put_right:Nn \l_chat_tmpa_tl {(#2);}
\tl_use:N \l_chat_tmpa_tl
}
\int_new:N \l_chat_box_index_int
\tl_new:N \l_chat_user_a_last_node_tl
\tl_new:N \l_chat_user_b_last_node_tl
\dim_new:N \l_chat_tmpa_dim
\dim_new:N \l_chat_tmpb_dim
\dim_new:N \l_chat_tmpc_dim
\dim_new:N \l_chat_tmpd_dim
\dim_new:N \l_chat_tmpe_dim
\dim_new:N \l_chat_last_vert_dim
\dim_new:N \l_chat_width_dim
\box_new:N \l_chat_tmpa_box
\newcommand{\GetLastVertPos}{
\tl_if_empty:NTF \l_chat_user_a_last_node_tl {
\dim_set:Nn \l_chat_tmpa_dim {-\ChatInterval}
} {
\ExtractCoordinate{\l_chat_user_a_last_node_tl.south}
%\GetSouthY{\l_chat_user_a_last_node_tl}
\dim_set:Nn \l_chat_tmpa_dim {\YCoord}
\iow_term:x {y~coord~is~\YCoord}
}
\tl_if_empty:NTF \l_chat_user_b_last_node_tl {
\dim_set:Nn \l_chat_tmpb_dim {-\ChatInterval}
} {
\ExtractCoordinate{\l_chat_user_b_last_node_tl.south}
\dim_set:Nn \l_chat_tmpb_dim {\YCoord}
}
\dim_compare:nNnTF \l_chat_tmpa_dim < \l_chat_tmpb_dim {
\dim_set_eq:NN \l_chat_last_vert_dim \l_chat_tmpa_dim
} {
\dim_set_eq:NN \l_chat_last_vert_dim \l_chat_tmpb_dim
}
}
\newcommand{\CalcChatWidth}[1]{
\hbox_set:Nn \l_chat_tmpa_box {\pgfinterruptpicture #1 \endpgfinterruptpicture}
\dim_compare:nNnTF {\box_wd:N \l_chat_tmpa_box} < {\UserMinWidth} {
\dim_set:Nn \l_chat_width_dim {\UserMinWidth}
} {
\dim_compare:nNnTF {\box_wd:N \l_chat_tmpa_box} < {\UserMaxWidth} {
\dim_set:Nn \l_chat_width_dim {
\dim_min:nn {\box_wd:N \l_chat_tmpa_box + 0.2cm} {\UserMaxWidth}
}
} {
\dim_set:Nn \l_chat_width_dim {\UserMaxWidth}
}
}
}
\NewDocumentEnvironment{ChatBox}{}{
\tl_clear:N \l_chat_user_a_last_node_tl
\tl_clear:N \l_chat_user_b_last_node_tl
\int_set:Nn \l_chat_box_index_int {1}
\newcommand{\UserA}[1]{
\GetLastVertPos
\CalcChatWidth{##1}
\node[chatnode, fill=user-1-color, anchor=north~west, text~width=\l_chat_width_dim]
(chat-\int_use:N \l_chat_box_index_int)
at ($(0pt, \dim_use:N \l_chat_last_vert_dim)-(0pt, \ChatInterval)$)
{##1};
\tl_set:Nx \l_chat_user_a_last_node_tl {chat-\int_use:N \l_chat_box_index_int}
\int_incr:N \l_chat_box_index_int
}
\newcommand{\UserB}[1]{
\GetLastVertPos
\CalcChatWidth{##1}
\node[chatnode, fill=user-2-color, anchor=north~east, text~width=\l_chat_width_dim]
(chat-\int_use:N \l_chat_box_index_int)
at ($(\ChatBlockWidth, \dim_use:N \l_chat_last_vert_dim)-(0, \ChatInterval)$)
{##1};
\tl_set:Nx \l_chat_user_b_last_node_tl {chat-\int_use:N \l_chat_box_index_int}
\int_incr:N \l_chat_box_index_int
}
\begin{tikzpicture}
}{
\ChatBubble{\l_chat_user_a_last_node_tl.south~west}
{$(\l_chat_user_a_last_node_tl.south~west)+(\BubbleHShift,-\BubbleHeight)$}
{user-1-color}{120}{-120}{2.0}{0.5cm}{0em}{face-eye-color-1}
\ChatBubble{\l_chat_user_b_last_node_tl.south~east}
{$(\l_chat_user_b_last_node_tl.south~east)+(-\BubbleHShift,-\BubbleHeight)$}
{user-2-color}{30}{-30}{2.0}{-0.5cm}{0em}{face-eye-color-2}
\end{tikzpicture}
}
\ExplSyntaxOff
\begin{document}
\begin{ChatBox}
\UserA{Hello, it's me!}
\UserA{I was wondering if after all these years you'd like to meet.}
\UserB{\emph{Hi...but who are you?}}
\UserA{S'up}
\UserA{dude?}
\UserB{\emph{Well nothing man...}}
\UserB{\emph{Who is it?}}
\UserA{Well, of course as usual brother.}
\end{ChatBox}
%
%This is the environment
%\begin{tikzpicture}
%\node[chatnode] {hello};
%%\ChatBubble{0,0}{1,-3}{user-1-color}{120}{-120}{2.0}{3em}{0em}
%\end{tikzpicture}
\end{document}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment