Adding SVG based completion arc
This commit is contained in:
parent
a6ebafb234
commit
11e5f99ba4
|
@ -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: `
|
||||
<span class='r-progress-circle'><svg
|
||||
:width="(1+stroke)+'em'"
|
||||
:height="(1+stroke)+'em'"
|
||||
:viewbox="'0 0 '+ size.w + ' '+size.h">
|
||||
<circle :cx="center.x" :cy="center.y" :r="50"
|
||||
:style="'opacity: ' + bgopacity + ';stroke-width: '+ (stroke*100)+'; stroke: currentcolor; fill: none;'"/>
|
||||
<path :d="arcpath(center.x,center.y,50)"
|
||||
:style="'stroke-width: ' + (stroke*100) +'; stroke: currentcolor; fill: none;'"/>
|
||||
</svg></span>
|
||||
`,
|
||||
});
|
||||
|
||||
|
||||
Vue.component('r-report', {
|
||||
props: {
|
||||
value: {
|
||||
|
@ -545,7 +625,13 @@ export default {
|
|||
</b-col>
|
||||
<b-col md="11">
|
||||
<b-card-body class="align-items-center">
|
||||
<i v-b-popover.top
|
||||
<r-progress-circle v-if='value.course.completion'
|
||||
:value='value.course.completion.progress'
|
||||
:max='value.course.completion.count'
|
||||
:min='0'
|
||||
:class="'r-course-result r-completion-'+value.completion"
|
||||
></r-progress-circle>
|
||||
<i v-else v-b-popover.top
|
||||
:class="'r-course-result fa fa-'+completion_icon(value.completion)+
|
||||
' r-completion-'+value.completion"
|
||||
:title="text['completion_'+value.completion]"></i>
|
||||
|
|
63
amd/src/svgarc.js
Normal file
63
amd/src/svgarc.js
Normal file
|
@ -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};
|
Loading…
Reference in New Issue
Block a user