Archiv des Autors: admin

Darf ich vorstellen: Stichwort Plugin Teil 1, CSV-Datei erzeugen

Da ich die ganze Mechanik schon mal programmiert habe, in Access mit Visual Basic, hab ich mir relativ leicht getan es auch in PHP zu lösen. Was gar nicht schön war: bei komplexeren Datenbankoperationen ist mir x-mal der Webserver abgeraucht. Deswegen hab ich dann die Notbremse gezogen und bin auf eine CSV-Datei ausgewichen. Nicht die schlechteste Lösung, was Stabilität und Performance angeht.

Was hab ich gemacht? Ich geh da mal im Schnelldurchlauf durch, haben wir alles schon mal so oder in ähnlicher Form gehabt. Trotzdem, das eine oder andere ist vielleicht gut zu wissen.

Also,, zunächst wird ein Plugin mit einem Eintrag für das Admin-Menü erstellt. Dazu legt man eine Datei an, die folgendermassen aussieht:

/*
Plugin Name: Stichworttabelle
Description: Erzeugt eine neue Stichworttabelle aus den Titeln der Beiträge (post_title)
Author: Evi Leu
Version: 0.1
*/
    add_action('admin_menu', 'stichworttabelle_plugin_setup_menu');
	
	function stichworttabelle_plugin_setup_menu(){
    add_menu_page( 'Stichworttabelle', 'Stichworttabelle Plugin', 'manage_options', 'stichworttabelle', 'stichworttabelle_init' );
}
 
