emsApplication/applications/WebConfigure/web/js/bench.js

2639 lines
76 KiB
JavaScript
Raw Permalink Normal View History

2024-05-24 12:19:45 +08:00
var Bench ={
create:function(id, options) {
var bn = {};
//public vars
bn.dirty = false; //is config need be saved
bn.shapes = []; //all shape instances in svg
bn.symbols = []; //all shape's template(symbol)
bn.paper = null; //raphael core container object
bn.temp = {}; //all vars in temp object
bn.enablePan = true; //
//bn.realScale = 20; //unit : meter for rule calculation
bn.options = {};
///////// function init code here /////////
bn.init = function (domId) {
//fields
bn.id = domId;
bn.domId = "#" + domId; //div id
//bn.offset = offset; //size of screen not belong to svg element
//states
bn.mouseState = "default"; //mouse state: default/drawFloor....
//members
bn.getSize = function () {
//var w = $(bn.domId).width();
var w = $(document).width() - 491;
var h = $(window).height() - $(bn.domId).position().top ;
//var h = $(window).height() - $(bn.domId).offset().top + 117;
//h = $(bn.domId).prop('scrollHeight');
return { width: w, height: h };
};
//inner functions
function createPaper() {
var size =bn.getSize();
bn.paper =new Raphael(document.getElementById(bn.id),
size.width, size.height);
bn.paper.canvas.setAttribute('preserveAspectRatio', 'xMidYMid meet');
bn.paper.setViewBox(0, 0, size.width, size.height);
bn.resetSelection();
}
function enablePaperResize() {
$(window).resize(function () {
if (bn.temp.resizeTO) clearTimeout(bn.temp.resizeTO);
bn.temp.resizeTO = setTimeout(function () {
$(this).trigger('resizeEnd');
}, 300);
});
$(window).unbind('resizeEnd').bind('resizeEnd', function () {
//resize canvas
bn.paper.setSize(bn.getSize().width,
bn.getSize().height);
});
}
function defineMouseBehavior() {
bn.viewBoxWidth = bn.paper.width;
bn.viewBoxHeight = bn.paper.height;
var canvasID = bn.domId;
var startX, startY;
var mousedown = false;
var dX, dY;
var oX = 0, oY = 0, oWidth = bn.viewBoxWidth, oHeight = bn.viewBoxHeight;
bn.viewBox = bn.paper.setViewBox(oX, oY, bn.viewBoxWidth, bn.viewBoxHeight);
bn.viewBox.X = oX;
bn.viewBox.Y = oY;
function handleZoom(delta) {
if (delta < 0) {
bn.setZoom(0.95);
}
else {
bn.setZoom(1.05);
}
}
//Event handler for mouse wheel event.
function wheel(e) {
var event = e.originalEvent;
var delta = 0;
if (!event) /* For IE. */
event = window.event;
if (event.wheelDelta) { /* IE/Opera. */
delta = event.wheelDelta / 120;
} else if (event.detail) {
/** Mozilla case. */
delta = -event.detail / 3;
}
/** If delta is nonzero, handle it.
* Basically, delta is now positive if wheel was scrolled up,
* and negative, if wheel was scrolled down.
*/
if (delta) {
handleZoom(delta);
}
//Prevent default actions caused by mouse wheel
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
}
$(canvasID).unbind('mousewheel DOMMouseScroll').bind(
{'mousewheel DOMMouseScroll': wheel});
function updateWallPath(mx, my) {
var cp = bn.canvasPoint(mx, my);
if (bn.temp.wallCache) {
var twidth = Math.abs(cp.x - bn.temp.wallCache.lastX);
var theight = Math.abs(cp.y - bn.temp.wallCache.lastY);
if (twidth > theight) {
bn.temp.wallCache.lastX = cp.x;
bn.temp.wallCache.path += " H " + cp.x + " ";
}
else {
bn.temp.wallCache.lastY = cp.y;
bn.temp.wallCache.path += " V " + cp.y + " ";
}
}
else {
bn.temp.wallCache = {};
bn.temp.wallCache.ps = [];
bn.temp.wallCache.path = "M " + cp.x + " " + cp.y + " ";
bn.temp.wallCache.lastX = cp.x;
bn.temp.wallCache.lastY = cp.y;
}
var p = bn.addShape("pointIndicator",
{x: bn.temp.wallCache.lastX, y: bn.temp.wallCache.lastY});
bn.temp.wallCache.ps.push(p);
}
function panWindow(px, py) {
if (bn.mouseState === "pan")
$(canvasID).css('cursor', "url('/img/3d/hand-pull-lightblue.cur'), default");
dX = startX - px;
dY = startY - py;
var x = bn.viewBoxWidth / bn.paper.width;
var y = bn.viewBoxHeight / bn.paper.height;
dX *= x;
dY *= y;
bn.paper.setViewBox(bn.viewBox.X + dX, bn.viewBox.Y + dY, bn.viewBoxWidth, bn.viewBoxHeight, true);
}
function getDoorPosition(x, y) {
//find one wall
var els = [];
var elements = bn.paper.getElementsByPoint(x,y);
elements.forEach(function(el){
if (el.sym != undefined) els.push(el);
});
var pointRanges = [];
var range = 5;
while( range > 0)
{
pointRanges.push({ x1: x + range, y1: y});
pointRanges.push({ x1: x, y1: y + range});
pointRanges.push({ x1: x - range, y1: y});
pointRanges.push({ x1: x, y1: y - range});
range--;
}
var pts = [];
pointRanges.forEach(function(point){
var elements = bn.paper.getElementsByPoint(point.x1, point.y1);
pts = _.filter(elements, function (el) {
return el.sym !== undefined;
});
pts.forEach(function(ptsItem){
if (_.contains(els, ptsItem) !== true){
els.push(ptsItem);
}
});
});
var wps = _.filter(els, function (el) {
return el.sym.name === "floorPath" || el.sym.name === "wallPath";
});
//find multi-points
if (_.isUndefined(wps)) return;
if (wps.length == 0 ) return;
var positions = [];
wps.forEach(function(pt){
//get path points collection
var lastX, lastY;
var ptPoints = _.reduce(pt.realPath, function (ps, segment) {
var point = {};
if (segment[0] == "M") {
point.x = segment[1];
point.y = segment[2];
lastX = point.x;
lastY = point.y;
point.type = "M";
}
if (segment[0] == "H") {
point.x = segment[1];
point.y = lastY;
lastX = point.x;
point.type = "H";
}
if (segment[0] == "V") {
point.y = segment[1];
point.x = lastX;
lastY = point.y;
point.type = "V";
}
ps.push(point);
return ps;
}, []);
var position = _.reduce(ptPoints, function (pos, poi) {
if (pos.min > Math.abs(poi.x - x)) {
pos.min = Math.abs(poi.x - x);
pos.type = "X";
pos.x = poi.x;
pos.y = poi.y;
}
if (pos.min > Math.abs(poi.y - y)) {
pos.min = Math.abs(poi.y - y);
pos.type = "Y";
pos.x = poi.x;
pos.y = poi.y;
}
return pos;
}, {min: 99999999});
positions.push(position);
});
//find right points
var minPosition = _.min(positions, function(o){
return o.min;
});
return minPosition;
}
function updateWallShape() {
$(bn.domId).css('cursor', 'crosshair');
if (bn.temp.wallCache.line) {
bn.temp.wallCache.line.attr("path", bn.temp.wallCache.path);
}
else {
bn.temp.wallCache.line = bn.paper.path(bn.temp.wallCache.path);
bn.temp.wallCache.line.attr({
"type": "path",
"stroke": "#28a4c9",
"stroke-width": 40,
"stroke-linejoin": "round",
"stroke-linecap": "round",
"pointer-events": "all"
});
}
if (bn.temp.wallCache.ps.length == 3){
if (bn.currentSymbol.name == "floorPath"){
bn.selectDefaultSymbol();
}
}
}
function finishRuler(mx, my) {
var cp = bn.canvasPoint(mx, my);
if (!bn.temp.rule) {
bn.temp.rule = {};
bn.temp.rule.start = cp;
bn.temp.rule.startIndicator = bn.addShape("pointIndicator", cp);
} else {
var shp = bn.addShape("ruler", {start: bn.temp.rule.start, end: cp});
bn.temp.rule.startIndicator.delete();
bn.temp.rule = undefined;
mousedown = false;
bn.selectDefaultSymbol();
}
}
function prepareSelection(e){
var el = bn.paper.getElementByPoint(e.pageX, e.pageY);
if (bn.isSelectable(el)){
var shp = bn.getShapeByElement(el);
if (shp)
{
if (!shp.selected)
{
bn.resetSelection();
bn.setSelection(el);
}
bn.selection.one = true;
}
}
else {
//selection default 0;
bn.selection.one = false;
var p1 = bn.canvasPoint(e.pageX, e.pageY);
setMarquee(p1.x, p1.y, 0, 0);
bn.marquee.toFront();
}
}
$(canvasID).mousedown(function (e) {
//if (bn.paper.getElementByPoint(e.pageX, e.pageY) != null) {
// bn.resetSelection();
// bn.selectByClick(e);
// if (bn.mouseState !== "drawWall" &&
// bn.mouseState !== "drawWallPart" &&
// bn.mouseState !== "drawRuler" &&
// bn.mouseState !== "drawShape") return;
//}
if (bn.mouseState === "default") prepareSelection(e);
//common
mousedown = true;
startX = e.pageX;
startY = e.pageY;
//all situation can pan window
panWindow(e.pageX, e.pageY);
if (bn.mouseState === "drawWall") {
updateWallPath(e.pageX, e.pageY);
}
if (bn.mouseState == "drawRuler") {
finishRuler(e.pageX, e.pageY);
}
if (bn.mouseState == "drawShape"){
var sp = bn.addShape(bn.currentSymbol.name, bn.canvasPoint(e.pageX,e.pageY));
bn.shapes.forEach(function(shp){
if (shp.selected) {
shp.updateLook();
}
});
bn.resetSelection();
bn.setSelection(sp.element);
}
if (bn.mouseState === "drawWallPart") {
var cp = bn.canvasPoint(e.pageX, e.pageY);
var pos = getDoorPosition(cp.x, cp.y);
//var pos = getDoorPosition(e.clientX, e.clientY);
if (_.isUndefined(pos)) return;
var symbolName = bn.currentSymbol.name;
if (pos.min < 100) {
if (pos.type == "Y") {
bn.addShape(symbolName, {x: cp.x, y: pos.y - 15, type: pos.type});
}
else {
bn.addShape(symbolName, {x: pos.x - 15, y: cp.y, type: "X"});
}
}
}
});
function setMarquee(x, y, width, height) {
bn.marquee.attr({"x": x});
bn.marquee.attr({"y": y});
bn.marquee.attr({"width": width});
bn.marquee.attr({"height": height});
}
function updateSelection(e){
if (bn.selection.one) return;
if (bn.selectRect) return;
var p1 = bn.canvasPoint(startX, startY);
var p2 = bn.canvasPoint(e.pageX, e.pageY);
function Interval(lo, hi) {
this.lo = Math.min(lo, hi);
this.hi = Math.max(lo, hi);
}
Interval.prototype.contains = function(value) {
return this.lo <= value && value <= this.hi;
};
Interval.prototype.isOverlapping = function(that) {
return (
this.contains(that.lo) ||
this.contains(that.hi) ||
that.contains(this.lo) ||
that.contains(this.hi)
);
};
function inSelection(shape) {
var mBBox = bn.marquee.getBBox();
var sBBox = shape.element.getBBox();
var marqueeX = new Interval(mBBox.x, mBBox.x + mBBox.width);
var marqueeY = new Interval(mBBox.y, mBBox.y + mBBox.height);
var shapeX = new Interval(sBBox.x, sBBox.x + sBBox.width);
var shapeY = new Interval(sBBox.y, sBBox.y + sBBox.height);
return marqueeX.contains(shapeX.lo) &&
marqueeX.contains(shapeX.hi) &&
marqueeY.contains(shapeY.lo) &&
marqueeY.contains(shapeY.hi);
}
function selectShapes() {
bn.shapes.forEach(function(shape){
if (!bn.isSelectable(shape.element)) return;
if ( inSelection(shape) ) {
bn.setSelection(shape.element);
} else {
bn.removeSelection(shape);
}
});
}
bn.marquee.show();
setMarquee(
Math.min(p1.x, p2.x), Math.min(p1.y, p2.y),
Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y)
);
selectShapes();
}
$(canvasID).mousemove(function (e) {
if (mousedown == false) {
return;
}
if (bn.mouseState === "default") updateSelection(e);
if (bn.mouseState === "pan") panWindow(e.pageX, e.pageY);
});
function finishSelection()
{
setMarquee(0,0,0,0);
if (!bn.selection.one)
{
if (bn.selectRect)
{
bn.shapes.forEach(function(shp){
if (shp.selected) {
shp.updateLook();
}
});
bn.resetSelection();
}
else
{
if (bn.selection.length == 0) return;
var box = bn.selection.getBBox();
//console.log(box.x,box.y,box.width);
bn.selectRect = bn.paper.rect(box.x,box.y,box.width,box.height);
bn.selectRect.attr({fill: "green"});
bn.selectRect.attr({"fill-opacity": "0.2"});
bn.selectRect.attr({"stroke-opacity": "0.3"});
bn.selectRect.attr({"stroke-dasharray":"-"});
bn.selectRect.attr({stroke: "green"});
bn.selectRect.attr({"stroke-width": 10});
bn.selectRect.toFront();
bn.selectRect.draggable();
}
}
bn.selection.getBBox();
}
$(canvasID).mouseup(function (e) {
//common
if (mousedown == false) return;
bn.viewBox.X += dX;
bn.viewBox.Y += dY;
mousedown = false;
if (bn.mouseState === "default")
finishSelection();
var cp = bn.canvasPoint(e.pageX, e.pageY);
if (bn.mouseState === "drawWall") {
updateWallShape();
} else if (bn.mouseState === "drawRuler") {
if (bn.temp.rule) $(canvasID).css('cursor', 'crosshair');
} else if (bn.mouseState === "drawWallPart") {
$(canvasID).css('cursor', 'crosshair');
} else if (bn.mouseState === "drawShape"){
}
else {
$(canvasID).css('cursor', 'default');
}
});
}
function defineKeyBehavior() {
$(document).keyup(function (e) {
if (e.keyCode == 27) { // escape key maps to keycode `27`
if (bn.currentSymbol.handleKey)
bn.currentSymbol.handleKey("ESC");
}
if (e.keyCode == 46) {
bn.delete();
}
if (e.keyCode == 37) {
bn.move('left');
}
if (e.keyCode == 39){
bn.move('right');
}
if (e.keyCode == 38){
bn.move('up');
}
if (e.keyCode == 40){
bn.move('down');
}
});
$(document).keydown(function (e) {
if (e.keyCode == 37) {
bn.move('left');
}
if (e.keyCode == 39){
bn.move('right');
}
if (e.keyCode == 38){
bn.move('up');
}
if (e.keyCode == 40){
bn.move('down');
}
});
}
//actions
createPaper();
defineMouseBehavior();
defineKeyBehavior();
bn.selectDefaultSymbol();
enablePaperResize();
};
bn.clear = function () {
bn.temp = {}; //clear all temporary vars
bn.dirty = false; //set to default
bn.shapes = []; //clear shape instances
bn.paper.clear();
bn.resetSelection();
};
bn.load = function (config) {
bn.clear();
if (config) {
bn.loadConfig = config;
}
else {
bn.loadConfig = bn.demoConfig;
}
bn.setZoom(bn.loadConfig.editorZoom);
var loadShape = function(sp) {
var shp = bn.addShape(sp.param2D.symbol, sp.param2D);
if (shp) {
shp.config = sp;
shp.updateLook();
}
};
bn.loadConfig.shapes.forEach(function (shp) {
loadShape(shp);
});
bn.shapes.forEach(function (shp) {
if (shp.element.sym.name === "floorPath") return;
if (shp.element.sym.name === "floorImage") return;
shp.element.toFront();
});
bn.dirty = false;
};
bn.addShape = function (symbolName, param) {
var sym = _.find(bn.symbols, function (item) {
return item.name === symbolName;
});
if (_.isUndefined(sym)) return;
/*unique elements create by each symbols*/
var el = sym.create(param);
$(el).keyup(function(event) {
if (e.keyCode == 46) {
bn.delete();
}
});
el.sym = sym;
var shp = _.extend({}, bn.shapeClass);
shp.element = el;
bn.shapes.push(shp);
if (!shp.config) shp.newConfig();
shp.updateLook();
bn.dirty = true;
return shp;
};
bn.shapeMakeup = function (el, sym) {
//el.hover(function () {
// this.glowEffect = this.glow({color: "blue", width: 15});
//}, function () {
// this.glowEffect.remove();
//});
if (sym.class)
{
$(el.node).attr("class", sym.class);
}
if (sym.style)
{
for(var a in sym.style)
{
el.attr(a, sym.style[a]);
}
}
if (sym.class !== "floorPath")
el.draggable();
return el;
};
bn.selectSymbol = function (sym) {
if (bn.currentSymbol) {
if (bn.currentSymbol.endState)
bn.currentSymbol.endState();
}
bn.mouseState = sym.mouseState;
bn.currentSymbol = sym;
if (sym.initState) sym.initState();
//update cursor & mouseState for common purpose
$(bn.domId).css('cursor', 'auto');
if (sym.cursor) $(bn.domId).css('cursor', sym.cursor);
bn.update();
};
bn.selectDefaultSymbol = function () {
bn.selectSymbol(bn.symbols[0]);
};
bn.findShapeBySymbolName = function (name) {
var sps = _.filter(bn.shapes, function (shp) {
return shp.element.sym !== undefined;
});
return _.find(sps, function (shp) {
return shp.element.sym.name === name;
});
};
bn.setZoom = function (zoom){
var vBHo = bn.viewBoxHeight;
var vBWo = bn.viewBoxWidth;
var vX = bn.viewBox.X;
var vY = bn.viewBox.Y;
bn.viewBoxWidth *= zoom;
bn.viewBoxHeight *= zoom;
bn.viewBox.X -= (bn.viewBoxWidth - vBWo) / 2;
bn.viewBox.Y -= (bn.viewBoxHeight - vBHo) / 2;
//bn.viewBox.X = zoom * vX;
//bn.viewBox.Y = zoom * vY;
bn.paper.setViewBox(bn.viewBox.X, bn.viewBox.Y, bn.viewBoxWidth, bn.viewBoxHeight, true);
};
bn.setSelection = function (el) {
el.attr({"stroke": "#8ADBB2"});
el.attr({"fill": "#74ED34"});
el.attr({"fill-opacity": "0.7"});
el.attr({"stroke-opacity": "0.7"});
var exist = false;
if (bn.selection) {
bn.selection.forEach(function (e) {
if (e === el) exist = true;
});
if (!exist)
{
if (el.sym) bn.selection.push(el);
}
bn.getShapeByElement(el).selected = true;
//bn.selection.draggable();
//console.log(bn.selection);
var selectedShapes = [];
bn.selection.forEach(function (e) {
selectedShapes.push(bn.getShapeByElement(e));
});
bn.ev("shapeSelected", selectedShapes);
}
};
bn.isSelectable = function(el){
if (el == null) return false;
if (el === bn.selectRect) return true;
if (_.isUndefined(el.sym)) return false;
if (el.sym.name === "floorPath") return false;
if (el.sym.name === "floorImage") return false;
return true;
};
bn.resetSelection = function (){
var selectedShapes = [];
if (bn.shapes) {
bn.shapes.forEach(function (shp) {
if (shp.selected) selectedShapes.push(shp);
});
bn.ev("resetShape", selectedShapes);
}
if (_.isUndefined(bn.marquee))
bn.marquee = bn.paper.rect(0, 0, 0, 0);
{
bn.marquee = bn.paper.rect(0, 0, 0, 0);
bn.marquee.attr({fill: "none"});
bn.marquee.attr({"stroke-dasharray":"-"});
bn.marquee.attr({stroke: "green"});
bn.marquee.attr({"stroke-width": 10});
bn.marquee.toFront();
}
bn.selection = bn.paper.set();
if (bn.selectRect) {
bn.selectRect.remove();
bn.selectRect = undefined ;
}
bn.shapes.forEach(function(shp){
shp.resetStyle();
shp.selected = false;
});
};
bn.getShapeByElement = function(el){
var res = null;
bn.shapes.forEach(function(shp){
if (shp.element === el) res = shp;
});
return res;
};
bn.removeSelection = function (shape){
shape.resetStyle();
shape.selected = false;
bn.selection.exclude(shape.element);
};
bn.save = function (){
//get floor calc center2D for 3d config position update
var floor = _.find(bn.shapes, function(shp){
return shp.element.sym.name == "floorPath";
});
if (floor) floor.element.sym.calcCenter(floor.element);
bn.loadConfig.shapes.length = 0;
bn.shapes.forEach(function(shp){
shp.updateConfig();
bn.loadConfig.shapes.push(shp.config);
});
bn.uploadConfig(bn.loadConfig);
//bn.demoConfig = bn.loadConfig;
//bn.info(angular.toJson(bn.loadConfig));
bn.dirty = false;
};
bn.newConfig = function(){
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var prompt = languageJson.Room3D.Edit.Prompt;
var nc = {
"name": "new floor",
"title": prompt.Room,
"description": prompt.Note,
"version": "0.0.1",
"editorZoom": 1,
"shapes":[]
};/*"新机房" "备注请放在这里"*/
bn.load(nc);
};
bn.canvasPoint = function (pageX, pageY) {
var rX = pageX - $(bn.domId).position().left;
var rY = pageY - $(bn.domId).position().top;
var x = bn.viewBoxWidth / bn.paper.width;
var y = bn.viewBoxHeight / bn.paper.height;
var tX = bn.viewBox.X + rX * x;
var tY = bn.viewBox.Y + rY * y;
return {x: tX, y: tY};
};
bn.delete = function(){
if (bn.selection.length == 0) return;
var needremoves = [];
bn.shapes.forEach(function(shape){
if (shape.selected) needremoves.push(shape);
});
needremoves.forEach(function(shp){
shp.delete();
});
};
bn.align = function(type){
if (bn.selection.length < 2) return;
if (type == "left"){
var leftElement = _.min(bn.selection, function(el){
var box = el.getBBox();
return box.x;
});
var leftPosition = leftElement.getBBox().x;
bn.selection.forEach(function(el){
var offset = leftPosition - el.getBBox().x;
var shp = bn.getShapeByElement(el);
//el.nt_translate(offset,0);
shp.translate(offset,0);
});
}
if (type == "hcenter"){
var ec = bn.selection.length;
var sy = 0;
bn.selection.forEach(function(el){
sy = sy + el.getBBox().y;
});
var mid = sy/ec;
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
var offset = mid - el.getBBox().y;
//el.nt_translate(0, offset);
shp.translate(0,offset);
});
}
if (type == "right"){
var rightElement = _.max(bn.selection, function(el){
var box = el.getBBox();
return box.x;
});
var rightPosition = rightElement.getBBox().x + rightElement.getBBox().width;
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
var offset = rightPosition - el.getBBox().x - el.getBBox().width;
shp.translate(offset, 0);
//el.nt_translate(offset, 0);
});
}
if (type == "top"){
var topElement = _.min(bn.selection, function(el){
return el.getBBox().y;
});
var topPosition = topElement.getBBox().y;
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
var offset = topPosition - el.getBBox().y;
//el.nt_translate(0,offset);
shp.translate(0,offset);
});
}
if (type == "vcenter"){
var ec = bn.selection.length;
var sx = 0;
bn.selection.forEach(function(el){
sx = sx + el.getBBox().x;
});
var mid = sx/ec;
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
var offset = mid - el.getBBox().x;
//el.nt_translate(offset,0);
shp.translate(offset, 0);
});
}
if (type == "bottom"){
var bottomElement = _.max(bn.selection, function(el){
var box = el.getBBox();
return box.y;
});
var bottomPosition = bottomElement.getBBox().y + bottomElement.getBBox().height;
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
var offset = bottomPosition - el.getBBox().y - el.getBBox().height;
//el.nt_translate(0,offset);
shp.translate(0,offset);
});
}
bn.dirty = true;
};
bn.spacing = function(type){
if (bn.selection.length < 2) return;
if (type == "h"){
var leftElement = _.min(bn.selection, function(el){
var box = el.getBBox();
return box.x;
});
var leftPosition = leftElement.getBBox().x;
var ar = _.sortBy(bn.selection, function(el){
return -(leftPosition - el.getBBox().x); });
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var prompt = languageJson.Room3D.Edit.Prompt;
/*"请输入物体间隔距离(cm)"*/
bn.input(prompt.Distance,0,languageJson.InputBox).then(function(data){
if (data.result){
var interval = parseFloat(data.val);
var leftSpace = 0;
ar.forEach(function(el){
el.nt_translate(leftPosition - el.getBBox().x,0);
el.nt_translate(leftSpace,0);
leftSpace = leftSpace + el.getBBox().width + interval;
});
}
});
}
if (type == "v"){
var topElement = _.min(bn.selection, function(el){
var box = el.getBBox();
return box.y;
});
var topPosition = topElement.getBBox().y;
var ar = _.sortBy(bn.selection, function(el){
return -(topPosition - el.getBBox().y); });
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var prompt = languageJson.Room3D.Edit.Prompt;
/*"请输入物体间隔距离(cm)"*/
bn.input(prompt.Distance,0,languageJson.InputBox).then(function(data){
if (data.result){
var interval = parseFloat(data.val);
var topSpace = 0;
ar.forEach(function(el){
el.nt_translate(0, topPosition - el.getBBox().y);
el.nt_translate(0, topSpace);
topSpace = topSpace + el.getBBox().height + interval;
});
}
});
}
bn.dirty = true;
};
bn.copy = function(){
if (bn.selection.length == 0) return;
var copyitems = [];
bn.selection.forEach(function(el){
var shp = bn.getShapeByElement(el);
if (shp) copyitems.push(shp.clone());
});
bn.resetSelection();
copyitems.forEach(function(shp){
bn.shapes.push(shp);
bn.setSelection(shp.element);
});
var box = bn.selection.getBBox();
bn.selectRect = bn.paper.rect(box.x,box.y,box.width,box.height);
bn.selectRect.attr({fill: "green"});
bn.selectRect.attr({"fill-opacity": "0.2"});
bn.selectRect.attr({"stroke-opacity": "0.3"});
bn.selectRect.attr({"stroke-dasharray":"-"});
bn.selectRect.attr({stroke: "green"});
bn.selectRect.attr({"stroke-width": 10});
bn.selectRect.toFront();
bn.selectRect.draggable();
bn.dirty = true;
};
bn.move = function(type){
if (bn.selection.length < 1) return;
if (type == "left"){
bn.selection.forEach(function(el){
bn.getShapeByElement(el).translate(-1,0);
//el.nt_translate(-1,0);
});
}
if (type == "right"){
bn.selection.forEach(function(el){
bn.getShapeByElement(el).translate(1,0);
//el.nt_translate(1,0);
});
}
if (type == "up"){
bn.selection.forEach(function(el){
bn.getShapeByElement(el).translate(0,-1);
//el.nt_translate(0,-1);
});
}
if (type == "down"){
bn.selection.forEach(function(el){
bn.getShapeByElement(el).translate(0,1);
//el.nt_translate(0,1);
});
}
bn.dirty = true;
};
bn.toBack = function(){
//if (bn.selection.length < 1) return;
bn.selection.forEach(function(el){
el.toBack();
});
//floor and image can not select, so it's must be at bottom.
var floor = _.find(bn.shapes, function(shp){
return shp.element.sym.name == "floorPath";
});
if (floor) floor.element.toBack();
var floorImage = _.find(bn.shapes, function(shp){
return shp.element.sym.name == "floorImage";
});
if (floorImage) floorImage.element.toBack();
};
bn.toFront = function(){
if (bn.selection.length < 1) return;
bn.selection.forEach(function(el){
el.toFront();
});
};
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var edit = languageJson.Room3D.Edit;
bn.symbols = [
{
name: "cursor",
title: edit.Cursor,/*"选择"*/
tip: edit.CursorPrompt,/*"选中物体,可操作各种物体"*/
icon: "/img/3d/cursor.png",
mouseState: "default",
cursor: "default",
visible: true,
initState: function(){
}
},
{
name: "pan",
title: edit.Pan,/*"移动"*/
tip: edit.PanPrompt,/*"拖动移动画布"*/
icon: "/img/3d/move.png",
mouseState: "pan",
cursor: "default",
visible: true,
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
initState: function(){
}
},
{
name: "pointIndicator",
title: edit.Point,/*"点"*/
tip: edit.PointPrompt,/*"鼠标点击提示"*/
visible: false,
class: "pointIndicator",
props: {
radius: 60
},
create: function (param) {
return bn.shapeMakeup(bn.paper.circle(param.x, param.y, this.props.radius), this);
}
},
{
name: "floorImage",
title: edit.FloorImage,/*"地板底图"*/
tip: edit.ImagePrompt,/*"用来做地板衬底方便绘制"*/
type: "part",
elementType: "path",
scale: 1,
tempParam: null,
create: function (param) {
var cp = bn.getSize();
var fx = (cp.width - param.width) / 2;
var fy = (cp.height - param.height) / 2;
var el = bn.paper.image(param.src, fx, fy, param.width, param.height);
// if (param.scale)
// {
// el.scale(param.scale,param.scale);
// this.scale = param.scale;
// }
return el;
},
updateScale: function(element, realSize, rulerLength){
var x = bn.viewBoxWidth / bn.paper.width;
this.scale = (100 * realSize) / (rulerLength);
//var y = bn.viewBoxHeight / bn.paper.height;
element.scale(this.scale,this.scale);
this.tempParam = {
width : element.getBBox().width,
height : element.getBBox().height
};
},
update3DConfig: function(element, config){
delete config['param3D'];
},
update2DConfig: function(element, config){
_.extend(config.param2D , this.tempParam);
//config.param2D = this.tempParam;
config.param2D.scale = this.scale;
},
},
{
name: "ruler",
title: edit.Ruler,/*"标尺"*/
tip: edit.RulerPrompt,/*"标尺状态: 标记地板底图尺寸用于缩放底图到适当大小"*/
icon: "/img/3d/ruler.png",
mouseState: "drawRuler",
cursor: "crosshair",
visible: true,
class: "rulerPath",
props:{
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
create: function (param) {
var line = bn.paper.path(["M", param.start.x, param.start.y,
"L", param.end.x, param.end.y]);
return bn.shapeMakeup(line, this);
},
initState: function () {
var ruler = bn.findShapeBySymbolName("ruler");
if (ruler) {
/*"此操作将删除已经存在的标尺比例,重新计算底图缩放比例,是否继续?"*/
bn.confirm(edit.Prompt.RulerConfirm,languageJson.ConfirmBox).then(function (data) {
if (data === true) {
ruler.delete();
var imgElement =bn.findShapeBySymbolName("floorImage").element;
imgElement.transform("");
}
if (data === false) bn.selectDefaultSymbol();
});
}
},
endState: function () {
var ruler = bn.findShapeBySymbolName("ruler");
if (ruler) {
/*"请输入该线段对应实际长度,单位:米"*/
bn.input(edit.Prompt.RulerInput,"0",languageJson.InputBox).then(function (data) {
if (data.result){
var v = parseFloat(data.val);
if (v <= 0 || v > 9999)
{
/*"输入的尺寸不正确, 请重新绘制"*/
bn.info(edit.Prompt.RulerInfo,languageJson.MessageBox);
ruler.delete();
return;
}
var imgElement =bn.findShapeBySymbolName("floorImage").element;
imgElement.sym.updateScale(imgElement, v,
ruler.element.getTotalLength());
}
ruler.delete();
});
}
},
update3DConfig: function(element, config){
delete config['param3D'];
},
update2DConfig: function(element, config){
config.param2D.start = {};
config.param2D.start.x = element.getBBox().x;
config.param2D.start.y = element.getBBox().y;
config.param2D.end = {};
config.param2D.end.x = element.getBBox().x + element.getBBox().width;
config.param2D.end.y = element.getBBox().y + element.getBBox().height;
}
},
{
name: "floorPath",
title: edit.FloorPath,/*"地板"*/
tip: edit.PathPrompt,/*"画地板状态: 画矩形封闭区域,点三点形成矩形"*/
icon: "/img/3d/Floor2.png",
mouseState: "drawWall",
cursor: "crosshair",
unit: "floor",
moldId:"wallpath-default",
visible: true,
style:{
"stroke":"#28a4c9",
"stroke-width":"40",
"stroke-linejoin":"round",
"stroke-linecap": "round",
"pointer-events": "all",
"fill-opacity":"0.5",
"fill":"#b9def0"
},
create: function (param) {
return bn.shapeMakeup(bn.paper.path(param.path), this);
},
update: function(cfg, element){
var mold = _.find(molds, function(m){
return m.id == cfg.param3D.moldId; });
if (cfg.param2D.angle) element.animate({
transform:"r" + cfg.param2D.angle }, 500);
element.animate({"stroke-width": mold.size.width }, 500);
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
endState: function (){
if (_.isUndefined(bn.temp.wallCache)) return;
if (_.isUndefined(bn.temp.wallCache.ps)) return;
bn.temp.wallCache.ps.forEach(function(shp){
shp.delete();
});
//因为只能绘制矩形地板的原因需对结果Path进行计算
//只能点3个点用直角折线形成精确的第三点并封闭来构成真正的矩形
var startPoint = {};
var endSegment = "";
var index = 0;
var floorLine = _.reduce(bn.temp.wallCache.line.attrs.path, function (ps, segment) {
if (index == 3) return ps;
index ++;
if (segment[0] == "M") {
ps = "M " + segment[1] + " " + segment[2];
startPoint.x = segment[1];
startPoint.y = segment[2];
}
if (segment[0] == "H") {
ps = ps + " H " + segment[1];
if (index == 3) endSegment = " V " + startPoint.y + " Z ";
}
if (segment[0] == "V") {
ps = ps + " V " + segment[1];
if (index == 3) endSegment = " H " + startPoint.x + " Z ";
}
return ps;
}, "");
if (index == 3) floorLine = floorLine + endSegment;
//console.log(floorLine);
var shp = bn.addShape("floorPath", {path: floorLine});
bn.toBack();
bn.temp.wallCache.line.remove();
bn.temp.wallCache = undefined;
//this.update2DConfig(shp.element, shp.config);
//this.update3DConfig(shp.element. shp.config);
},
calcCenter: function(element){
var fp = element;
if (fp) {
var ps = fp.attr("path");
var w, h;
var sx,sy,mx,my;
var sx = parseFloat(ps[0][1]);
var sy = parseFloat(ps[0][2]);
if (ps[1][0] === "H")
mx = parseFloat(ps[1][1]);
else
mx = parseFloat(ps[2][1]);
if (ps[1][0] === "V")
my = parseFloat(ps[1][1]);
else
my = parseFloat(ps[2][1]);
}
w = Math.abs(mx - sx);
h = Math.abs(my - sy);
bn.center2D = {};
bn.center2D.x = sx + w / 2;
bn.center2D.y = sy + h / 2;
},
initState: function(){
bn.enablePan = false;
var fp = bn.findShapeBySymbolName("floorPath");
if (fp) {
/*"地板只允许有一个,确定重新绘制?"*/
bn.confirm(edit.Prompt.FloorConfirm,languageJson.ConfirmBox).then(function (data) {
if (data === true) {
fp.delete();
}
else
bn.selectDefaultSymbol();
});
}
else{
/*"点击三个点形成直角折线来自动形成矩形地板"*/
bn.info(edit.Prompt.FloorInfo,languageJson.MessageBox);
}
},
update2DConfig: function(element, config){
//todo: when moved all path string changed to 'c'
config.param2D.path = element.attr("path").toString();
},
update3DConfig: function(element, config) {
config.param3D.floorTexture = "/img/3d/floor05.png";
var fp = element;
if (fp) {
var ps = fp.attr("path");
var w, h;
var sx,sy,mx,my;
var sx = parseFloat(ps[0][1]);
var sy = parseFloat(ps[0][2]);
if (ps[1][0] === "H")
mx = parseFloat(ps[1][1]);
else
mx = parseFloat(ps[2][1]);
if (ps[1][0] === "V")
my = parseFloat(ps[1][1]);
else
my = parseFloat(ps[2][1]);
}
w = Math.abs(mx - sx);
h = Math.abs(my - sy);
config.param3D.floorWidth = w;
config.param3D.floorHeight = h;
bn.center2D = {};
bn.center2D.x = sx + w / 2;
bn.center2D.y = sy + h / 2;
}
},
{
name: "wallPath",
title: edit.WallPath,/*"墙壁"*/
tip: edit.WallPrompt,/*"画墙状态:鼠标点击画墙等折线路径物体"*/
icon: "/img/3d/wall.png",
mouseState: "drawWall",
unit: "wallPath",
moldId:"wallpath-default",
cursor: "crosshair",
visible: true,
style:{
"stroke":"#28a4c9",
"stroke-width":"40",
"stroke-linejoin":"round",
"stroke-linecap": "round",
"pointer-events": "all",
"fill-opacity":"0.5",
"fill":"#b9def0"
},
update: function(cfg, element){
var mold = _.find(molds, function(m){
return m.id == cfg.param3D.moldId; });
if (cfg.param2D.angle) element.animate({
transform:"r" + cfg.param2D.angle }, 500);
element.animate({"stroke-width": mold.size.width }, 500);
},
create: function (param) {
//this.linePath = param.path;
return bn.shapeMakeup(bn.paper.path(param.path), this);
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
endState: function (){
if (_.isUndefined(bn.temp.wallCache)) return;
if (_.isUndefined(bn.temp.wallCache.ps)) return;
bn.temp.wallCache.ps.forEach(function(shp){
shp.delete();
});
bn.addShape("wallPath", bn.temp.wallCache);
bn.temp.wallCache.line.remove();
bn.temp.wallCache = undefined;
},
update2DConfig: function(element, config){
if (config.param2D.pathArray)
{
var oldPath = bn.paper.path(config.param2D.pathArray.toString());
// var pathOffset = {
// x: element.getBBox().x - oldPath.getBBox().x,
// y: element.getBBox().y - oldPath.getBBox().y
// };
// var newX = parseFloat(element.realPath[0][1]) + pathOffset.x;
// var newY = parseFloat(element.realPath[0][2]) + pathOffset.y;
var pathNew = oldPath.attrs.path.slice(0);
pathNew[0][1] = element.getBBox().x;
pathNew[0][2] = element.getBBox().y;
config.param2D.path = pathNew.toString();
config.param2D.pathArray = pathNew;
oldPath.remove();
}
else if (element.attrs.path){
config.param2D.path = element.attrs.path.toString();
config.param2D.pathArray = element.attrs.path;
}
},
update3DConfig: function(element, config){
var ps = config.param2D.pathArray;
var lines = bn.util.get3DLinesBySegments(ps, 10);
config.param3D.lines = lines;
}
},
{
name: "door",
title: edit.Door,/*"门窗"*/
tip: edit.DoorPrompt,/*"画门窗状态:在墙上鼠标点击的位置放置门窗"*/
icon: "/img/3d/door.png",
mouseState: "drawWallPart",
unit: "door",
moldId:"door-default",
visible: true,
cursor:"crosshair",
style:{
"fill": "#FF8080"
},
props: {
width: 190,
height: 30
},
create: function (param) {
var rect;
if (param.type === "Y") {
rect = bn.paper.rect(param.x, param.y, this.props.width, this.props.height);
}
else {
rect = bn.paper.rect(param.x, param.y, this.props.height, this.props.width);
}
return bn.shapeMakeup(rect, this);
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
update: function(cfg, element){
var mold = _.find(molds, function(m){
return m.id == cfg.param3D.moldId; });
if (cfg.param2D.angle) element.animate({
transform:"r" + cfg.param2D.angle }, 500);
if (element.attrs.width > element.attrs.height)
{
element.animate({
width:mold.size.width,
height:mold.size.depth
}, 500);
}
else
{
element.animate({
width:mold.size.depth,
height:mold.size.width
}, 500);
}
},
update2DConfig: function(element, config){
config.param2D.x = element.getBBox().x;
config.param2D.y = element.getBBox().y;
if (element.attrs.width > element.attrs.height)
config.param2D.type = "Y";
else
config.param2D.type = "X";
},
update3DConfig: function(element, config){
var c = bn.util.boxCenter(element);
config.param3D.position = bn.util.Point3D(c);
config.param3D.position.y = parseFloat(config.param3D.aboveGround);
if (element.attrs.width > element.attrs.height)
config.param3D.direct = "X";
else
config.param3D.direct = "Z";
}
},
{
name: "rack",
title: edit.Rack,/*"机架"*/
tip: edit.RackPrompt,/*"放置机架等盒状物体"*/
icon: "/img/3d/rack.jpg",
cursor:"url('/img/3d/object.cur'), default",
mouseState: "drawShape",
visible: true,
unit: "rack",
moldId:"rack-default",
style:{
"fill": "blue",
"fill-opacity":"0.5",
"stroke": "#437ded",
"stroke-width":10,
"pointer-events":"all"
},
props: {
width: 70,
depth: 100,
height: 220
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
create: function (param) {
var rect = bn.paper.rect(param.x, param.y,
this.props.width, this.props.depth);
return bn.shapeMakeup(rect, this);
},
update: function(cfg, element){
var mold = _.find(molds, function(m){
return m.id == cfg.param3D.moldId; });
if (cfg.param2D.angle) element.animate({
transform:"R" + cfg.param2D.angle }, 600);
element.animate({
width:mold.size.width,
height:mold.size.depth
}, 500);
},
update2DConfig: function(element, config){
//element.animate({transform:""}, 10);
config.param2D.x = element.attrs.x;
config.param2D.y = element.attrs.y;
},
update3DConfig: function(element, config){
var c = bn.util.boxCenter(element);
config.param3D.position = bn.util.Point3D(c);
}
},
//{
// name: "camera",
// title: "摄像头",
// tip: "放置摄像头在鼠标点击位置",
// icon: "/img/3d/camera.jpg",
// cursor:"url('/img/3d/object.cur'), default",
// mouseState: "drawShape",
// visible: true,
// style:{
// "stroke": "#ed4f44",
// "stroke-width":"10",
// "fill-opacity":"0.5",
// "fill":"red"
// },
// props: {
// radius: 30
// },
// handleKey : function (key){
// if (key === "ESC"){
// bn.selectDefaultSymbol();
// }
// },
// create: function (param) {
// return bn.shapeMakeup(bn.paper.circle(param.x, param.y, this.props.radius), this);
// },
// update2DConfig: function(element, config){
// config.param2D.x = element.getBBox().x;
// config.param2D.y = element.getBBox().y;
// },
// update3DConfig: function(element, config){
// config.param3D = {
// "unit": "camera",
// "angle": 0,
// "high": 300,
// "position":{x:0,y:0,z:0}
// };
// var c = bn.util.boxCenter(element);
// config.param3D.position = bn.util.Point3D(c);
// config.param3D.position.y = config.param3D.high;
// }
//},
{
name: "flat",
title: edit.Flat,/*"装饰"*/
tip: edit.FlatPrompt,/*"放置平面图形到3D画布"*/
icon: "/img/3d/plant.png",
cursor:"url('/img/3d/object.cur'), default",
mouseState: "drawShape",
unit:"flat",
moldId: "flat-default",
visible: true,
style:{
"stroke": "#ed4fee",
"stroke-width":"10",
"fill-opacity":"0.5",
"fill":"yellow"
},
props:{
"width":"100",
"depth":"100"
},
handleKey : function (key){
if (key === "ESC"){
bn.selectDefaultSymbol();
}
},
create: function (param) {
var rect = bn.paper.rect(param.x, param.y,
this.props.width, this.props.width);
return bn.shapeMakeup(rect, this);
},
update2DConfig: function(element, config){
config.param2D.x = element.getBBox().x;
config.param2D.y = element.getBBox().y;
config.param2D.width = element.getBBox().width;
},
update: function(cfg, element){
var mold = _.find(molds, function(m){
return m.id == cfg.param3D.moldId; });
element.animate({
width:mold.size.width,
height:mold.size.width
}, 500);
},
update3DConfig: function(element, config){
var c = bn.util.boxCenter(element);
config.param3D.position = bn.util.Point3D(c);
config.param3D.position.y = config.param3D.high;
}
}
];
bn.shapeClass = {
newConfig:function(){
var that = this;
if (!this.config)
{
this.config = {};
this.config.name = this.element.sym.name;
this.config.title = this.element.sym.title;
this.config.param2D = {};
this.config.param2D.symbol = this.element.sym.name;
this.config.param2D.angle = 0;
this.config.param3D = {};
this.config.param3D.unit = this.element.sym.unit;
this.config.param3D.moldId = this.element.sym.moldId;
this.config.param3D.angle = 0;
this.config.param3D.aboveGround = 0;
this.config.param3D.bindings = [];
}
this.config.id = this.element.id;
},
getBindingTitle:function(){
if (!this.config.param3D.bindings) return "无";
var str = "<ul>";
this.config.param3D.bindings.forEach(function(item){
str = str + "<li>" + item.title + "</li>";
});
var str = str + "</ul>";
},
translate:function(dx,dy){
if (this.element.matrix.split().rotate)
{
this.element.transform('');
}
this.element.nt_translate(dx,dy);
this.updateLook();
},
updateLook:function(){
if (this.element.sym)
{
if (this.element.sym.update){
this.element.sym.update(this.config, this.element);
}
}
},
updateConfig:function(){
var that = this;
if (that.element.sym)
{
if (that.element.sym.update2DConfig)
that.element.sym.update2DConfig(that.element,that.config);
if (that.element.sym.update3DConfig)
that.element.sym.update3DConfig(that.element,that.config);
}
},
delete:function(){
bn.shapes = _.without(bn.shapes, this);
if (this.element.glowEffect)
this.element.glowEffect.remove();
this.element.remove();
bn.proofer.resetUI();
bn.resetSelection();
bn.dirty = true;
},
resetStyle:function(){
var that = this;
if (that.element.sym.style)
{
for(var a in that.element.sym.style)
{
if (a == "stroke-width" && that.element.sym.name == "wallPath") continue;
that.element.attr(a, that.element.sym.style[a]);
}
}
},
clone:function(){
var that = this;
var ns = _.extend({}, that);
ns.config = angular.fromJson(angular.toJson(that.config));
ns.element = that.element.clone();
ns.config.id = that.element.id;
ns.element.sym = _.extend({}, that.element.sym);
ns.selected = that.selected;
if (that.element.sym.class !== "floorPath")
ns.element.draggable();
return ns;
}
};
bn.util = {};
bn.util.Point3D = function(point2D){
var p ={};
if (bn.center2D)
{
p.x = point2D.x - bn.center2D.x;
p.z = point2D.y - bn.center2D.y;
}
else{
p.x = point2D.x;
p.z = point2D.y;
}
return p;
};
bn.util.boxCenter = function(el){
var box = el.getBBox();
var p = {x: box.x + box.width / 2 , y:box.y + box.height / 2};
return p;
};
bn.util.get3DLinesBySegments = function (segs, y) {
var lastX, lastY;
var lines = [];
var parr = _.reduce(segs, function (ps, segment) {
var point = {};
if (segment[0] == "M") {
point.x = parseFloat(segment[1]);
point.y = parseFloat(segment[2]);
lastX = point.x;
lastY = point.y;
}
if (segment[0] == "H") {
point.x = parseFloat(segment[1]);
point.y = lastY;
lastX = point.x;
}
if (segment[0] == "V") {
point.y = parseFloat(segment[1]);
point.x = lastX;
lastY = point.y;
}
var p3 = bn.util.Point3D(point);
p3.y = parseFloat(y);
var startPoint = ps[ps.length - 1];
if (startPoint)
{
var line = {
start: startPoint,
end: p3
};
lines.push(line);
}
ps.push(p3);
return ps;
}, []);
return lines;
};
bn.proofer = {
showSettings: function(shapes, setting){
//single:
if (_.isUndefined(shapes)) return;
bn.proofer.shapes = shapes;
bn.proofer.setting = setting;
if (shapes.length == 1){
var shp = shapes[0];
if (!shp.config) shp.newConfig();
setting.title = shp.config.title;
setting.angle = shp.config.param2D.angle;
setting.aboveGround = shp.config.param3D.aboveGround;
setting.molds = this.getMolds(shp.element.sym.name);
setting.mold = _.find(setting.molds,
function(m){ return m.id == shp.config.param3D.moldId; });
setting.bindings = shp.config.param3D.bindings;
}
if (shapes.length > 1){
var allSame = true; var ns = [];
ns.push(shapes[0].element.sym.name);
shapes.forEach(function(shp){
if (!_.contains(ns, shp.element.sym.name))
allSame = false;
});
if (allSame){
setting.molds = this.getMolds(shapes[0].element.sym.name);
}
else
setting.molds = undefined;
setting.title = undefined;
setting.angle = undefined;
setting.aboveGround = undefined;
setting.mold = undefined;
setting.bindings = [];
}
},
resetUI: function(){
if (bn.proofer.setting){
bn.proofer.setting.molds = undefined;
bn.proofer.setting.title = undefined;
bn.proofer.setting.angle = undefined;
bn.proofer.setting.aboveGround = undefined;
bn.proofer.setting.mold = undefined;
bn.proofer.setting.bindings = [];
}
},
getMolds: function(symbolName){
var ms = [];
molds.forEach(function(m){
if (m.name === symbolName) ms.push(m);
});
return ms;
},
saveShapes: function(shapes, setting){
if (shapes.length == 1){
var shp = shapes[0];
if (shp.config)
{
shp.config.title = setting.title;
shp.config.param2D.angle = parseFloat(setting.angle);
shp.config.param3D.angle = parseFloat(setting.angle);
shp.config.param3D.moldId = setting.mold.id;
shp.config.param3D.aboveGround = parseFloat(setting.aboveGround);
shp.config.param3D.bindings = setting.bindings;
shp.updateLook();
}
}
if (shapes.length > 1){
var allSame = true; var ns = [];
ns.push(shapes[0].element.sym.name);
shapes.forEach(function(shp){
if (!_.contains(ns, shp.element.sym.name))
allSame = false;
});
shapes.forEach(function(shp){
if (setting.title)
shp.config.title = setting.title;
if (setting.angle)
{
shp.config.param2D.angle = parseFloat(setting.angle);
shp.config.param3D.angle = parseFloat(setting.angle);
}
if (allSame){
if (setting.mold){
shp.config.param3D.moldId = setting.mold.id;
}
}
if (setting.aboveGround)
shp.config.param3D.aboveGround = parseFloat(setting.aboveGround);
shp.updateLook();
});
}
},
//rend: function(shapes, setting){
//
// //when focus lose or save, save config to shape
// this.updateShapes(shapes,setting);
//
// //3 load proof by shape's mold define
// //4 user can use set in template or modify it
// //multiple:
// //1 if shape's symbol is same, they can change style (not binding)
// //2 when focus lose or save, save copied config to each shape
//},
proofs:[
{
type:"rack",
load: function(shape, setting){
},
save: function(shape, setting){
}
}
]
};
(function(R) {
R.el.draggable = function(move, start, up) {
this._ui = this._ui || {};
var that = this;
this._ui.onMove = R.is(move, 'function') ?
move : function(distanceX, distanceY, x, y, deltaX, deltaY) {
if (that.sym){
if (that.sym.name == "floorPath") return;
if (that.sym.name == "wallPath") return;
}
bn.dirty = true;
bn.update();
if (that === bn.selectRect)
{
that.translate(deltaX, deltaY);
bn.shapes.forEach(function(shp){
if (shp.selected)
{
if (shp.element.matrix.split().rotate)
{
that._ui.rotatestr = "r"+shp.element.matrix.split().rotate;
shp.element.transform('');
}
shp.element.nt_translate(deltaX,deltaY);
}
});
}
else{
if (that.sym){
if (that.matrix.split().rotate)
{
that._ui.rotatestr = "r"+ that.matrix.split().rotate;
that.transform('');
}
that.nt_translate(deltaX,deltaY);
}
}
};
this._ui.onStart = R.is(start, 'function') ? start : function(x, y) {
if (bn.mouseState !== "default") return;
//if (that.glowEffect) that.glowEffect.remove();
$(bn.domId).css( 'cursor', "url('/img/3d/hand-pull-darkblue.cur'), default");
};
function onMove(distanceX, distanceY, x, y) {
if (bn.mouseState !== "default") return;
var cp = bn.canvasPoint(x, y);
var deltaX = cp.x - that._ui.lastX;
var deltaY = cp.y - that._ui.lastY;
that._ui.lastX = cp.x;
that._ui.lastY = cp.y;
//if (that.glowEffect) that.glowEffect.remove();
that._ui.onMove(distanceX, distanceY, x, y, deltaX, deltaY);
that.paper.safari();
}
function onStart(x, y) {
if (bn.mouseState !== "default") return;
if (that.sym)
if (that.sym.name == "floorPath") return;
var cp = bn.canvasPoint(x, y);
that._ui.lastX = cp.x;
that._ui.lastY = cp.y;
//if (that.glowEffect) that.glowEffect.remove();
that._ui.onStart(x, y);
}
function onUp(e){
if (that.sym){
bn.getShapeByElement(that).updateLook();
}
$(bn.domId).css( 'cursor', "auto" );
}
return this.drag(onMove, onStart, onUp);
};
})(Raphael);
(function() {
/** define 2 custom attributes translateNT and scaleNT (relative attributes) */
var initCA = function(shape) {
if(!shape.paper.customAttributes["translateNT"]) {
shape.paper.customAttributes["translateNT"] = function(dx, dy) {
if (this.type == "circle" || this.type == "ellipse") {
return {
"cx" : this.attr("cx") + dx,
"cy" : this.attr("cy") + dy
};
} else if (this.type == "rect" || this.type == "text"
|| this.type == "image") {
return {
"x" : this.attr("x") + dx,
"y" : this.attr("y") + dy
};
} else if (this.type == "path") {
var matrix = Raphael.matrix(1, 0, 0, 1, 0, 0);
matrix.translate(dx, dy);
var newPath = Raphael.mapPath(this.attr("path"), matrix);
this.attr({
"path" : newPath
});
}
};
shape.paper.customAttributes["scaleNT"] = function(dx, dy) {
if (this.type == "circle") {
return {
"r" : this.attr("r") * Math.max(dx, dy)
};
} else if (this.type == "ellipse") {
return {
"rx" : this.attr("rx") * dx,
"ry" : this.attr("ry") * dy
};
} else if (this.type == "rect" || this.type == "image") {
return {
"width" : this.attr("width") * dx,
"height" : this.attr("height") * dy
};
} else if (this.type == "text") {
var fs = parseInt(this.attr("font-size") + "");
return {
"font-size" : fs * Math.max(dx, dy)
};
} else if (this.type == "path") {
var bb = this.getBBox(), cx = bb.x + bb.width / 2, cy = bb.y
+ bb.height / 2;
var matrix = Raphael.matrix(1, 0, 0, 1, 0, 0);
matrix.scale(dx, dy, cx, cy);
var newPath = Raphael.mapPath(this.attr("path"), matrix);
return {
"path" : newPath
};
}
}
}
};
Raphael.el.nt_translate = function(dx, dy) {
initCA(this);
if (this.type == "circle" || this.type == "ellipse") {
this.attr({
"cx" : this.attr("cx") + dx,
"cy" : this.attr("cy") + dy
});
} else if (this.type == "rect" || this.type == "text"
|| this.type == "image") {
this.attr({
"x" : this.attr("x") + dx,
"y" : this.attr("y") + dy
});
} else if (this.type == "path") {
var matrix = Raphael.matrix(1, 0, 0, 1, 0, 0);
matrix.translate(dx, dy);
var newPath = Raphael.mapPath(this.attr("path"), matrix);
this.attr({
"path" : newPath
});
}
return this;
};
Raphael.el.nt_scale = function(dx, dy) {
initCA(this);
if (this.type == "circle") {
this.attr({
"r" : this.attr("r") * Math.max(dx, dy)
});
} else if (this.type == "ellipse") {
this.attr({
"rx" : this.attr("rx") * dx,
"ry" : this.attr("ry") * dy
});
} else if (this.type == "rect" || this.type == "image") {
this.attr({
"width" : this.attr("width") * dx,
"height" : this.attr("height") * dy
});
} else if (this.type == "text") {
var fs = parseInt(this.attr("font-size") + "");
this.attr({
"font-size" : fs * Math.max(dx, dy)
});
} else if (this.type == "path") {
var bb = this.getBBox(), cx = bb.x + bb.width / 2, cy = bb.y
+ bb.height / 2;
var matrix = Raphael.matrix(1, 0, 0, 1, 0, 0);
matrix.scale(dx, dy, cx, cy);
var newPath = Raphael.mapPath(this.attr("path"), matrix);
this.attr({
"path" : newPath
});
}
return this;
}
Raphael.st.nt_translate = function(dx, dy) {
initCA(this);
this.forEach(function(shape, idx) {
shape.nt_translate(dx, dy);
return true;
});
return this;
};
Raphael.st.nt_scale = function(dx, dy) {
initCA(this);
this.forEach(function(shape, idx) {
shape.nt_scale(dx, dy);
return true;
});
return this;
};
})();
//add reference service from outside
bn.inject = function(){
bn.$scope = bn.options.shell.$scope;
bn.$modal = bn.options.shell.$modal;
bn.$q = bn.options.shell.$q;
bn.$srv = bn.options.shell.$srv;
bn.$upload = bn.options.shell.$upload;
bn.$scope.setting = {};
bn.$scope.$on('shapeSelected', function(e, shapes) {
bn.proofer.showSettings(shapes, bn.$scope.setting);
if(!bn.$scope.$$phase) {
bn.$scope.$apply();
}
});
bn.$scope.$on('resetShape', function(e, shapes) {
bn.proofer.saveShapes(shapes, bn.$scope.setting);
if(!bn.$scope.$$phase) {
bn.$scope.$apply();
}
});
bn.$scope.change = function(){
bn.dirty = true;
bn.proofer.saveShapes(bn.proofer.shapes, bn.$scope.setting);
if(!bn.$scope.$$phase) {
bn.$scope.$apply();
}
};
};
bn.update = function(){
if(!bn.$scope.$$phase) {
bn.$scope.$apply();
}
};
bn.input = function(msg, inputValue, inputBox){
var deferred = bn.$q.defer();
var $modalScope = bn.$scope.$new(true);
$modalScope.message = msg;
$modalScope.inputValue = inputValue;
$modalScope.ok = function (){
deferred.resolve({val:this.inputValue, result:true});
this.$hide();
};
$modalScope.cancel = function (){
deferred.resolve({val:undefined, result:false});
this.$hide();
};
if($modalScope.languageJson == undefined)
$modalScope.languageJson = {};
$modalScope.languageJson.InputBox = inputBox;
bn.$modal({scope: $modalScope,
templateUrl: '/partials/inputBox.html',
show: true});
return deferred.promise;
};
bn.option = function(){
var imgShape, floorShape;
var $modalScope = bn.$scope.$new(false);
$modalScope.m = {};
var getMolds= function(symbolName){
var ms = [];
molds.forEach(function(m){
if (m.name === symbolName) ms.push(m);
});
return ms;
};
var load= function(){
imgShape = _.find(bn.shapes, function(shp){
return shp.config.name == "floorImage";
});
if (imgShape)
{
$modalScope.m.img = imgShape.config.param2D.src;
}
floorShape = _.find(bn.shapes, function(shp){
return shp.config.name == "floorPath";
});
if (floorShape){
$modalScope.floorDisable = false;
$modalScope.m.mold= _.find(molds,
function(m){ return m.id == floorShape.config.param3D.moldId; });
}
else
$modalScope.floorDisable = true;
};
$modalScope.walltype = false;
$modalScope.molds = getMolds("wallPath");
load();
$modalScope.change = function(){
if ($modalScope.m.mold){
floorShape.config.param3D.moldId = $modalScope.m.mold.id;
floorShape.updateLook();
}
bn.dirty = true;
};
$modalScope.$on("fileSelected",
function(event, msg) {
$modalScope.file = msg;
});
$modalScope.$on("fileSelected2",
function(event, msg) {
$modalScope.file2 = msg;
});
$modalScope.upload = function() {
var file = $modalScope.file;
if (file === undefined) return;
bn.$upload.uploadFile($modalScope.file).then(function(data) {
if ($modalScope.m.img) bn.$upload.deleteUploadFile($modalScope.m.img);
$modalScope.m.img = data;
bn.setBackground(data);
});
};
$modalScope.ok = function (){
this.$hide();
};
bn.$modal({scope: $modalScope,
templateUrl: '/partials/pageOption.html',
show: true});
};
bn.setBackground = function(imgurl) {
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var edit = languageJson.Room3D.Edit;
var img = new Image();
img.src = imgurl;
img.onload = function() {
var cfg = {
"id": "0",
"name": "floorImage",
"title": edit.FloorImage,
"param2D": {
"symbol": "floorImage",
"src": imgurl,
"height": this.height,
"width": this.width,
"transparent": "0.4"
}
};/*"地板底图"*/
var old = bn.findShapeBySymbolName("floorImage");
if (old) old.delete();
var shp = bn.addShape("floorImage", cfg.param2D);
if (shp) {
shp.config = cfg;
shp.updateLook();
}
}
};
bn.setBinding = function(bs){
if (!bs) return;
var $modalScope = bn.$scope.$new(true);
var echo= function(){
bs.forEach(function(item){
var dev = _.find($modalScope.data.devices,
function(d){ return d.id === item.id; });
if (dev) $modalScope.data.selecteds.push(dev);
})
};
$modalScope.data = {};
$modalScope.data.selecteds = [];
bn.$srv.getBinding().then(function(data){
$modalScope.data.devices = data;
echo();
});
$modalScope.ok = function (){
bs.length = 0;
$modalScope.data.selecteds.forEach(function(item){
bs.push(item);
});
bn.dirty = true;
this.$hide();
};
$modalScope.deleteBind = function (){
bs.length = 0;
bn.dirty = true;
this.$hide();
};
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
if($modalScope.languageJson == undefined)
$modalScope.languageJson = {Configuration:{TextControl:{}}};
$modalScope.languageJson.Configuration.TextControl.BindingSettings = languageJson.Configuration.TextControl.BindingSettings;
bn.$modal({scope: $modalScope,
templateUrl: '/partials/bindingDlg.html',
show: true});
};
bn.confirm = function(msg,confirmBox){
var deferred = bn.$q.defer();
var $modalScope = bn.$scope.$new(true);
$modalScope.message = msg;
$modalScope.ok = function (){
deferred.resolve(true);
this.$hide();
};
$modalScope.cancel = function (){
deferred.resolve(false);
this.$hide();
};
if($modalScope.languageJson == undefined) $modalScope.languageJson = {};
$modalScope.languageJson.ConfirmBox = confirmBox;
bn.$modal({scope: $modalScope,
templateUrl: '/partials/confirmBox.html',
show: true});
return deferred.promise;
};
bn.info = function(msg,messageBox){
var $modalScope = bn.$scope.$new(true);
$modalScope.message = msg;
if($modalScope.languageJson == undefined) $modalScope.languageJson = {};
$modalScope.languageJson.MessageBox = messageBox;
bn.$modal({scope: $modalScope,
templateUrl: '/partials/messageBox.html',
show: true});
};
bn.uploadConfig = function(cfg){
bn.$srv.saveConfig("demo", angular.toJson(cfg));
};
bn.ev = function(event, obj){
bn.$scope.$emit(event, obj);
};
bn.local = function(key){
var languageJson = angular.fromJson(sessionStorage.getItem('languageJson'));
var zh ={
new: "新建",
save: "保存",
clone: "复制并粘贴",
delete: "删除",
page_option: "画面设置",
align_top: "上对齐",
align_bottom: "下对齐",
align_vcenter: "水平居中",
align_left: "左对齐",
align_hcenter: "垂直居中",
align_right: "右对齐",
align_vscale: "垂直等间距",
align_hscale: "水平等间距",
to_back: "移动到最下层",
to_front: "移动到最上层",
move_up: "向上移动物体",
move_down: "向下移动物体",
move_left: "向左移动物体",
move_right: "向右移动物体"
};
var lan = undefined;
if(languageJson.Room3D.Head)
lan = languageJson.Room3D.Head;
else
lan = zh;
for(var a in lan)
{
if (a == key) return lan[a];
}
return null;
};
bn.dispose = function(){
var disposeObject = function(obj){
for(var b in obj){
if(typeof(obj[b]) === "function" && obj[b].name === "event"){
obj[b] = undefined;
}
else if(typeof(obj[b]) === "function" && obj[b].length > 0){
disposeObject(obj[b]);
}
else if(typeof(obj[b]) === "object" && b === "dispatch"){
disposeObject(obj[b]);
}
}
};
$(window).off();
$(window).unbind();
$(document).off();
$(document).unbind();
$(bn.domId).off();
$(bn.domId).unbind();
bn.clear();
bn.paper.clear();
var clearPaper = function (paper){
var paperDom = paper.canvas;
paperDom.parentNode.removeChild(paperDom);
};
clearPaper(bn.paper);
disposeObject(bn.paper);
bn.paper = undefined;
delete bn.options;
bn.$scope.change = undefined;
bn.$scope = undefined;
bn.$modal = undefined;
bn.$q = undefined;
bn.$srv = undefined;
bn.$upload = undefined;
disposeObject(bn);
bn = undefined;
};
///////// create main code here /////////
bn.options = _.extend(bn.options, options);
bn.inject();
bn.init(id);
bn.newConfig();
return bn;
}
};