diff --git a/basic-example/README.md b/basic-example/README.md new file mode 100644 index 0000000..9198eab --- /dev/null +++ b/basic-example/README.md @@ -0,0 +1,15 @@ +# Grundlegendes Beispiel + +_FΓΌr Kapitel 3.3_ + +[D3](https://d3js.org/) ist eine JavaScript-Bibliothek zur Datendarstellung. + +In `javascript.html` und `pyscript.html` wird dargestellt, wie Daten fΓΌr die Verwendung in D3 jeweils mit JavaScript und PyScript von einer externen Quelle in JSON-Form bezogen mithilfe von D3 in die Seite eingebettet werden. + +Die Darstellungen sollten exakt gleich aussehen. + +## Notizen/Hinweise + +`pyscript.py` in diesem Ordner wird nicht direkt verwendet, sondern ist nur eine Kopie des Skriptes aus `pyscript.js` und dient nur dem Zweck einer besser lesbaren Darstellung in gΓ€ngigen Editoren und auf GitHub. + +Der Kommentar `` verhindert, dass mein verwendeter Formatter Prettier den Inhalt `py-script`-Tags staucht und damit unbrauchbar macht. diff --git a/basic-example/base.html b/basic-example/base.html new file mode 100644 index 0000000..5a3dfdb --- /dev/null +++ b/basic-example/base.html @@ -0,0 +1,179 @@ + + + d3: JavaScript & PyScript visualizations side-by-side + + + + + + + + + + + Based on + Learn D3: Shapes + tutorial. + +
+
+
JavaScript version
+
+
+
+
+
+
PyScript version
+
+
+
+
+
+ + + + + + + + from pyodide import create_proxy, to_js + import d3 + + fruits = [ + dict(name="🍊", count=21), + dict(name="πŸ‡", count=13), + dict(name="🍏", count=8), + dict(name="🍌", count=5), + dict(name="🍐", count=3), + dict(name="πŸ‹", count=2), + dict(name="🍎", count=1), + dict(name="πŸ‰", count=1), + ] + + fn = create_proxy(lambda d, *_: d["count"]) + data = d3.pie().value(fn)(to_js(fruits)) + + arc = (d3.arc() + .innerRadius(210) + .outerRadius(310) + .padRadius(300) + .padAngle(2 / 300) + .cornerRadius(8)) + + py = d3.select("#py") + py.select(".loading").remove() + + svg = (py + .append("svg") + .attr("viewBox", "-320 -320 640 640") + .attr("width", "400") + .attr("height", "400")) + + for d in data: + d_py = d.to_py() + + (svg.append("path") + .style("fill", "steelblue") + .attr("d", arc(d))) + + text = (svg.append("text") + .style("fill", "white") + .attr("transform", f"translate({arc.centroid(d).join(',')})") + .attr("text-anchor", "middle")) + + (text.append("tspan") + .style("font-size", "24") + .attr("x", "0") + .text(d_py["data"]["name"])) + + (text.append("tspan") + .style("font-size", "18") + .attr("x", "0") + .attr("dy", "1.3em") + .text(d_py["value"])) + + + diff --git a/basic-example/javascript.html b/basic-example/javascript.html new file mode 100644 index 0000000..14eae32 --- /dev/null +++ b/basic-example/javascript.html @@ -0,0 +1,95 @@ + + + + + + + + + + + + D3 mit JavaScript + + +
+
JavaScript
+
+
+
+
+ + + + diff --git a/basic-example/pyscript.html b/basic-example/pyscript.html new file mode 100644 index 0000000..174b092 --- /dev/null +++ b/basic-example/pyscript.html @@ -0,0 +1,97 @@ + + + + + + + + + + + + D3 mit PyScript + + +
+
PyScript
+
+
+
+
+ + + + + + from pyodide import create_proxy, to_js, open_url + import d3 + import json + + url = f"https://duolingo.checksch.de/duo_user_info.json" + res = open_url(url) + lang_info = json.loads(res.read())["lang_data"] + lang_info_prepped = [] + + for lang in lang_info: + item = dict(name=lang_info[lang]["learningLanguage"], count=lang_info[lang]["xp"]) + + if lang_info[lang]["xp"] > 500: + lang_info_prepped.append(item) + + fn = create_proxy(lambda d, *_: d["count"]) + data = d3.pie().value(fn)(to_js(lang_info_prepped)) + + arc = ( + d3.arc() + .innerRadius(210) + .outerRadius(310) + .padRadius(300) + .padAngle(2 / 300) + .cornerRadius(8) + ) + + py = d3.select("#py") + py.select(".loading").remove() + + svg = ( + py.append("svg") + .attr("viewBox", "-320 -320 640 640") + .attr("width", "400") + .attr("height", "400") + ) + + for d in data: + d_py = d.to_py() + + (svg.append("path").style("fill", "rebeccapurple").attr("d", arc(d))) + + text = ( + svg.append("text") + .style("fill", "white") + .attr("transform", f"translate({arc.centroid(d).join(',')})") + .attr("text-anchor", "middle") + ) + + ( + text.append("tspan") + .style("font-size", "24") + .attr("x", "0") + .text(d_py["data"]["name"]) + ) + + ( + text.append("tspan") + .style("font-size", "18") + .attr("x", "0") + .attr("dy", "1.3em") + .text(d_py["value"]) + ) + + + diff --git a/basic-example/pyscript.py b/basic-example/pyscript.py new file mode 100644 index 0000000..42ce7ac --- /dev/null +++ b/basic-example/pyscript.py @@ -0,0 +1,63 @@ +from pyodide import create_proxy, to_js, open_url +import d3 +import json + +url = f"https://duolingo.checksch.de/duo_user_info.json" +res = open_url(url) +lang_info = json.loads(res.read())["lang_data"] +lang_info_prepped = [] + +for lang in lang_info: + item = dict(name=lang_info[lang]["learningLanguage"], count=lang_info[lang]["xp"]) + + if lang_info[lang]["xp"] > 500: + lang_info_prepped.append(item) + +fn = create_proxy(lambda d, *_: d["count"]) +data = d3.pie().value(fn)(to_js(lang_info_prepped)) + +arc = ( + d3.arc() + .innerRadius(210) + .outerRadius(310) + .padRadius(300) + .padAngle(2 / 300) + .cornerRadius(8) +) + +py = d3.select("#py") +py.select(".loading").remove() + +svg = ( + py.append("svg") + .attr("viewBox", "-320 -320 640 640") + .attr("width", "400") + .attr("height", "400") +) + +for d in data: + d_py = d.to_py() + + (svg.append("path").style("fill", "rebeccapurple").attr("d", arc(d))) + + text = ( + svg.append("text") + .style("fill", "white") + .attr("transform", f"translate({arc.centroid(d).join(',')})") + .attr("text-anchor", "middle") + ) + + ( + text.append("tspan") + .style("font-size", "24") + .attr("x", "0") + .text(d_py["data"]["name"]) + ) + + ( + text.append("tspan") + .style("font-size", "18") + .attr("x", "0") + .attr("dy", "1.3em") + .text(d_py["value"]) + )