-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmenu.js
159 lines (146 loc) · 4.91 KB
/
menu.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import {html,html_tag,add_sheet,remove_sheet,defined,add_style_element} from "../libs/web-js-utils.js"
import {event} from "./utils.js"
import {Svg} from "../libs/svg_utils.js"
let utl = new Svg()
let svg = null;
let menu_svg = null;
let buttons = {};
let texts = {};
let params = null
let state = {active:false}
let sheet = null
/**
*
* @param {*} rel : relative position [0,1] around the 360° circle
* @param {*} radius
*/
function angle_pos(rel,radius){
let angle = rel * 2 * Math.PI
let x = radius * Math.cos(angle)
let y = radius * Math.sin(angle)
return [x,y]
}
function remove(){
if(state.active){
svg.removeChild(menu_svg)
console.log("menu over")
state.active = false
event("context_menu",{menu:params.menu,type:"end"})
if(sheet!=null){
remove_sheet(sheet)
}
//can't remove sheet with : document.adoptedStyleSheets.splice(document.adoptedStyleSheets.indexOf(sheet))
}
}
function onMouseLeave(e){
remove()
}
function onPointerDown(e){
let pointer_2 = defined(e.buttons)?(e.buttons == 2):(e.touches.length == 2)
if(pointer_2 || (!e.target.classList.contains("svg_menu"))){
remove()
}
}
function onContext(e){
e.preventDefault();
e.stopPropagation();
}
class Menu{
call(Params){
params = Params
const circle_radius = 80
const pie_radius_start = 20
const pie_radius_end = 90
svg = Params.svg
let [x,y] = [Params.x,Params.y]
menu_svg = html(svg,/*html*/`<g id="g_menu"/>`)
html_tag(menu_svg,"circle",/*html*/`
<circle class="svg_menu" cx="${x}" cy="${y}" r="10" fill="rgba(120,160,200,0.5)" >
<animate attributeName="r" begin="0s" values="10;${circle_radius}" keyTimes="0;1" calcMode="spline" keySplines="0 .75 .25 1" dur="300ms" repeatCount="1" fill="freeze"/>
</circle>`)
menu_svg.getElementsByTagName("animate")[0].beginElement()
state.active = true
menu_svg.addEventListener( 'mouseleave', onMouseLeave, false );
svg.addEventListener( 'mousedown', onPointerDown, false );
svg.addEventListener( 'touchstart', onPointerDown, false );
menu_svg.addEventListener( 'contextmenu', onContext, false );
const len = Params.actions.length
buttons = {}
texts = {}
Params.actions.forEach((a,i)=>{
const start = i / len
const stop = (i+1) / len
const margin = 0.01
let pie = utl.pie(menu_svg,x,y,pie_radius_start,pie_radius_end,start,stop,margin)
buttons[a] = pie
pie.setAttribute("data-name",a)
pie.setAttribute("visibility","hidden")
pie.classList.add("svg_menu")
pie.classList.add("pie_element")
let [tx,ty] = angle_pos((start+stop)/2,(pie_radius_start+pie_radius_end)/2)
texts[a] = html(menu_svg,/*html*/`<text x="${x+tx}" y="${y+ty}" class="m_text" dominant-baseline="middle" text-anchor="middle" style="pointer-events:none" visibility="hidden">${a}</text>`)
})
Params.actions.forEach((action,i)=>{
setTimeout(()=>{
buttons[action].setAttribute("visibility","visible")
texts[action].setAttribute("visibility","visible")
},200+i*50)
})
try{
this.add_style_sheet()
}
catch(err){
console.log(err)
console.log(`adding style failed, falling back on old style`)
this.add_style(menu_svg)
}
return buttons
}
add_style_sheet(){
sheet = new CSSStyleSheet()
sheet.insertRule(/*css*/`
path.pie_element{
fill:hsl(140, 80%, 35%)
}`)
sheet.insertRule(/*css*/`
path.pie_element:hover{
fill:hsl(140, 80%, 45%)
}`)
sheet.insertRule(/*css*/`
path.pie_element:hover:active{
fill:hsl(140, 80%, 65%)
}`)
sheet.insertRule(/*css*/`
text.m_text{
font: bold 12px Verdana, Helvetica, Arial, sans-serif;
color:hsl(240, 80%, 65%)
}`)
add_sheet(sheet)
}
add_style(parent){
add_style_element(parent,/*css*/`
path.pie_element{
fill:hsl(140, 80%, 35%)
}
path.pie_element:hover{
fill:hsl(140, 80%, 45%)
}
path.pie_element:hover:active{
fill:hsl(140, 80%, 65%)
}
text.m_text{
font: bold 12px Verdana, Helvetica, Arial, sans-serif;
color:hsl(240, 80%, 65%)
}`)
}
update_action(old_action_name,new_action_name){
let pie = buttons[old_action_name]
pie.setAttribute("data-name",new_action_name)
let text = texts[old_action_name]
text.innerHTML = new_action_name
buttons[new_action_name] = pie
texts[new_action_name] = text
return buttons
}
}
export{Menu};