function stichworttabelle_init(){... HIER GEHTS MIT DER MAIN FUNCTION LOS

Diese Datei kommt in ein eigenes Unterverzeichnis „Stichworttabelle“ im Plugin-Verzeichnis deiner WP-Installation und heißt Stichworttabelle.php. Sie kann jetzt in der Liste der installierten Plugins aktiviert werden. Sie tut zunächst mal nichts ausser einen Eintrag im Admin-Menü zu erzeugen, der heißt „Stichworttabelle Plugin“ und ist erstmal noch eine leere Seite.

Die Menüseite wird in der Funktion function stichworttabelle_init() mit Leben gefüllt, erst kommt ein bisschen Infotex, dann wird der Name der Datenbank ermittelt und ausgegeben:

echo "<h1>Stichworttabelle neu erstellen</h1>";
	echo "Das Plugin hat zwei Funktionalitäten: </br></br>
	1. Diesen Admin-Menüpunkt Stichworttabelle Plugin, in dem die Stichworttabelle neu aufgebaut werden kann.</br>
	Aus Performancegründe und wegen der Runtime-Stabilität wurde die Stichwortbasis in eine externe CSV-Datei ausgelagert. Diese wird neu erstellt, falls sie nicht schon vorhanden ist. Falls sie schon vorhanden sein sollte, wird sie überschrieben. Man kann die Datei beliebig oft neu erzeugen, z.B. wenn es grössere Mengen neuer Beiträge gibt.</br></br>
	
	2. einen Shortcode [stichwortverzeichnis]. der an beliebiger Stelle in einem Beitrag oder einer Seite eingesetzt werden kann und dort ein Stichwortverzeichnis erzeugt.</br></br>";
	global $wpdb;
	
	//Datenbankname ermitteln
	$mydatabase=$wpdb->dbname;
	echo "Sie arbeiten auf der Datenbank: ".$mydatabase."</br>";
	echo "Stichworte werden aus den Titeln ihrer Beiträge erzeugt</br>";

Dann kommt ein kleines Formular, das aus genau einem Button besteht:

//***************Begin Formular
//Formular mit Button
//"
// Stichwortliste Datei neu erzeugen startet die array-Erzeugung fuellen und befüllt die Datei stichwortliste.csv wieder

echo "<form action = '#' method = 'post'>";
	
	echo "<input type='submit' id='el_button2' name='ButtonFuellen' value='Stichwortliste Datei neu erzeugen'>";
	echo "</form>";
	
	if (isset($_POST['ButtonFuellen'])){
			
			return tabelle_fuellen();
		}
//*****************End Formular

Wenn auf den Knopf gedrückt wird, wird die Funktion tabelle_fuellen aufgerufen. Jetzt wirds interessant:

function tabelle_fuellen(){
	
	$neuesArray=array_erzeugen();
	erzeuge_csv($neuesArray);
}

Die Variable $neuesArray wird mit Hilfe der Funktion array_erzeugen() befüllt. Diese erstellt eine Stichwortliste aus den Titeln aller Beiträge in der Tabelle wp_posts, dazu gleich mehr.

Dann wird die Funktion erzeuge_csv aufgerufen, sie kriegt als Parameter unser Array mit und schreibt die Einträge zeilenweise in eine Datei.

Frischauf, wir sehen uns die Funktion array_erzeugen() mal näher an. Der erste Teil mit den nötigen MySQL-Abfragen sieht so aus:

global $wpdb;

//Beginn Originalcode
$table_name = $wpdb->prefix.'posts';

	//Datensätze zählen & Ausgabe Anzahl
	$count_query = "select count(*) from $table_name where post_status='publish' and post_type = 'post'";
	$num = $wpdb->get_var($count_query);
	echo $num."&nbsp Beiträge gefunden</br>";
	
//******************

//Alle Datensätze vom Typ post und published ausgeben
$alleposts = $wpdb->get_results( "SELECT * FROM ".$table_name."
								where post_status='publish' and post_type = 'post' order by post_title");


Das übliche Spiel wenn man die veröffentlichten Beiträge ausgeben will, man braucht in der Where-Klausel die Bedingung post_status=’publish‘ and post_type = ‚post‘. Und zugegeben, man könnte statt select * auch select post_title verwenden, das fällt mir erst jetzt auf.

Jetzt stecken alle veröffentlichten Beiträge als Array in der Variablen $alleposts. Durch dieses Array steppe ich jetzt mit foreach durch und nehme mir die einzelnen Einträge vor, die werden mit Hilfe der Funktion explode() am Leerzeichen gesplittet, mit preg_replace() von Sonderzeichen bereinigt und mit ctype_upper auf Groß/Kleinschreibung überprüft, ich nehme nur die groß geschriebenen Einträge. Das ist willkürlich festgelegt, produziert aber eine sehr brauchbare Stichwortliste. Schließlich wird der gefundene Eintrag mit array_push() in die Variable $stichwortliste weggeschrieben.

$stichwortliste = array(); 
//Durch alle gefundenen Datensätze durchsteppen
$zaehler = 0;
foreach ( $alleposts as $einpost ) 
{ 
  //ersten gefundenen Titel in array aufsplitten
  $liste = explode(" ", $einpost->post_title);
  
  //Durch das Array durchsteppen
   foreach ($liste as $einwort)
  {
	  //Prüfen, ob Wort groß geschrieben ist
	  $wortanfang = substr($einwort,0,1);
	  
	  //Sonderzeichen entfernen (nach Bedarf editieren)
	  $einwort = preg_replace('/[0-9\@\.\;\" "\(\)\:\?\!\,]+/', '', $einwort);
	  
	  //nur ausgeben wenn Groß geschrieben
	  if (ctype_upper($wortanfang)){
		 
		  $zaehler = $zaehler+1;
		  
		  //Hier kommt der Knackpunkt: Neues Stichwort in Array schreiben
		  //***********************************
		  array_push($stichwortliste, $einwort);
		  //***********************************
	  }// ende von ctype_upper
  }// ende von liste as einwort

  
}//ende von alleposts as einpost und array befüllen

Es folgt noch ein bisschen Kosmetik, und ganz am Ende gibt unsere Funktion das gebrauchsfertige Array zurück:

//Dubletten entfernen
$stichwortliste= array_unique($stichwortliste);

//Array sortieren
sort($stichwortliste);

//Ausgabe Anzahlen erzeugter Stichwörter
echo "Anzahl Stichwörter in den Rohdaten: ".$zaehler."</br>";
echo "Grösse des sortierten und Dubletten-bereinigten Arrays: ".count($stichwortliste)."</br>";
echo "<h2>Erzeuge neue Stichwortliste aus der Tabelle: ".$table_name."</h2>";

return $stichwortliste;
}// ende array erzeugen_function

Noch alle mit mir beieinander? Fehlt noch was? Ach ja, die Erzeugung der CSV-Datei mit Hilfe der Funktion erzeuge_csv(), damit halte ich mich jetzt nicht lange auf, die ist einigermassen selbsterklärend:

function erzeuge_csv($liste){
	
	global $wpdb;
	
	echo "Ich erzeuge jetzt ein csv: ";
	
	//***************
	// Verzeichis des aktuellen Plugins ermitteln
	$dir = plugin_dir_path( __FILE__ );
	$aktVerzeichnis = $dir;
	//Dateiname fest verdrahtet	
	$fileName = $aktVerzeichnis.'stichwortliste.csv';
	echo $fileName."</br>";
	
if(file_exists($fileName)){
	echo "Die alte Datei wird überschrieben</br>";
	}
    
	//Gnadenlos überschreiben, der Parameter 'w' ersetzt den alten Dateiinhalt
	
    $csvFile = fopen($fileName,'w');
    $head = ["Wort"];
    fputcsv($csvFile,$head);

// Variable mit den Listeneinträgen befüllen
foreach ($liste as $einwort){
$data = [
    ["$einwort"],
    
];

//Durch alle data-Einträge durchsteppen und in Datei schreiben

foreach($data as $row){
    fputcsv($csvFile,$row);
}
}
fclose($csvFile);

 //Debug-Ausgabe aller Stichworte
$anzahl = sizeof($liste);
echo "<h2>Testausgabe: ".$anzahl." Stichwörter erzeugt</h2>";

foreach ($liste as $stichwort){
	
	echo $stichwort."</br>";
	
}
		
}// Ende function erzeuge csv
//*****************************************

Falls die Datei nicht existiert, wird sie neu angelegt. Falls sie schon existiert, wird der Inhalt überschrieben. So das wars. Jetzt einen Kaffee und sacken lassen. Und dann Hurra auf zu neuen Ufern, jetzt kommt der Teil mit dem Shortcode. Aber dazu gibts einen neuen Beitrag.

Da knarzt es im Gebälk: ich brauche einen PAP für mein Stichwortverzeichnis

Also, ich hab ja jetzt schon ein paar Tage Gehirnschmalz in das Stichwortverzeichnis investiert, und stelle fest dass die Sache schon hübsch komplex wird. Vor allem muss ich mir Gedanken machen, wer was wann macht (machen darf) und was wohin gehört. Ich mach mal ein Brainstorming:

  • es soll ein WordPress-Plugin (PHP) werden, ich möchte ohne Datenimport/Export in MYSQL arbeiten
  • Auf der WordPress-Adminseite soll es einen neuen Menüpunkt geben: „Stichworttabelle neu erstellen“ . Hier soll erst eine Sicherung der alten Stichworttabelle (falls vorhanden) angelegt werden, dann die Tabelle quelle erst geleert und dann mit der aktuell aus der Tabelle wp_posts (Feld wp_title) neu erstellten Stichwortliste neu befüllt werden.
  • Es soll ein Shortcode mitgeliefert werden [Stichwortverzeichnis], der an beliebiger Stelle auf einer Seite oder in einem Beitrag eingefügt werden kann und der da ein komplettes Stichwortverzeichnis (mit Unterseite) generiert.
  • Es soll eine Positiv- und Negativliste geben, für Wörter die auf jeden Fall/auf keinen Fall im Stichwortverzeichnis auftauchen sollen (nice to have)

Ich seh schon, ich muss mich erst mal wieder mit dem good old WordPress auseinandersetzen, das ist verdammt lang her dass ich was mit Plugins und Admin-Menüs gemacht habe. OK, ich geh mal googlen… bis dann!

Update am Montagmittag: nachdem mir der Webserver noch einige Male unter lautem Jubel abgerauscht ist, schmeisse ich den PAP nochmal über den Haufen. Anscheinend sind die vielen PHP-gesteuerten MySQL-Kommandos zuviel für das gute alte WordPress. Ich machs jetzt ganz anders, ich lege die Stichwörter in eine CSV-Datei. Die sollte man eigentlich gefahrlos wieder auslesen können – ich bin da recht vorsichtig geworden.

Update am Montagabend: Das mit dem CSV war der Schlüssel zum Erfolg, jetzt läuft die ganze Chose stabil. Die Erzeugung einer Stichwortdatei aus den Beitragstiteln der wp_posts läuft einwandfrei, und dauert nicht mal lang. Morgen bastel ich dann den Shortcode, der eben jene CSV-Datei wieder ausliest und das Stichwortverzeichnis an beliebiger Stelle in einem Beitrag oder auf einer Seite aufbaut. Mal sehen ob das ohne grössere Unfälle funkt. Hach, Programmieren ist so eine kurzweilige Sache! 😉

Stichwortverzeichnis: frisch gewagt in PHP und WordPress

Ich hab mich so über die unzuverlässige Asc()-Funktion in Access geärgert, jetzt hab ich mir die ganze Mechanik der Stichwort-Extraktion nochmal in PHP angetan, das funktioniert wesentlich zuverlässiger und erspart mir ausserdem den ständigen Datenimport/Export.

Praktisch gelöst wird die ganze Sache erst einmal über einen Shortcode, da musste ich jetzt schon nochmal überlegen wie das genau ging, ist lange her. Und wie ich so in $wpdb-Nostalgie schwelge, ist mir ein anderer Dreh eingefallen, wie ich die Stichwörterliste aus den Post-Titeln extrahieren kann, nämlich völlig dynamisch mithilfe von Arrays. Bei einigen Hundert Wörtern geht das noch sehr locker, da brauche ich mir wegen der Performance noch keine Gedanken zu machen…. dachte ich zuerst mal.

Nachdem mir aber ein paar mal hintereinander der lokale Webserver abgeraucht ist bei dem Versuch, eine dynamische Stichwortliste mit Links zu erzeugen, habe ich mich für eine Hybridlösung entschieden. Ich werde die Erzeugung der Quelldaten für das Stichwortverzeichnis doch über eine Tabelle abwickeln, das ist der erste Schritt. Dafür baue ich mir nach Erzeugung und Bereinigung des Arrays eine kleine MySQL-Abfrage, die die vorhandene Tabelle „quelle“ zuerst ausleert und dann neu befüllt. Das wäre natürlich nett, wenn man das über eine Art Benutzerführung abwickeln könnte, aber ich schau erstmal dass ich es überhaupt zum Laufen kriege. Dann kann ich meinen bereits vorhandenen Shortcode zur Erzeugung des Stichwortverzeichnisses aus der Tabelle quelle wiederverwenden, der ist nämlich schon fertig und funkt einwandfrei. Ich hab da so eine Idee, dass man die Datenbasis immer wieder mal neu erstellen können soll, wenn zum Beispiel viele Beiträge dazugekommen sind. Da es für die Erzeugung des Stichwortverzeichnisses aus einer statischen Tabelle keinerlei großartige PHP-Konstrukte braucht, sollte die Performance und Stabilität auch deutlich verbessert werden. Dann hab ich auch noch so eine Idee mit Positiv/Negativliste, mein Plugin könnte lernfähig werden, da gehts schon hübsch in Richtung AI. Morgen ist auch noch ein Tag…

Ein ehrgeiziges Projekt: Stichwortverzeichnis

Meine beiden mit Abstand am häufigsten gebrauchten Kochbücher sind „Das Bayrische Kochbuch“ und „Joy of Cooking“. Und bei beiden ist das am Meisten genutzte Feature das Stichwortverzeichnis, da findet man alles! Es eignet sich auch hervorragend zum kreuz- und querschmökern, man findet dabei Rezepte die man sonst nie gesehen hätte. Langer Rede kurzer Sinn, ein Stichwortverzeichnis (Volltext-Index) wäre ein schickes Feature für mein Inselfisch-Kochbuch. Und dazu möchte ich nicht das Stichwort-Feature von WordPress nutzen, das ist mir viel zu umständlich zu bedienen und zu schlecht auszuwerten.

Dazu waren einige Vorüberlegungen nötig. Zunächst muss ich mal festlegen, woher ich die Stichwörter nehme. Ich habe in meinem Inselfisch-Kochbuch knappe 400 Rezepte, in denen relevanter Text in zwei Feldern steht, einmal in post_title und einmal in post_content. Der Titel ist meist zwischen 5 und 10 Wörter lang, der Content kann wesentlich länger sein, bis zu einer ganzen DIN A 4 Seite und mehr, also auf jeden Fall mehr als 100 Wörter. Ich möchte meine Stichwortbasis natürlich maschinell erzeugen, dazu muss ich irgendwie einzelne Wörter aus meiner Datenbasis extrahieren. Dazu muss ich meinen Quelltext aufsplitten (ob mit PHP oder VBA wird sich noch zeigen) und in eine Tabelle schreiben. Diese Tabelle (ich nenne sie mal Rohdaten) soll am Ende nur alle Stichwörter und eine ID (Autowert) enthalten. Man sieht schon: mit dem Content, das wird uferlos, das können leicht mehrere Zehntausend Wörter werden. Ich beschränke mich also auf die Wörter aus dem post_title, das ist besser zu handeln. Wir machen das mal als erste Annäherung und schauen uns dann an, was wir mit den extrahierten potentiellen Stichworten anfangen können.

Wie ich das in MS Access angehe: ich importiere mir die gesamte Tabelle wp_posts aus dem Original-Inselfischkochbuch über CSV-Export aus phpmyadmin. Dann schreibe ich mir eine Abfrage,, die nur den post_title enthält und als where-Klausel post_Type = post und post_status = publish bekommt, damit ich nur die echt veröffentlichten Rezepte in der Datenbasis habe. Die Abfrage heißt quelle und sieht so aus:

Screenshot quelle

265 Datensätze a drei bis zehn Wörter, damit kann man arbeiten. Ich lege ausserdem fest, dass ich nur Großgeschriebene Wörter im Stichwortverzeichnis haben möchte. Das ist willkürlich, aber doch recht sinnvoll, weil damit die ganzen kleinen Füllwörter rausfallen.

Dann gehts rund: Ich lege mir eine Tabelle namens ziel an, die nur zwei Felder hat: ID(AutoWert) und Wort(Text). Sie bleibt zunächst leer. Dann bastle ich mir ein VBA-Modul. Hier lege ich zwei Recordsets an, rstquelle das ist die Abfrage Quelle, und rstziel, das ist die Tabelle Ziel.

Jetzt gehe ich zum ersten Datensatz in rstquelle und lese mir den Inhalt des Feldes post_title ein. Dann verwende ich die VBA-Funktion split(), die zerlegt das Feld in einzelne Wörter, die in ein Array geschrieben werden.  Ich laufe durch dieses Array und prüfe zunächst, ob das Wort Groß oder klein geschrieben ist:

Asc(Left(liste(i), 1) >= 65) And (Asc(Left(liste(i), 1)) <= 90)

Mit dieser Funktion bin ich nicht so recht glücklich, weil sie unerklärlicherweise manche Wörter mit Kleinbuchstaben doch durchrutschen läßt, aber ich hab noch nichts besseres gefunden.

Dann werden noch evtl vorhandene Sonderzeichen entfernt, dazu gibts eine Funktion die Folgende Zeichenkette durchläuft:

Const strSonderzeichen As String = „.,:;#+’*?=)(/%$§!~\}][{“

Dann schreibe jeweils ein gefundenes, geputztes Wort in die Zieltabelle. Dann gehe ich zum nächsten Datensatz der Quelltabelle und wiederhole den Vorgang. das mache ich, bis EOF der Quelltabelle erreicht ist.

Hurra! 669 Datensätze, beim ersten Drüberschauen sieht es schon mal ganz gut aus. Noch die Dubletten ausblenden, das geht mit einer Abfrage mit Gruppierung ganz easy. Sortieren, man sieht noch ein bisschen Datenschmutz ganz oben, das bereinigt man per Hand.

abfrage quelle

Es bleiben 496 recht manierliche Stichworte übrig. Damit könnte ich jetzt schon nach MySQL und WordPress gehen und die Webseite aufbauen, aber ich halte mich noch ein wenig in Access auf und teste nochmal, mit der „wackeligen“ Asc-Funktion bin ich nicht zufrieden.

Konform zu WCAG: Kontrastfarben automatisch berechnen

Ich bin darauf hingewiesen worden, dass mein Color Tool für barrierefreie Kontrastfarben im WEB nicht der aktuellsten Version der WCAG entspricht. OK, hab ich ein bisschen recherchiert und umgestrickt. Was früher als Brightness gehandelt wurde, heißt jetzt Luminescence und wird etwas anders berechnet. Zum Vergleich der Schrift- und Hintergrundfarbe wird eine Ratio herangezogen, 4.5:1 entspricht AA, 7:1 enspricht AAA. Die Berechnung ist im Ganzen etwas komplexer geworden, aber doch kein Hexenwerk. Nachlesen kann man die nötigen Formeln hier:
https://www.w3.org/WAI/GL/wiki/Relative_luminance

Das Kernstück ist die Formel zur Umrechnung des RGB-Wertes aus dem Colorpicker in WCAG-konforme Lumineszenz, die sieht so aus:

function Luminescence($r, $g, $b) //neuere Definition nach wcag s. a. https://www.w3.org/WAI/GL/wiki/Relative_luminance

 {
 $rs = $r/255;
 $gs = $g/255;
 $bs = $b/255;
 
 if ($rs <= 0.03928)
 {
 $R = $rs/12.92;
 }
 else {
 $R = (($rs+0.055)/1.055) ** 2.4;}
 
 if ($gs <= 0.03928)
 { $G = $gs/12.92;
 }
 else {
 $G = (($gs+0.055)/1.055) ** 2.4;
 }
 
 if ($bs <= 0.03928){
 $B = $bs/12.92 ;}
 else 
 {$B = (($bs+0.055)/1.055) ** 2.4;}

 $Lumi = 0.2126 * $R + 0.7152 * $G + 0.0722 * $B;
 
 return $Lumi;
 
 
 }

Dann braucht man noch die Formel für die Contrast Ratio, die findet sich hier im WCAG-Wiki. Damit kann man sich einstellen, ob man AA oder AAA kompatibel sein möchte, und das wars dann auch im Grossen und Ganzen.

if ($input_luminescence >= $row_luminescence){
  $ratio = ($input_luminescence+0.05)/($row_luminescence+0.05);
  }
 else
 {
 $ratio = ($row_luminescence+0.05)/($input_luminescence+0.05);
 }

 if ($ratio>4.5){ //Nur die Farben nehmen bei denen die Ratio grösser als 4.5 ist
...


Viel Spaß beim Ausprogrammieren!

Erster Versuch mit HTML5 Canvas: ein kleines Feuerwerk

Ich habe bei den Musik-Animationen die ersten Erfahrungen mit dem Canvas-Element gesammelt, und ich muss sagen, ich bin sehr angetan. Das eröffnet wirklich ungeahnte Möglichkeiten, und ich finde es wesentlich eingänginger und intuitiver zu bedienen als CSS-Animationen, wo man sich ja ewig mit der Cross-Browser-Kompatibilität herumschlagen muss. Canvas wird von den meisten gängigen modernen Browsern unterstützt, genauere Info hier auf der Seite der Canvas Community.

Statt langer Vorreden legen wir gleich los: passend zum Jahreswechsel habe ich eine kleine Feuerwerksanimation geschrieben. Sowas gibt es schon, auch als downloadbare Freeware, aber mir kam der Sourcecode der Beispiele immer unnötig aufgeblasen vor, ich dachte mir, das muss doch auch einfacher gehen…. und es geht einfacher, deutlich.

Die Vorgabe

Meine Vorgabe ist folgende: auf einem dunklen Sternenhimmel sollen farbige Feuerwerksraketen sternförmig explodieren, an zufälligen Stellen auf dem Canvas. Die Animation soll per Klick startbar sein und dann in einer Endlosschleife laufen. Aussehen soll das ganze etwa so:

screenshot_feuerwerk

screenshot_feuerwerk

Dafür brauche ich zwei Zeitschleifen. Die äussere Schleife wird endlos wiederholt (setInterval…) und erzeugt immer einen neuen zufälligen Mittelpunkt der nächsten Explosion. An einem gegebenen Mittelpunkt startet dann die zweite Zeitschleife, hier soll die Sternenexplosion in mehreren Iterationsschritten von der Mitte aus zeitverzögert ablaufem, dafür nehme ich einen setTimeout. Für die Skriptsteuerung brauche ich Jquery, das binde ich mal lokal ein.

Los gehts: wir basteln uns erst einmal die Leinwand, den canvas, das ist straightes HTML:

<canvas id="leinwand" width="400" height="400" 
style="display: block; background: url('sternenhimmel.jpg')" ></canvas>

Ich lege hier gleich mal einen netten Sternenhimmel in den Hintergrund.

Dann brauchen wir noch einen Startknopf:

<input type="button" value = "Abspielen" onclick = "kontrolle()" >

Die Funktion kontrolle() tut nichts weiter als die Funktion zeichnen() aufzurufen, hier könnte man noch Parameter übergeben, z.B. eine Wiederholungsrate oder die Dauer einer Schleife, aber ich hab das mal gelassen und setze die entsprechenden Werte direkt im Code. Als allererste Massnahme definiert die Funtkion zeichnen() einen Canvas-2d-Context, mit dem arbeiten wir dann weiter:

function zeichnen(param) {
    
    // get the context from the canvas to draw on
    var lwd = $("#leinwand").get()[0].getContext("2d");
...

lwd ist jetzt unser Zeichenbrett.

Wie man einen Stern zeichnet

Wir zäumen das Pferd jetzt mal von hinten auf. Wie zeichnet man überhaupt einen Stern auf den Canvas? Man braucht einen festen Mittelpunkt in Form einer x- und einer y-Koordinate, und einen festen Radius. Dann braucht man noch eine mathematische Formel, die einem ausrechnet bis zu welchem Endpunkt ein Strahl zu einem bestimmten Winkel gesetzt werden soll. Die Formel packt man in eine for…Schleife, und zählt den Winkel einfach hoch, bis man einmal rum ist.

//Begin funktion strahlen zeichnen        
function strahlen(fx,fy,radius){
                    
           var rad = radius;
                    //Beginn strahlen graduell
                    for (grad = -1; grad <=1; grad = grad + 0.2){
                        
                        theta = grad*Math.PI;
                        lwd.moveTo(fx, fy);
                        lwd.lineTo(fx + rad * Math.cos(theta), fy + rad * Math.sin(theta));
                                            
                        //jeder Strahl eine andere Farbe
                        lwd.strokeStyle = "hsl("+Math.floor((Math.random()*359))+", 100%, 50%)";
                        lwd.stroke();
                        
                        //Nach der letzten Schleife Leinwand leer machen
                        if (radius == 100){lwd.clearRect(0, 0, 400, 400);}
                        
                        //**Pfad neu zeichnen (ohne "Geisterbilder")
                        lwd.beginPath();
                                                                
                    }//end strahlen graduell
        
} // Ende von fucntion strahlen    zeichnen

Man setzt den Cursor mit .moveTo auf den Mittelpunkt, und zeichnet mit dem .lineTo den Strahl bis zur berechneten Koordinate. .stroke() führt die Zeichnung aus. Dann wird der Winkel hochgesetzt, man zeichnet den nächsten Strahl, bis man einmal um den Kreis von -1 bis +1 herum ist. Ich hab hier auch noch die Farbdefinition mit hineingepackt und bestimme für jeden Strahl eine zufällige hsl-Farbe, das macht sich ganz hübsch.

Nach dem letzten Aufruf (gegebener maximaler Radius von 100 ist erreicht) macht man die Leinwand leer, damit der Stern auch wieder verschwindet. .beginPath() macht dann noch klar Schiff auf dem internen Pfad-Objekt, wenn das fehlt hat man dann später „Geisterbilder“ von den vorher bereits gezeichneten Sternen.

Die erste Animation: Sterne mit steigenden Radien

Damit der Stern nicht in einem Flash auftaucht, sondern sich wie bei einer Explosion von innen heraus vergrößert, rufe ich die soeben definierte Funktion strahlen() mehrfach auf, immer mit dem selben Mittelpunkt, aber mit stetig wachsenden Radien. Dafür benutze ich einen setTimeout:

//*********begin function sternchen mit timeout    
function sternchen(koord1,koord2){

var i = 10;      //  zähler für den Radius auf 10 (px)
                
//Zufälliger Mittelpunkt des sterns kommt als Parameter rein koord zwischen 1 und 400
var x1 = koord1;
var y1 = koord2;
                
        function myLoop () {           //  Loop function definieren
           setTimeout(function () {    //  setTimeout Wenn die Loop-Funktion aufgerufen wird
                        
              strahlen(x1,y1,i);        //  Strahlen zeichnen an festem Mittelpunkt und Radius
              i=i+10;;                  //  Radius um 10 (px) hochsetzen
              if (i <=100) {            //  Radius <= 100?           
                 myLoop();              //  Loop function erneut aufrufen, Strahlen mit neuem Radius zeichnen
              }                           
              
           }, 50)                        //  ..  setTimeout() auf 50 ms
           
        } //*******Ende von function myloop

myLoop();        //Startet den Loop

} //******ende von function sternchen

Mein i geht in 10er-Schritten hoch, das benutze ich als Radius für den explodierenden Stern in px. Die x- und y-Koordinate des Mittelpunkts bleiben immer gleich, die hab ich als Parameter reingegeben. Der Timeout läuft auf 50 Millisekunden, das ergibt eine hübsch gleichmässige Bewegung. Die Schleife bricht erst ab, wenn der maximale Radius von 100 px erreicht ist.

Die zweite Animation: alle halbe Sekunde ein neuer zufälliger Mittelpunkt

Meine Funktion sternchen() wird jetzt alle 500 my aufgerufen, und bei jedem Aufruf wird eine zufällige x- und y-Koordinate für den Mittelpunkt der Explosion generiert. Das ganze wird mit einem setInterval in einer Endlosschleife gesteuert:

//Beginn Feuerwerk Endlosschleife
        //passiert alle x millisekunden
        var drawLinesInterval = setInterval(function() {
                
                //Leinwand putzen
                lwd.clearRect(0, 0, 400, 400);
                
                //Zufälligen Mittelpunkt des Sterns bestimmen Koordinaten zwischen 1 und 400
                var koord1 = Math.floor(Math.random() * 20 + 1)*20;
                var koord2 = Math.floor(Math.random() * 20 + 1)*20;
                
                //Funktion zum Sternzeichnen aufrufen            
                sternchen(koord1,koord2);
                
        }, 500); // end drawLinesInterval

Das wars auch schon! Morgen packe ich noch eine Demo mit dazu. da könnt ihr euch dann den Source direkt anschauen. Canvas macht Laune!

 

 

Musik sichtbar machen 2: ein animiertes Volume Meter

Ich hab noch ein bisschen nach Audiospielereien gegooglet, und bin bei dzone fündig geworden. Hier wird ganz genau erklärt, wie man mit der Web Audio API von HTML5 einen Audioplayer und ein einfaches Zweikanal-Volumemeter konstruiert:

https://dzone.com/articles/exploring-html5-web-audio

Mit den vorgefertigten Beispielen ist es einfach, sich ein kleines Animationsbeispiel selber zu basteln. Kleiner Wermutstropfen: es funktioniert nicht mit dem Internet Explorer. Aber hübsch ist es trotzdem!

Statt langer Rede stelle ich hier einfach eine kleine Demo rein:

https://evileu.de/demos/peters_roll/peters_roll.html

Das Script läuft mit einer lokalen Kopie von jquery-1.8.0.min.js, wer mag kann das ja noch anpassen. Viel Vergnügen beim Nachbasteln!

Musik sichtbar machen: der Wavesurfer

Ich habe an den Feiertagen ein bisschen mit Audio/Multimedia rumgespielt, und bin da auf ein sehr hübsches Skript gestossen, den wavesurfer.js. Er ermöglicht die Darstellung einer wav-Datei als Frequenzkurve, die beim Abspielen der Musik animiert durchlaufen wird. Das sieht dann zum Beispiel so aus:

peters_roll_screenshot

peters_roll_screenshot

Die Animation läuft synchron zur Musik, das Layout ist fully responsive – eine sehr hübsche Angelegenheit!

Die Implementierung ist denkbar einfach, man bindet das Skript ein:

<script src="https://unpkg.com/wavesurfer.js"></script>

Dann kann man schon loslegen. Man braucht nur eine Div, in die der wavesurfer-Output geschrieben werden kann, und einen Button zum Starten:

<input type="button" value = "Abspielen" onclick = "play()" >
<div id="waveform"></div>

Die Function play sieht dann Beispielsweise so aus:

function play(){
    
    var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    waveColor: 'yellow',
    progressColor: 'blue',
    });

Man legt eine neue Instanz von WaveSurfer auf eine Variable, und stellt die Ausgabe-div und die Farbe ein. Mit der Variablen kann man dann weiterarbeiten:

wavesurfer.load('musik.wav');

wavesurfer.on('ready', function () {
    
    wavesurfer.play();
    var dauer = wavesurfer.getDuration();
    console.log("Dauer:"+dauer);
    
}); //Ende von play()

Die Wav-Datei muss erst vollständig geladen sein, ehe die Animation loslegen kann, deswegen erst den load, dann die Statusabfrage  wavesurfer.on(‚ready’…, die Musik wird erst gestartet wenn der ready-Event zündet. Ich hab hier gleich mal noch ein bisschen gespielt und gebe mir die Dauer des Musikstücks in der Konsole aus, das funktioniert mit dem .getDuration().

Hier habe ich eine kleine Demoversion gebastelt, der Trommelwirbel stammt von meinem Lieblingscousin:

https://evileu.de/demos/wavesurfer_min.html

Mehr zu den Wavesurfer-Methoden gibts hier:

https://wavesurfer-js.org/docs/methods.html

Die Doku ist zwar sehr knapp gehalten, aber das Nötigste findet man schnell heraus, und es gibt auch einige hübsche Plugins. Ein gelungene Sache, finde ich – und ausbaufähig!

WordPress 5.0 und Gutenberg – der erste Eindruck

Was soll ich sagen? Gerade WordPress 5.0 installiert, und gleich beim ersten Versuch mit dem neuen Editor Gutenberg einen Bug produziert. Ich hab einfach mal rumgeklickt und einen „Drop Cap“ angewählt, also ein Initial, und dazu eine Hintergrundfarbe. Das sah dann erstmal so aus:

dropcap_bug

dropcap_bug

Ist jetzt irgendwie nicht so ideal, oder?

Das neue Theme Twenty Nineteen ist ausserdem so ziemlich das häßlichste Theme, das mir je untergekommen ist. Das Design ist absolut grottig, die Schriften sind für meinen Geschmack lieblos zusammengeklatscht, und statt eines schönen Titelbilds ist nur ein minikleines rundes Logo vorgesehen. Die Startseite sieht dann z.B. so aus:

schriften

schriften

Weiter unten ist es auch nicht schöner, der Widget-Bereich ist vom Layout her so schön wie eine billige Einwurfzeitung:

widgetarea

widgetarea

Dann wollte ich ein Bild einfügen – hab erstmal nur die Option „Beitragsbild“ gefunden, das stellt sich dann so dar, blaugetönt und über die ganze Seite ausgebreitet:

beitragsbild

beitragsbild

Finde ich jetzt auch nicht wirklich prickelnd…

Aber ein Theme kann man wechseln, ich hör da mal auf zu meckern und nehm das Twenty Sixteen, damit bin ich eigentlich immer gut gefahren. Wollen doch mal sehen, wie sich der neue Editor benimmt.

Ich möchte gerne eine Liste mit Bullets, erster Ansatz: ich schreib mal meine Listenpunkte untereinander hin, mach jeweils ein Return am Ende. Und jetzt? Noch nichts weiter in Sicht. Ich markiere mal meine drei Listenpunkte, dann ändert sich das Bild. Anscheinend wird für jeden Listenpunkt ein Block angelegt.

drei_blocks

drei_blocks

Ah, guxtu! Wenn man auf das Paragraph-Zeichen drauffährt, kommt auch ein Tooltip, der sagt „Change Block Type“, und hier kriege ich schließlich die Auswahl Liste oder Zitat:

transform_to_list

transform_to_list

Ah, geschafft! Anscheinend brauche ich für jeden Listenpunkt einen eigenen Block, so läuft der Hase.

liste

liste

Dann werde ich wohl für ein Bild auch einen eigenen Block brauchen, schätze ich mal. Ich mach da mal unterhalb der Liste weiter. Wenn man da ganz genau hinguckt, aber wirklich ganz genau, sieht man drei ausgegraute Icons, das mittlere davon könnte evtl. für ein Bild sein:

graue_icons

graue_icons

Sehen sie die Icons in der rechten unteren Ecke? Also, ohne Brille hätte ich da keine Chance. Na gut, klicken wir mal auf das Bild-Icon. Hurra, da kommt der Media-Uploader!

media_uploader

media_uploader

Wenn ich das Bild eingefügt habe, erscheinen rechts im Editorfenster die Bildeigenschaften, das ist OK:

bildeigenschaften

bildeigenschaften

Wenn ich jetzt rechts neben dem Bild Text weiterlaufen lassen will, geht das wieder nur mit einem neuen Block. Hier vermisse ich die Oprion „Als Text einfügen“, die hab ich einfach nicht gefunden. Wenn ich jetzt z.B. aus Word einen Text mit einer Überschrift reinkopiere, baut er mir gleich wieder zwei Blocks, einen für die Überschrift und einen für den Textkörper. Langsam wirds hier unübersichtlich. Ausserdem fehlen im Text etliche Leerzeichen, das ist nicht schön:

leerzeichen_fehlen

leerzeichen_fehlen

Jetzt möchte ich gern noch ein Video einfügen, also frisch auf, ein neuer Block. Klick auf das Icon „Add file“, dann gehts wieder in die Mediathek oder zum Upload und wird defaultmässig zum Download angeboten, das ist ganz OK.

file_download

file_download

Man kann aber auch mit „Change Block Type“ das ganze in ein eingebettetes Video konvertieren, wer das möchte ist auch gut bedient.

Ich lasse es hier mal gut sein, für einen ersten Eindruck reicht das. Das man für jeden Pfiffkaas einen eigenen Block braucht, finde ich dann doch etwas gewöhnungsbedürftig. Man hat dann quasi den Bildschirm voll mit lauter kleinen spezialisierten Editorfenstern, die einem immer nur die Optionen anbieten, die für den jeweiligen Blocktype gültig sind. Na ja. Das kann man mögen oder nicht, ich finde es ziemlich gewöhnungsbedürftig. Was mich definitiv stört: ich bin mehrfach in eine „Keyboard Trap“ gefallen, wo die Tab- und Pfeiltasten nicht mehr so durch den Artikel navigieren, wie man es erwarten würde. Das ist natürlich total grottenschlecht für Benutzer, die Gutenberg nicht mit der Maus, sondern über die Tastatur bedienen möchten. Aber das geht schon stark ans Thema Barrierefreiheit, und sprengt den Rahmen dieses ersten subjektiven Eindrucks.  Mein Fazit: geht so. Ich sehe keinen großen Vorteil im Block-Konzept, aber man kanns wahrscheinlich doch recht schnell lernen. Man kann mit Gutenberg arbeiten, aber wo der grosse bahnbrechende Innovationsvorsprung liegt, hat sich mir nic.ht erschlossen.

Barrierefreie Farbkontraste revisited: die ganze HTML-Palette

140 Farben war mir zuwenig

Ich habe in dem Artikel über Barrierefreie Farbkontraste 2 den Source zur Bestimmung von idealen Kontrastfarben nach WCAG-Richtlinien aus den benannten Farben der HTML-Palette vorgestellt. Jetzt habe ich das Thema nochmal aufgegriffen, weil mir die Beschränkung auf die benannten Farben doch ein zu enges Korsett war, das sind ja nur ca. 140, und der HTML-Farbraum umfasst  bekanntermassen 24 Bit Farbtiefe, das sind 16.777.216 Farben. Ich hatte damals eine MySQL Tabelle der benannten Farben mit ihren RGB-Werten verwendet, das Konzept habe ich jetzt gekippt, bei über 16 Mio Farben war mir das dann doch zu unhandlich.

Der ganze HTML-Farbraum

Statt dessen benutze ich jetzt den ganzen Farbraum zur Bestimmung der idealen Kontrastfarben und berechne mir die RGB-Komponenten durch drei geschachtelte While-Schleifen. Na ja, nicht den ganzen Farbraum, ich steppe mit einer definierten Schrittweite durch die RGB-Werte, damit die Ergebnisse nicht so unübersichtlich werden. In der Testphase hat sich eine Schrittweite von 20 als praktikabel erwiesen, da hat man noch eine wirklich grosse Auswahl möglicher Farben, und es bleibt trotzdem recht übersichtlich.

Was das Programm macht

Zur Eingabe der vom Benutzer gewünschten Farbe benutze ich wieder einen Colorpicker, man könnte aber auch gleichgut ein Textfeld zur Eingabe des Hex- oder RGB-Wertes vorsehen. Die gewählte Farbe wird in ihre RGB-Komponenten zerlegt, mithilfe der Formel für die relative wahrgenommene Helligkeit wird die Brightness bestimmt. Ein barrierefreier Farbkontrast wird bei einer Differenz der Brightness zweier Farben von einem Wert von ca. 120 bis 130 erzielt, diesen kann man im Code festlegen.

Ich steppe jetzt in drei geschachtelten Schleifen durch den gesamten 24-Bit-Farbraum. Damit das nicht uferlos wird, gebe ich wie gesagt für jede Iteration eine Schrittweite von 20 an, bei Bedarf könnte man das auch noch feiner oder gröber einstellen.

Ich berechne die Brightness der jeweils aktuellen Farbe, berechne die Differenz zur vom Benutzer gewählten Farbe und gebe die aktuelle Farbe nur dann aus, wenn diese Differenz über dem eingestellten Schwellwert liegt. Bei der Ausgabe liefere ich dann gleich den rgb(x,y,z) der aktuellen Farbe mit. That’s it – wenn ich dazukomme, mache ich die Tage noch ein paar Screenshots der Ausgabe. Den Sourcecode liefere ich diesmal nicht mit, der kommt in mein Portfolio 🙂

Nachtrag: die Screenshots

Der Startbildschirm ist unspektakulär, hat aber auch nur eine Funktionailtät: den Colorpicker.

el_allcolors_start

el_allcolors_start

Hier ein Ausschnitt des Ergebnisses, man sieht dass die gewählte Farbe wirklich gut zu den vorgeschlagenen Farben kontrastiert:

el_allcolors_ergebnis

el_allcolors_ergebnis

Ganz am Ende gebe ich noch aus, wieviele mögliche Kontrastfarben es gibt:

el_allcolors_anzahlfarben

el_allcolors_anzahlfarben

Das wars –  viel Spaß beim Austüfteln!