<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>flashcards &amp;mdash; Technikecke</title>
    <link>https://blog.anghenfil.de/technikecke/tag:flashcards</link>
    <description></description>
    <pubDate>Fri, 09 Oct 2026 04:20:28 +0000</pubDate>
    <item>
      <title>Anki: Bildverdeckung mit automatischem Scrollen</title>
      <link>https://blog.anghenfil.de/technikecke/anki-bildverdeckung-mit-automatischem-scrollen</link>
      <description>&lt;![CDATA[Wie viele andere Student\innen auch nutze ich die Open-Source Karteikartensoftware Anki, um effektiver auswendig zu lernen. Gerade für Gebiete wie Anatomie ist der Bildverdeckungs-Kartentyp sehr nützlich. &#xA;&#xA;Doch es gibt ein Problem: Bei großen Bildern wird alles extrem klein. Deshalb habe ich den Kartentyp so angepasst, dass hochformatige Bilder breiter (-  größer) anzeigt werden. Dadurch entsteht dann ein vertikaler Scrollbalken, doch durch eine weitere Anpassung wird die gerade aktive Bildverdeckung automatisch in die Mitte des Bildschirms gescrollt:&#xA;&#xA;Screenshot von Anki mit einer langen Bildverdeckungs-Karte zur Lactosesynthese, die aktive Bildverdeckung ist in der Bildschirmmitte.&#xA;&#xA;Selber Ausprobieren&#xA;&#xA;Probiert es doch gerne selber einmal aus! Entweder ihr ladet euch einfach dieses Stapelpaket mit dem Notiztypen herunter, oder ihr passt euren Bildverdeckungstyp selber an.&#xA;&#xA;via Stapelpaket&#xA;Ladet euch einfach dieses Stapelpaket herunter und öffnet es in Anki.&#xA;Nun müsst ihr euren bestehenden Bildverdeckungskarten den neuen Typ zuordnen: Öffnet die Kartenverwaltung&#xA;In der Kartenverwaltung wählt ihr links Notiztypen -  Bildverdeckung&#xA;Jetzt markiert ihr alle angezeigten Notizen (Strg + A), macht einen Rechtsklick -  Notiztyp ändern&#xA;Dort wählt ihr dann den gerade importierten Notiztypen, er müsste Bildverdeckung-[irgendwas] heißen. &#xA;&#xA;Manuell&#xA;Öffnet Anki&#xA;Ruft Extras -  Notiztypen verwalten auf&#xA;Wählt &#34;Bildverdeckung&#34; aus und geht auf &#34;Karten ...&#34;&#xA;Ersetzt den kompletten Code bei &#34;Vorlage für Vorderseite&#34; mit:&#xA;&#xA;{{#Kopfzeile}}div{{Kopfzeile}}/div{{/Kopfzeile}}&#xA;small{{Deck}}/small&#xA;div style=&#34;display: none&#34;{{cloze:Verdeckung}}/div&#xA;div id=&#34;err&#34;/div&#xA;div id=&#34;image-occlusion-container&#34;&#xA;    {{Bild}}&#xA;    canvas id=&#34;image-occlusion-canvas&#34;/canvas&#xA;/div&#xA;script&#xA;function scrollToActiveOcclusion() {&#xA;  const canvas = document.getElementById(&#39;image-occlusion-canvas&#39;);&#xA;  // Vorderseite: .cloze, Rückseite: .cloze-highlight&#xA;  const shapes = [...document.querySelectorAll(&#39;.cloze[data-shape], .cloze-highlight[data-shape]&#39;)];&#xA;  if (!canvas || !shapes.length) return;&#xA;&#xA;  const top = Math.min(...shapes.map(s =  +s.dataset.top));&#xA;  const bottom = Math.max(...shapes.map(s =  +s.dataset.top + +s.dataset.height));&#xA;  const center = (top + bottom) / 2;&#xA;&#xA;  const box = canvas.getBoundingClientRect();&#xA;  const y = box.top + window.scrollY + center  box.height;&#xA;&#xA;  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;&#xA;  const target = y - window.innerHeight / 2;&#xA;&#xA;  // Zentrieren lohnt sich nicht, wenn darunter kaum noch Platz ist -  ganz nach unten&#xA;  const toBottom = maxScroll - target &lt; window.innerHeight / 4;&#xA;  window.scrollTo({ top: toBottom ? maxScroll : Math.max(0, target) });&#xA;}&#xA;&#xA;try {&#xA;  const container = document.getElementById(&#39;image-occlusion-container&#39;);&#xA;  const img = container.querySelector(&#39;img&#39;);&#xA;&#xA;  const imgReady = img.complete&#xA;    ? Promise.resolve()&#xA;    : new Promise(resolve =  {&#xA;        img.addEventListener(&#39;load&#39;, resolve, { once: true });&#xA;        img.addEventListener(&#39;error&#39;, resolve, { once: true });&#xA;      });&#xA;&#xA;  imgReady.then(() =  {&#xA;    // 1. Klasse anhand der echten Bildmaße&#xA;    container.classList.toggle(&#39;tall&#39;, img.naturalHeight   img.naturalWidth);&#xA;&#xA;    anki.imageOcclusion.setup();&#xA;    &#xA;    setTimeout(function(){&#xA;    requestAnimationFrame(scrollToActiveOcclusion);&#xA;    }, 10);&#xA;  });&#xA;} catch (exc) {&#xA;  document.getElementById(&#34;err&#34;).innerHTML = Fehler beim Laden der Bildverdeckung. Ist Ihre Anki-Version aktuell?brbr${exc};&#xA;}&#xA;/script&#xA;&#xA;Ersetzt den kompletten Code bei &#34;Vorlage für Rückseite&#34; mit:&#xA;&#xA;{{#Kopfzeile}}div{{Kopfzeile}}/div{{/Kopfzeile}}&#xA;small{{Deck}}/small&#xA;div style=&#34;display: none&#34;{{cloze:Verdeckung}}/div&#xA;div id=&#34;err&#34;/div&#xA;div id=&#34;image-occlusion-container&#34;&#xA;    {{Bild}}&#xA;    canvas id=&#34;image-occlusion-canvas&#34;/canvas&#xA;/div&#xA;script&#xA;function scrollToActiveOcclusion() {&#xA;  const canvas = document.getElementById(&#39;image-occlusion-canvas&#39;);&#xA;  // Vorderseite: .cloze, Rückseite: .cloze-highlight&#xA;  const shapes = [...document.querySelectorAll(&#39;.cloze[data-shape], .cloze-highlight[data-shape]&#39;)];&#xA;  if (!canvas || !shapes.length) return;&#xA;&#xA;  const top = Math.min(...shapes.map(s =  +s.dataset.top));&#xA;  const bottom = Math.max(...shapes.map(s =  +s.dataset.top + +s.dataset.height));&#xA;  const center = (top + bottom) / 2;&#xA;&#xA;  const box = canvas.getBoundingClientRect();&#xA;  const y = box.top + window.scrollY + center * box.height;&#xA;&#xA;  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;&#xA;  const target = y - window.innerHeight / 2;&#xA;&#xA;  // Zentrieren lohnt sich nicht, wenn darunter kaum noch Platz ist -  ganz nach unten&#xA;  const toBottom = maxScroll - target &lt; window.innerHeight / 4;&#xA;  window.scrollTo({ top: toBottom ? maxScroll : Math.max(0, target) });&#xA;}&#xA;&#xA;try {&#xA;  const container = document.getElementById(&#39;image-occlusion-container&#39;);&#xA;  const img = container.querySelector(&#39;img&#39;);&#xA;&#xA;  const imgReady = img.complete&#xA;    ? Promise.resolve()&#xA;    : new Promise(resolve =  {&#xA;        img.addEventListener(&#39;load&#39;, resolve, { once: true });&#xA;        img.addEventListener(&#39;error&#39;, resolve, { once: true });&#xA;      });&#xA;&#xA;  imgReady.then(() =  {&#xA;    // 1. Klasse anhand der echten Bildmaße&#xA;    container.classList.toggle(&#39;tall&#39;, img.naturalHeight   img.naturalWidth);&#xA;&#xA;    anki.imageOcclusion.setup();&#xA;    &#xA;    setTimeout(function(){&#xA;    requestAnimationFrame(scrollToActiveOcclusion);&#xA;    }, 10);&#xA;  });&#xA;} catch (exc) {&#xA;  document.getElementById(&#34;err&#34;).innerHTML = Fehler beim Laden der Bildverdeckung. Ist Ihre Anki-Version aktuell?brbr${exc};&#xA;}&#xA;/script&#xA;&#xA;divbutton id=&#34;toggle&#34;Verdeckungen ein/aus/button/div&#xA;&#xA;Ersetzt den kompletten Code bei &#34;Stil&#34; mit:&#xA;&#xA;image-occlusion-canvas {&#xA;    --inactive-shape-color: #ffeba2;&#xA;    --active-shape-color: #ff8e8e;&#xA;    --inactive-shape-border: 1px #212121;&#xA;    --active-shape-border: 1px #212121;&#xA;}&#xA;&#xA;.card {&#xA;    font-family: arial;&#xA;    font-size: 20px;&#xA;    text-align: center;&#xA;    color: black;&#xA;    background-color: white;&#xA;    margin-bottom: 75px;&#xA;}&#xA;img{&#xA;max-height: none !important;&#xA;max-width: none !important;&#xA;width: 100%;&#xA;height: auto;&#xA;}&#xA;image-occlusion-container.tall{ &#xA;&#x9;&#x9;max-height: 150vh !important;&#xA;}&#xA;&#xA;Fragen oder Probleme? Schreibt mir an blog@anghenfil.de!&#xA;&#xA;#Anki #Flashcards #Karteikarten #Tipps #OpenSource]]&gt;</description>
      <content:encoded><![CDATA[<p>Wie viele andere Student*innen auch nutze ich die Open-Source Karteikartensoftware Anki, um effektiver auswendig zu lernen. Gerade für Gebiete wie Anatomie ist der Bildverdeckungs-Kartentyp sehr nützlich.</p>

<p>Doch es gibt ein Problem: Bei großen Bildern wird alles extrem klein. Deshalb habe ich den Kartentyp so angepasst, dass hochformatige Bilder breiter (–&gt; größer) anzeigt werden. Dadurch entsteht dann ein vertikaler Scrollbalken, doch durch eine weitere Anpassung wird die gerade aktive Bildverdeckung automatisch in die Mitte des Bildschirms gescrollt:</p>

<p><img src="https://cloud.anghenfil.de/public.php/dav/files/9TM7my9xSXBfWFr" alt="Screenshot von Anki mit einer langen Bildverdeckungs-Karte zur Lactosesynthese, die aktive Bildverdeckung ist in der Bildschirmmitte."></p>

<h2 id="selber-ausprobieren">Selber Ausprobieren</h2>

<p>Probiert es doch gerne selber einmal aus! Entweder ihr ladet euch einfach <a href="https://cloud.anghenfil.de/index.php/s/xtPfXmjZbx4dFoP/download" rel="nofollow">dieses</a> Stapelpaket mit dem Notiztypen herunter, oder ihr passt euren Bildverdeckungstyp selber an.</p>

<h3 id="via-stapelpaket">via Stapelpaket</h3>
<ol><li>Ladet euch einfach <a href="https://cloud.anghenfil.de/index.php/s/xtPfXmjZbx4dFoP/download" rel="nofollow">dieses</a> Stapelpaket herunter und öffnet es in Anki.</li>
<li>Nun müsst ihr euren bestehenden Bildverdeckungskarten den neuen Typ zuordnen: Öffnet die Kartenverwaltung</li>
<li>In der Kartenverwaltung wählt ihr links Notiztypen –&gt; Bildverdeckung</li>
<li>Jetzt markiert ihr alle angezeigten Notizen (Strg + A), macht einen Rechtsklick –&gt; Notiztyp ändern</li>
<li>Dort wählt ihr dann den gerade importierten Notiztypen, er müsste Bildverdeckung-[irgendwas] heißen.</li></ol>

<h3 id="manuell">Manuell</h3>
<ol><li>Öffnet Anki</li>
<li>Ruft Extras –&gt; Notiztypen verwalten auf</li>
<li>Wählt “Bildverdeckung” aus und geht auf “Karten ...”</li>
<li>Ersetzt den kompletten Code bei “Vorlage für Vorderseite” mit:</li></ol>

<pre><code class="language-html">{{#Kopfzeile}}&lt;div&gt;{{Kopfzeile}}&lt;/div&gt;{{/Kopfzeile}}
&lt;small&gt;{{Deck}}&lt;/small&gt;
&lt;div style=&#34;display: none&#34;&gt;{{cloze:Verdeckung}}&lt;/div&gt;
&lt;div id=&#34;err&#34;&gt;&lt;/div&gt;
&lt;div id=&#34;image-occlusion-container&#34;&gt;
    {{Bild}}
    &lt;canvas id=&#34;image-occlusion-canvas&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script&gt;
function scrollToActiveOcclusion() {
  const canvas = document.getElementById(&#39;image-occlusion-canvas&#39;);
  // Vorderseite: .cloze, Rückseite: .cloze-highlight
  const shapes = [...document.querySelectorAll(&#39;.cloze[data-shape], .cloze-highlight[data-shape]&#39;)];
  if (!canvas || !shapes.length) return;

  const top = Math.min(...shapes.map(s =&gt; +s.dataset.top));
  const bottom = Math.max(...shapes.map(s =&gt; +s.dataset.top + +s.dataset.height));
  const center = (top + bottom) / 2;

  const box = canvas.getBoundingClientRect();
  const y = box.top + window.scrollY + center * box.height;

  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
  const target = y - window.innerHeight / 2;

  // Zentrieren lohnt sich nicht, wenn darunter kaum noch Platz ist -&gt; ganz nach unten
  const toBottom = maxScroll - target &lt; window.innerHeight / 4;
  window.scrollTo({ top: toBottom ? maxScroll : Math.max(0, target) });
}

try {
  const container = document.getElementById(&#39;image-occlusion-container&#39;);
  const img = container.querySelector(&#39;img&#39;);

  const imgReady = img.complete
    ? Promise.resolve()
    : new Promise(resolve =&gt; {
        img.addEventListener(&#39;load&#39;, resolve, { once: true });
        img.addEventListener(&#39;error&#39;, resolve, { once: true });
      });

  imgReady.then(() =&gt; {
    // 1. Klasse anhand der echten Bildmaße
    container.classList.toggle(&#39;tall&#39;, img.naturalHeight &gt; img.naturalWidth);

    anki.imageOcclusion.setup();
    
    setTimeout(function(){
    requestAnimationFrame(scrollToActiveOcclusion);
    }, 10);
  });
} catch (exc) {
  document.getElementById(&#34;err&#34;).innerHTML = `Fehler beim Laden der Bildverdeckung. Ist Ihre Anki-Version aktuell?&lt;br&gt;&lt;br&gt;${exc}`;
}
&lt;/script&gt;
</code></pre>
<ol><li>Ersetzt den kompletten Code bei “Vorlage für Rückseite” mit:</li></ol>

<pre><code class="language-html">{{#Kopfzeile}}&lt;div&gt;{{Kopfzeile}}&lt;/div&gt;{{/Kopfzeile}}
&lt;small&gt;{{Deck}}&lt;/small&gt;
&lt;div style=&#34;display: none&#34;&gt;{{cloze:Verdeckung}}&lt;/div&gt;
&lt;div id=&#34;err&#34;&gt;&lt;/div&gt;
&lt;div id=&#34;image-occlusion-container&#34;&gt;
    {{Bild}}
    &lt;canvas id=&#34;image-occlusion-canvas&#34;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script&gt;
function scrollToActiveOcclusion() {
  const canvas = document.getElementById(&#39;image-occlusion-canvas&#39;);
  // Vorderseite: .cloze, Rückseite: .cloze-highlight
  const shapes = [...document.querySelectorAll(&#39;.cloze[data-shape], .cloze-highlight[data-shape]&#39;)];
  if (!canvas || !shapes.length) return;

  const top = Math.min(...shapes.map(s =&gt; +s.dataset.top));
  const bottom = Math.max(...shapes.map(s =&gt; +s.dataset.top + +s.dataset.height));
  const center = (top + bottom) / 2;

  const box = canvas.getBoundingClientRect();
  const y = box.top + window.scrollY + center * box.height;

  const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
  const target = y - window.innerHeight / 2;

  // Zentrieren lohnt sich nicht, wenn darunter kaum noch Platz ist -&gt; ganz nach unten
  const toBottom = maxScroll - target &lt; window.innerHeight / 4;
  window.scrollTo({ top: toBottom ? maxScroll : Math.max(0, target) });
}

try {
  const container = document.getElementById(&#39;image-occlusion-container&#39;);
  const img = container.querySelector(&#39;img&#39;);

  const imgReady = img.complete
    ? Promise.resolve()
    : new Promise(resolve =&gt; {
        img.addEventListener(&#39;load&#39;, resolve, { once: true });
        img.addEventListener(&#39;error&#39;, resolve, { once: true });
      });

  imgReady.then(() =&gt; {
    // 1. Klasse anhand der echten Bildmaße
    container.classList.toggle(&#39;tall&#39;, img.naturalHeight &gt; img.naturalWidth);

    anki.imageOcclusion.setup();
    
    setTimeout(function(){
    requestAnimationFrame(scrollToActiveOcclusion);
    }, 10);
  });
} catch (exc) {
  document.getElementById(&#34;err&#34;).innerHTML = `Fehler beim Laden der Bildverdeckung. Ist Ihre Anki-Version aktuell?&lt;br&gt;&lt;br&gt;${exc}`;
}
&lt;/script&gt;

&lt;div&gt;&lt;button id=&#34;toggle&#34;&gt;Verdeckungen ein/aus&lt;/button&gt;&lt;/div&gt;
</code></pre>
<ol><li>Ersetzt den kompletten Code bei “Stil” mit:</li></ol>

<pre><code class="language-css">#image-occlusion-canvas {
    --inactive-shape-color: #ffeba2;
    --active-shape-color: #ff8e8e;
    --inactive-shape-border: 1px #212121;
    --active-shape-border: 1px #212121;
}

.card {
    font-family: arial;
    font-size: 20px;
    text-align: center;
    color: black;
    background-color: white;
    margin-bottom: 75px;
}
img{
max-height: none !important;
max-width: none !important;
width: 100%;
height: auto;
}
#image-occlusion-container.tall{ 
		max-height: 150vh !important;
}
</code></pre>

<p>Fragen oder Probleme? Schreibt mir an <a href="mailto:blog@anghenfil.de" rel="nofollow">blog@anghenfil.de</a>!</p>

<p><a href="/technikecke/tag:Anki" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Anki</span></a> <a href="/technikecke/tag:Flashcards" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Flashcards</span></a> <a href="/technikecke/tag:Karteikarten" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Karteikarten</span></a> <a href="/technikecke/tag:Tipps" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Tipps</span></a> <a href="/technikecke/tag:OpenSource" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">OpenSource</span></a></p>
]]></content:encoded>
      <guid>https://blog.anghenfil.de/technikecke/anki-bildverdeckung-mit-automatischem-scrollen</guid>
      <pubDate>Thu, 01 Oct 2026 12:17:49 +0000</pubDate>
    </item>
  </channel>
</rss>