From 11e5f99ba45b107baeb6c34171bb21bf9f32a793 Mon Sep 17 00:00:00 2001 From: PMKuipers Date: Sat, 20 May 2023 17:36:00 +0200 Subject: [PATCH] Adding SVG based completion arc --- amd/src/report-viewer-components.js | 90 ++++++++++++++++++++++++++++- amd/src/svgarc.js | 63 ++++++++++++++++++++ 2 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 amd/src/svgarc.js diff --git a/amd/src/report-viewer-components.js b/amd/src/report-viewer-components.js index a436849..026d6a3 100644 --- a/amd/src/report-viewer-components.js +++ b/amd/src/report-viewer-components.js @@ -9,8 +9,13 @@ import {get_strings} from 'core/str'; import {load_strings} from './string-helper'; import {call} from 'core/ajax'; import notification from 'core/notification'; +import {svgarcpath} from './svgarc'; //import {fixLineWrappers} from './studyplan-processor'; +// Make π available as a constant +const π = Math.PI; + + export default { install(Vue/*,options*/){ @@ -30,7 +35,7 @@ export default { /************************************ * * - * Treestudyplan Editor components * + * Treestudyplan Viewer components * * * ************************************/ @@ -43,6 +48,81 @@ export default { return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); } + Vue.component('r-progress-circle',{ + props: { + value: { + type: Number, + }, + max: { + type: Number, + default: 100, + }, + min: { + type: Number, + default: 0, + }, + stroke: { + type: Number, + default: 0.2, + }, + bgopacity: { + type: Number, + default: 0.2, + }, + }, + data() { + return { + selectedstudyplan: null, + }; + }, + computed: { + range() { + return this.max - this.min; + }, + fraction(){ + if(this.max - this.min == 0){ + return 1; + // 0 size is always full :) + } else { + return (this.value - this.min)/(this.max - this.min); + } + }, + center() { + const x = (1+this.stroke)*50; + const y = x; + return { 'x' : x, 'y' : y }; + }, + size() { + const w = (1+this.stroke)*100; + const h = w; + return { 'h' : h, 'w' : w }; + } + }, + methods: { + arcpath(cx, cy, r) { + let fraction = 1; + if(this.max - this.min != 0){ + fraction = (this.value - this.min)/(this.max - this.min); + } + + const Δ = fraction * 2*π; + return svgarcpath([cx,cy],[r,r],[0,Δ],270); + }, + }, + template: ` + + + + + `, + }); + + Vue.component('r-report', { props: { value: { @@ -545,7 +625,13 @@ export default { - + diff --git a/amd/src/svgarc.js b/amd/src/svgarc.js new file mode 100644 index 0000000..422948f --- /dev/null +++ b/amd/src/svgarc.js @@ -0,0 +1,63 @@ +/* +Copyright © 2020 Xah Lee, © 2023 P.M Kuipers +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +URL: SVG Circle Arc http://xahlee.info/js/svg_circle_arc.html +*/ + +const cos = Math.cos; +const sin = Math.sin; +const π = Math.PI; + +const f_matrix_times = (( [[a,b], [c,d]], [x,y]) => [ a * x + b * y, c * x + d * y]); +const f_rotate_matrix = (x => [[cos(x),-sin(x)], [sin(x), cos(x)]]); +const f_vec_add = (([a1, a2], [b1, b2]) => [a1 + b1, a2 + b2]); + +// function modified by pmkuipers for text params +/** + * Create svg path text for an arc + * @param {*} center [cx,cy] center of ellipse + * @param {*} radius [rx,ry] major minor radius + * @param {*} angle [t1, Δ] start angle, in radian, angle to sweep, in radian. positive. + * @param {*} φ rotation on the whole, in radian + * @returns a SVG path element that represent a ellipse. Text describing the arc path in an svg path element + */ +const svgarcpath = (([cx,cy],[rx,ry], [t1, Δ], φ ) => { + Δ = Δ % (2*π); + const rotMatrix = f_rotate_matrix (φ); + const [sX, sY] = ( f_vec_add ( f_matrix_times ( rotMatrix, [rx * cos(t1), ry * sin(t1)] ), [cx,cy] ) ); + const [eX, eY] = ( f_vec_add ( f_matrix_times ( rotMatrix, [rx * cos(t1+Δ), ry * sin(t1+Δ)] ), [cx,cy] ) ); + const fA = ( ( Δ > π ) ? 1 : 0 ); + const fS = ( ( Δ > 0 ) ? 1 : 0 ); + return "M " + sX + " " + sY + " A " + [ rx , ry , φ / (2*π) *360, fA, fS, eX, eY ].join(" "); +}); + +/** + * Create an svg arc element + * @param {*} center [cx,cy] center of ellipse + * @param {*} radius [rx,ry] major minor radius + * @param {*} angle [t1, Δ] start angle, in radian, angle to sweep, in radian. positive. + * @param {*} φ rotation on the whole, in radian + * @returns a SVG path element that represent a ellipse. + */ +const svgarc = (([cx,cy],[rx,ry], [t1, Δ], φ ) => { + const path_2wk2r = document.createElementNS("http://www.w3.org/2000/svg", "path"); + const d = svgarcpath([cx,cy],[rx,ry], [t1, Δ], φ ); + path_2wk2r.setAttribute("d", d); + return path_2wk2r; +}); + +export {svgarc, svgarcpath}; \ No newline at end of file