1"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6935],{75216:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>a});var t=s(85893),o=s(11151);const i={sidebar_position:2},c="Complex Animations",l={id:"tutorials/dynamic/complex",title:"Complex Animations",description:"Thanks to the syntax provided by Polylux, we can also use only, uncover, and alternatives in Touying.",source:"@site/docs/tutorials/dynamic/complex.md",sourceDirName:"tutorials/dynamic",slug:"/tutorials/dynamic/complex",permalink:"/docs/tutorials/dynamic/complex",draft:!1,unlisted:!1,editUrl:"https://github.com/touying-typ/touying/tree/main/docs/en/tutorials/dynamic/complex.md",tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Simple Animations",permalink:"/docs/tutorials/dynamic/simple"},next:{title:"Math Equation Animations",permalink:"/docs/tutorials/dynamic/equation"}},r={},a=[{value:"Mark-Style Functions",id:"mark-style-functions",level:2},{value:"Callback-Style Functions",id:"callback-style-functions",level:2},{value:"only",id:"only",level:2},{value:"uncover",id:"uncover",level:2},{value:"alternatives",id:"alternatives",level:2}];function d(e){const n={a:"a",admonition:"admonition",br:"br",code:"code",h1:"h1",h2:"h2",img:"img",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"complex-animations",children:"Complex Animations"}),"\n",(0,t.jsxs)(n.p,{children:["Thanks to the syntax provided by ",(0,t.jsx)(n.a,{href:"https://polylux.dev/book/dynamic/syntax.html",children:"Polylux"}),", we can also use ",(0,t.jsx)(n.code,{children:"only"}),", ",(0,t.jsx)(n.code,{children:"uncover"}),", and ",(0,t.jsx)(n.code,{children:"alternatives"})," in Touying."]}),"\n",(0,t.jsx)(n.h2,{id:"mark-style-functions",children:"Mark-Style Functions"}),"\n",(0,t.jsx)(n.p,{children:"We can use mark-style functions, which are very convenient to use."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typst",children:'At subslide #touying-fn-wrapper((self: none) => str(self.subslide)), we can\n\nuse #uncover("2-")[`#uncover` function] for reserving space,\n\nuse #only("2-")[`#only` function] for not reserving space,\n\n#alternatives[call `#only` multiple times \\u{2717}][use `#alternatives` function #sym.checkmark] for choosing one of the alternatives.\n'})}),"\n",(0,t.jsx)(n.img,{alt:"Touying example output",src:s(56588).Z+"",width:"3440",height:"995"}),"\n",(0,t.jsxs)(n.p,{children:["However, this does not work in all cases, for example if you put ",(0,t.jsx)(n.code,{children:"uncover"})," into the context expression, you will get an error."]}),"\n",(0,t.jsx)(n.h2,{id:"callback-style-functions",children:"Callback-Style Functions"}),"\n",(0,t.jsxs)(n.p,{children:["To overcome the limitations of layout functions mentioned earlier, Touying cleverly implements always-effective ",(0,t.jsx)(n.code,{children:"only"}),", ",(0,t.jsx)(n.code,{children:"uncover"}),", and ",(0,t.jsx)(n.code,{children:"alternatives"})," using callback functions. Specifically, you need to introduce these three functions as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typst",children:'#slide(repeat: 3, self => [\n #let (uncover, only, alternatives) = utils.methods(self)\n\n At subslide #self.subslide, we can\n\n use #uncover("2-")[`#uncover` function] for reserving space,\n\n use #only("2-")[`#only` function] for not reserving space,\n\n #alternatives[call `#only` multiple times \\u{2717}][use `#alternatives` function #sym.checkmark] for choosing one of the alternatives.\n])\n'})}),"\n",(0,t.jsx)(n.img,{alt:"Touying example output",src:s(51093).Z+"",width:"3440",height:"1966"}),"\n",(0,t.jsxs)(n.p,{children:["Notice that we no longer pass a content block but instead pass a callback function with a ",(0,t.jsx)(n.code,{children:"self"})," parameter. Later, we extract ",(0,t.jsx)(n.code,{children:"only"}),", ",(0,t.jsx)(n.code,{children:"uncover"}),", and ",(0,t.jsx)(n.code,{children:"alternatives"})," functions from ",(0,t.jsx)(n.code,{children:"self"})," using:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typst",children:"#let (uncover, only, alternatives) = utils.methods(self)\n"})}),"\n",(0,t.jsx)(n.p,{children:"We then call these functions in subsequent steps."}),"\n",(0,t.jsxs)(n.p,{children:["Here's an interesting fact: the ",(0,t.jsx)(n.code,{children:"self.subslide"})," of type int indicates the current subslide index, and in fact, the ",(0,t.jsx)(n.code,{children:"only"}),", ",(0,t.jsx)(n.code,{children:"uncover"}),", and ",(0,t.jsx)(n.code,{children:"alternatives"})," functions rely on ",(0,t.jsx)(n.code,{children:"self.subslide"})," to determine the current subslide index."]}),"\n",(0,t.jsx)(n.admonition,{title:"Warning",type:"warning",children:(0,t.jsxs)(n.p,{children:["We manually specify the ",(0,t.jsx)(n.code,{children:"repeat: 3"})," parameter, indicating the display of 3 subslides. We need to do this manually because Touying cannot infer how many subslides ",(0,t.jsx)(n.code,{children:"only"}),", ",(0,t.jsx)(n.code,{children:"uncover"}),", and ",(0,t.jsx)(n.code,{children:"alternatives"})," should display when we use the bindings via utils."]})}),"\n",(0,t.jsx)(n.h2,{id:"only",children:"only"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"only"})," function means it \"appears\" only on selected subslides. If it doesn't appear, it completely disappears and doesn't occupy any space. In other words, ",(0,t.jsx)(n.code,{children:"#only(index, body)"})," is either ",(0,t.jsx)(n.code,{children:"body"})," or ",(0,t.jsx)(n.code,{children:"none"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["The index can be an int type or a str type like ",(0,t.jsx)(n.code,{children:'"2-"'})," or ",(0,t.jsx)(n.code,{children:'"2-3"'}),". For more usage, refer to ",(0,t.jsx)(n.a,{href:"https://polylux.dev/book/dynamic/complex.html",children:"Polylux"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["For more convenience we also support ",(0,t.jsx)(n.code,{children:"auto"}),", which uses the current subslide position when ",(0,t.jsx)(n.code,{children:"only"})," is encountered; ",(0,t.jsx)(n.code,{children:'"h"'})," which does the same, but is a string, and derivations of that: ",(0,t.jsx)(n.code,{children:'"h-"'})," and ",(0,t.jsx)(n.code,{children:'"-h"'}),".\nFurthermore we allow the use of the inversion via ",(0,t.jsx)(n.code,{children:'"!"'}),". Simply write ",(0,t.jsx)(n.code,{children:'"!h"'})," or ",(0,t.jsx)(n.code,{children:'"!2-4"'})," to get all but those subslides. Contrary to normal indices, the inversion does not increment subslide count."]}),"\n",(0,t.jsxs)(n.p,{children:["For how to use waypoints, please see the dedicated section on ",(0,t.jsx)(n.a,{href:"/docs/tutorials/dynamic/waypoints",children:"waypoints"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"uncover",children:"uncover"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"uncover"}),' function means it "displays" only on selected subslides; otherwise, it will be covered by the ',(0,t.jsx)(n.code,{children:"cover"})," function but still occupies the original space. In other words, ",(0,t.jsx)(n.code,{children:"#uncover(index, body)"})," is either ",(0,t.jsx)(n.code,{children:"body"})," or ",(0,t.jsx)(n.code,{children:"cover(body)"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["The index can be an int type or a str type like ",(0,t.jsx)(n.code,{children:'"2-"'})," or ",(0,t.jsx)(n.code,{children:'"2-3"'}),". For more usage, refer to ",(0,t.jsx)(n.a,{href:"https://polylux.dev/book/dynamic/complex.html",children:"Polylux"}),". ",(0,t.jsx)(n.br,{}),"\n","But you can also use the other options you saw for ",(0,t.jsx)(n.code,{children:"only"})," above."]}),"\n",(0,t.jsxs)(n.p,{children:["You may also have noticed that ",(0,t.jsx)(n.code,{children:"#pause"})," actually uses the ",(0,t.jsx)(n.code,{children:"cover"})," function, providing a more convenient syntax. In reality, their effects are almost identical."]}),"\n",(0,t.jsx)(n.h2,{id:"alternatives",children:"alternatives"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"alternatives"}
1)," function displays a series of different content in different subslides. For example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typst",children:"#slide(repeat: 3, self => [\n #let (uncover, only, alternatives) = utils.methods(self)\n\n #alternatives[Ann][Bob][Christopher]\n likes\n #alternatives[chocolate][strawberry][vanilla]\n ice cream.\n])\n"})}),"\n",(0,t.jsx)(n.img,{alt:"Touying example output",src:s(52865).Z+"",width:"3440",height:"1966"}),"\n",(0,t.jsxs)(n.p,{children:["As you can see, ",(0,t.jsx)(n.code,{children:"alternatives"})," can automatically expand to the most suitable width and height, a capability that ",(0,t.jsx)(n.code,{children:"only"})," and ",(0,t.jsx)(n.code,{children:"uncover"})," lack. In fact, ",(0,t.jsx)(n.code,{children:"alternatives"})," has other parameters, such as ",(0,t.jsx)(n.code,{children:"start: 2"}),", ",(0,t.jsx)(n.code,{children:"repeat-last: true"}),", and ",(0,t.jsx)(n.code,{children:"position: center + horizon"}),". For more usage, refer to ",(0,t.jsx)(n.a,{href:"https://polylux.dev/book/dynamic/alternatives.html",children:"Polylux"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},51093:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/62c056d3-44d9ce354c96f42706fcfbe3b31e1c8e.png"},52865:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/7f16e352-1160ed5a36b6c67f967785bce2c9a036.png"},56588:(e,n,s)=>{s.d(n,{Z:()=>t});const t=s.p+"assets/images/d30e4c67-41fbf9839684b2b22d27dfeb2ebd61bf.png"},11151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>c});var t=s(67294);const o={},i=t.createContext(o);function c(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.