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 = ""; }, 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; } };