forked from Open-CT/openct-tasks
273 lines
8.7 KiB
JavaScript
273 lines
8.7 KiB
JavaScript
function GPS(settings) {
|
|
self = this;
|
|
var paper = settings.paper;
|
|
var paperID = settings.paperID;
|
|
var attr = settings.attr;
|
|
var x0 = settings.x0;
|
|
var y0 = settings.y0;
|
|
var w = settings.w;
|
|
var h = settings.h;
|
|
var scale = settings.scale;
|
|
var unit = settings.unit;
|
|
var fixed = settings.fixed;
|
|
var create = settings.create;
|
|
var hideTowerLabel = settings.hideTowerLabel;
|
|
|
|
this.timeShiftEnabled = settings.timeShiftEnabled;
|
|
this.timeShift = 0;
|
|
var firstTowersPos = settings.towerPos;
|
|
var towerR = settings.towerR;
|
|
var towerH = settings.towerH;
|
|
var towerW = settings.towerW;
|
|
var callback = settings.callback;
|
|
var addTowerCallback = settings.addTowerCallback;
|
|
var dragEndCallback = settings.dragEndCallback;
|
|
var dragMargin = 10;
|
|
var minR = towerR + dragMargin;
|
|
|
|
this.landscape;
|
|
this.overlay;
|
|
this.towers = {};
|
|
this.towerID = [];
|
|
this.distInfo = {};
|
|
var draggedData;
|
|
|
|
this.setTimeShift = function(val) {
|
|
this.timeShift = val;
|
|
this.updateShiftCircles();
|
|
};
|
|
|
|
this.init = function() {
|
|
paper.rect(x0,y0,w,h).attr(attr.frame);
|
|
if(firstTowersPos){
|
|
for(var pos of firstTowersPos){
|
|
this.addTower(pos);
|
|
}
|
|
}
|
|
this.overlay = paper.rect(x0,y0,w,h).attr(attr.overlay);
|
|
|
|
this.initHandlers();
|
|
};
|
|
|
|
this.initHandlers = function() {
|
|
Beav.dragWithTouch(this.overlay, onMove, onStart, onEnd);
|
|
this.overlay.mousemove(self.mousemove);
|
|
};
|
|
|
|
this.addTower = function(pos) {
|
|
if(pos.id && this.towerID.includes(pos.id)){
|
|
console.log(pos.id+" already exists")
|
|
return
|
|
}
|
|
var x = x0 + pos.x;
|
|
var y = y0 + pos.y;
|
|
var circle = paper.circle(x,y,towerR).attr(attr.tower);
|
|
if(!pos.id){
|
|
var id = 1;
|
|
while(this.towerID.includes(id)){
|
|
id++;
|
|
};
|
|
pos.id = id;
|
|
}
|
|
var label = paper.text(x,y,pos.id).attr(attr.towerLabel);
|
|
if(hideTowerLabel){
|
|
label.hide();
|
|
}
|
|
var circleR = pos.r || minR;
|
|
var outCircle = paper.circle(x,y,circleR).attr(attr.circle).attr("clip-rect",x0+","+y0+","+w+","+h);
|
|
if(this.timeShiftEnabled){
|
|
var shiftedCircle = paper.circle(x,y,circleR + this.timeShift).attr(attr.shiftedCircle).attr("clip-rect",x0+","+y0+","+w+","+h);
|
|
var raphObj = paper.set(circle,label,outCircle,shiftedCircle);
|
|
}else{
|
|
var raphObj = paper.set(circle,label,outCircle);
|
|
}
|
|
var maxR = Math.max(Math.abs(pos.x),Math.abs(pos.x - w),Math.abs(pos.y),Math.abs(pos.y - h));
|
|
this.towers[pos.id] = { x: pos.x, y: pos.y, raphObj: raphObj, r: circleR, maxR: maxR };
|
|
this.towerID.push(pos.id);
|
|
this.updateDistInfo(pos.id);
|
|
if(this.overlay){
|
|
this.overlay.toFront();
|
|
}
|
|
if(addTowerCallback){
|
|
addTowerCallback();
|
|
}
|
|
return pos.id;
|
|
};
|
|
|
|
this.mousemove = function(ev) {
|
|
var xMouse = ev.pageX - $("#"+paperID).offset().left - x0;
|
|
var yMouse = ev.pageY - $("#"+paperID).offset().top - y0;
|
|
var cursor = "auto";
|
|
for(var id of self.towerID){
|
|
var r = self.towers[id].r;
|
|
var x = self.towers[id].x;
|
|
var y = self.towers[id].y;
|
|
var d = Beav.Geometry.distance(x,y,xMouse,yMouse);
|
|
if(d > r - 10 && d < r + 10){
|
|
cursor = "grab";
|
|
break;
|
|
}
|
|
}
|
|
self.overlay.attr("cursor",cursor);
|
|
};
|
|
|
|
var onStart = function(x,y,ev) {
|
|
var xMouseGps = x - $("#"+paperID).offset().left - x0;
|
|
var yMouseGps = y - $("#"+paperID).offset().top - y0;
|
|
var minDist = Infinity;
|
|
draggedData = null;
|
|
for(var id of self.towerID){
|
|
var towerData = self.towers[id];
|
|
var distFromCenter = Beav.Geometry.distance(xMouseGps,yMouseGps,towerData.x,towerData.y);
|
|
|
|
if(!fixed && distFromCenter <= towerR){
|
|
/* drag center */
|
|
minDist = 0;
|
|
draggedData = { id: id, type: 0};
|
|
break;
|
|
}
|
|
var distFromCircle = Math.abs(distFromCenter - towerData.r);
|
|
if(distFromCircle < minDist){
|
|
minDist = distFromCircle;
|
|
draggedData = { id: id, type: 1, r0: distFromCenter, ri: towerData.r };
|
|
}
|
|
}
|
|
if(minDist > dragMargin){
|
|
draggedData = (!create) ? null : { x: xMouseGps, y: yMouseGps, create: true };
|
|
if(draggedData){
|
|
// console.log(draggedData)
|
|
}
|
|
}
|
|
if(callback){
|
|
callback();
|
|
}
|
|
};
|
|
var onMove = function(dx,dy,x,y,ev) {
|
|
if(!draggedData){
|
|
return
|
|
}
|
|
var xMouseGps = x - $("#"+paperID).offset().left - x0;
|
|
var yMouseGps = y - $("#"+paperID).offset().top - y0;
|
|
if(draggedData.create){
|
|
if(Beav.Geometry.distance(xMouseGps,yMouseGps,draggedData.x,draggedData.y) < minR){
|
|
return
|
|
}
|
|
var id = self.addTower(draggedData);
|
|
draggedData = {
|
|
id: id,
|
|
type: 1,
|
|
r0: minR,
|
|
ri: minR
|
|
}
|
|
}else{
|
|
var id = draggedData.id;
|
|
}
|
|
var ri = draggedData.ri;
|
|
var towerData = self.towers[id];
|
|
|
|
if(draggedData.type == 1){
|
|
/* drag circle */
|
|
var r0 = draggedData.r0;
|
|
var dR = Beav.Geometry.distance(xMouseGps,yMouseGps,towerData.x,towerData.y) - r0;
|
|
var maxR = Math.max(Math.abs(towerData.x),Math.abs(towerData.x - w),Math.abs(towerData.y),Math.abs(towerData.y - h));
|
|
var newR = Math.min(maxR,Math.max(minR,ri + dR));
|
|
self.towers[id].raphObj[2].attr("r",newR);
|
|
towerData.r = newR;
|
|
self.updateDistInfo(id);
|
|
}else{
|
|
/* drag center */
|
|
var newX = towerData.x + dx + x0;
|
|
var newY = towerData.y + dy + y0;
|
|
self.towers[id].raphObj.attr({ x: newX, y: newY, cx: newX, cy: newY });
|
|
self.distInfo[id].line.transform("t"+dx+" "+dy);
|
|
self.distInfo[id].val.transform("t"+dx+" "+dy);
|
|
}
|
|
if(self.timeShiftEnabled){
|
|
self.updateShiftCircle(id);
|
|
}
|
|
};
|
|
var onEnd = function(ev) {
|
|
if(!draggedData){
|
|
return
|
|
}
|
|
if(draggedData.type == 0){
|
|
var id = draggedData.id;
|
|
var towerData = self.towers[id];
|
|
var x = self.towers[id].raphObj[0].attr("cx");
|
|
var y = self.towers[id].raphObj[0].attr("cy");
|
|
if(x < x0 || x > x0 + w || y < y0 || y > y0 + h){
|
|
self.deleteTower(id);
|
|
return
|
|
}
|
|
towerData.x = x - x0;
|
|
towerData.y = y - y0;
|
|
var maxR = Math.max(Math.abs(towerData.x),Math.abs(towerData.x - w),Math.abs(towerData.y),Math.abs(towerData.y - h));
|
|
towerData.maxR = maxR;
|
|
self.distInfo[id].line.remove();
|
|
self.distInfo[id].val.remove();
|
|
self.distInfo[id] = null;
|
|
self.updateDistInfo(id);
|
|
}
|
|
if(dragEndCallback){
|
|
dragEndCallback();
|
|
}
|
|
};
|
|
|
|
this.deleteTower = function(id) {
|
|
this.towers[id].raphObj.remove();
|
|
delete this.towers[id];
|
|
this.distInfo[id].line.remove();
|
|
this.distInfo[id].val.remove();
|
|
delete this.distInfo[id];
|
|
var index = this.towerID.indexOf(id);
|
|
this.towerID.splice(index,1);
|
|
};
|
|
|
|
this.updateDistInfo = function(id) {
|
|
if(this.distInfo[id]){
|
|
this.distInfo[id].line.remove();
|
|
}
|
|
var data = this.towers[id];
|
|
var cx = data.x;
|
|
var cy = data.y;
|
|
var r = data.r;
|
|
var side = (cx > w/2) ? 0 : 1;
|
|
|
|
var x1 = (side) ? x0 + cx + towerR : x0 + cx - towerR;
|
|
var x2 = (side) ? x0 + cx + data.r : x0 + cx - data.r;
|
|
var line = paper.path("M"+x1+" "+(cy + y0)+",H"+x2).attr(attr.distLine);
|
|
|
|
var xVal = (x2 + x1)/2;
|
|
var yVal = y0 + cy - 15;
|
|
if(r < minR + 20){
|
|
yVal -= 20;
|
|
}
|
|
var valText = Math.round(data.r*scale)+" "+unit;
|
|
if(this.distInfo[id]){
|
|
this.distInfo[id].line = line;
|
|
this.distInfo[id].val.attr({
|
|
text: valText,
|
|
x: xVal,
|
|
y: yVal
|
|
});
|
|
}else{
|
|
var val = paper.text(xVal,yVal,valText).attr(attr.distVal);
|
|
this.distInfo[id] = { line: line, val: val };
|
|
}
|
|
};
|
|
|
|
this.updateShiftCircles = function() {
|
|
for(var id of this.towerID){
|
|
this.updateShiftCircle(id);
|
|
}
|
|
};
|
|
|
|
this.updateShiftCircle = function(id) {
|
|
var data = this.towers[id];
|
|
if(data.raphObj[3]){
|
|
data.raphObj[3].attr("r", Math.max(towerR,data.r + this.timeShift));
|
|
}
|
|
};
|
|
|
|
this.init();
|
|
}; |