Merged in feature/VBV-259-create-new-circle-component (pull request #21)

This commit is contained in:
Elia Bieri 2023-02-09 09:31:03 +00:00
parent b667140d3e
commit bac7acb021
2 changed files with 156 additions and 0 deletions

View File

@ -0,0 +1,135 @@
<script setup lang="ts">
import * as d3 from "d3";
import * as log from "loglevel";
import { computed, onMounted } from "vue";
// @ts-ignore
import colors from "@/colors.json";
export type CircleSectorProgress = "none" | "in_progress" | "finished";
export interface CircleSectorData {
progress: CircleSectorProgress;
}
const props = defineProps<{
sectors: CircleSectorData[];
}>();
onMounted(async () => {
log.debug("LearningPathCircle mounted");
render();
});
interface CircleSector extends d3.PieArcDatum<number> {
arrowStartAngle: number;
arrowEndAngle: number;
progress: CircleSectorProgress;
}
const pieData = computed(() => {
const pieWeights = new Array(Math.max(props.sectors.length, 1)).fill(1);
const pieGenerator = d3.pie();
const angles = pieGenerator(pieWeights);
return angles
.map((angle) => {
// Rotate the circle by PI (180 degrees) normally 0 = 12'o clock, now start at 6 o clock
angle.startAngle += Math.PI;
angle.endAngle += Math.PI;
return Object.assign(
{
startAngle: angle.startAngle,
endAngle: angle.endAngle,
arrowStartAngle: angle.endAngle + (angle.startAngle - angle.endAngle) / 2,
arrowEndAngle: angle.startAngle + (angle.startAngle - angle.endAngle) / 2,
progress: props.sectors[angle.index].progress,
},
angle
);
})
.reverse() as CircleSector[];
});
const width = 450;
const height = 450;
const radius = Math.min(width, height) / 2.4;
function getColor(sector: CircleSector) {
let color = colors.gray[300];
if ("in_progress" === sector.progress) {
color = colors.sky[500];
}
if ("finished" === sector.progress) {
color = colors.green[500];
}
return color;
}
function render() {
const svg = d3.select(".circle-visualization");
// Clean svg before adding new stuff.
svg.selectAll("*").remove();
if (pieData.value) {
const arrowStrokeWidth = 2;
// Append marker as definition to the svg
svg
.attr("viewBox", `0 0 ${width} ${height}`)
.append("svg:defs")
.append("svg:marker")
.attr("id", "triangle")
.attr("refX", 11)
.attr("refY", 11)
.attr("markerWidth", 20)
.attr("markerHeight", 20)
.attr("markerUnits", "userSpaceOnUse")
.attr("orient", "auto")
.append("path")
.attr("d", "M -1 0 l 10 0 M 0 -1 l 0 10")
.attr("transform", "rotate(-90, 10, 0)")
.attr("stroke-width", arrowStrokeWidth)
.attr("stroke", colors.gray[500]);
const g = svg
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Generate the pie diagram wedge
const wedgeGenerator = d3
.arc()
.innerRadius(radius / 2.5)
.padAngle(12 / 360)
.outerRadius(radius);
const learningSequences = g
.selectAll(".learningSegmentArc")
.data(pieData.value)
.enter()
.append("g")
.attr("class", "learningSegmentArc");
learningSequences
.transition()
.duration(1)
.attr("fill", (d) => {
return getColor(d);
});
// @ts-ignore
learningSequences.append("path").attr("d", wedgeGenerator);
}
return svg;
}
</script>
<template>
<div class="svg-container h-full content-center">
<pre hidden>{{ pieData }}</pre>
<pre hidden>{{ render() }}</pre>
<svg class="circle-visualization h-full">
<circle :cx="width / 2" :cy="height / 2" :r="radius" :color="colors.gray[300]" />
<circle :cx="width / 2" :cy="height / 2" :r="radius / 2.5" color="white" />
</svg>
</div>
</template>

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import IconLogout from "@/components/icons/IconLogout.vue";
import IconSettings from "@/components/icons/IconSettings.vue";
import LearningPathCircle from "@/components/learningPath/LearningPathCircle.vue";
import HorizontalBarChart from "@/components/ui/HorizontalBarChart.vue";
import ItCheckbox from "@/components/ui/ItCheckbox.vue";
import ItCheckboxGroup from "@/components/ui/ItCheckboxGroup.vue";
@ -496,6 +497,26 @@ function log(data: any) {
/>
<HorizontalBarChart title="Frage X" text="Fragentext" :items="barChartItems" />
</div>
<h2 class="mt-8 mb-8">LearningPathCircle</h2>
<LearningPathCircle
class="h-48 w-48"
:sectors="[
{
progress: 'finished',
},
{
progress: 'finished',
},
{
progress: 'in_progress',
},
{
progress: 'done',
},
]"
></LearningPathCircle>
</main>
</template>