# HG changeset patch # User Harris Baptiste # Date 1469198888 -7200 # Node ID 22c88b2c325f6836c19f7e5dda1c61c0b957319d # Parent 8f1af46307e1014c7857979c42ba9562934c4cb9 adding zoomview component diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/css/iconolab.css --- a/src/iconolab/static/iconolab/css/iconolab.css Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/css/iconolab.css Fri Jul 22 16:48:08 2016 +0200 @@ -6,4 +6,3 @@ .form-drawing-wrapper .selected {border: 1px solid orange; color: white; background-color: orange} .showPointer {cursor: pointer;} -.zoomview-wrapper {border: 1px solid red; width: 135px; height: 100px; text-align: center;} \ No newline at end of file diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/.babelrc --- a/src/iconolab/static/iconolab/js/iconolab-bundle/.babelrc Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/.babelrc Fri Jul 22 16:48:08 2016 +0200 @@ -1,3 +1,3 @@ { - "presets": ["es2015"] + "presets": ["es2015"], } diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/package.json --- a/src/iconolab/static/iconolab/js/iconolab-bundle/package.json Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/package.json Fri Jul 22 16:48:08 2016 +0200 @@ -25,6 +25,7 @@ "devDependencies": { "babel-core": "^6.0.0", "babel-loader": "^6.0.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.8.0", "babel-preset-es2015": "^6.0.0", "cross-env": "^1.0.6", "css-loader": "^0.23.1", diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/Cutout.vue --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/Cutout.vue Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/Cutout.vue Fri Jul 22 16:48:08 2016 +0200 @@ -3,7 +3,7 @@ import svgboard from './svgboard' import Typeahead from '../typeahead/Typeahead.vue' import Zoomview from '../zoomview/Zoomview.vue' - + export default { el: '#drawing-zone', @@ -37,22 +37,26 @@ self.setDrawingMode(mode, false); } }); - + this.$refs.zoomview.setZoomTarget(this.drawingComponent.getPaper()); this.showForm(); }, methods: { - - incraseDrawingZoom: function () { - this.drawingComponent.increaseZoom(); - }, + + computeCentreredViewBox: function () { + var zoomSvg = this.$refs.zoomSvg; + var viewBox = []; + var imageWidth = zoomSvg.getAttribute("width"); + var imageHeight = zoomSvg.getAttribute("height"); - decreaseDrawingZoom: function () { - this.drawingComponent.decreaseZoom(); - }, + /* normalize */ + var xRatio = imageWidth / 100 ; + var yRatio = imageHeight / 100; - resetDrawingZoom: function () { - this.drawingComponent.reset(); + var zTarget = this.drawingComponent.getShapeBBox(); + viewBox = [(zTarget.x - 1) * xRatio, (zTarget.y - 1) * yRatio, (zTarget.w + 2) * xRatio, (zTarget.h + 2) * yRatio]; + return viewBox.join(" "); + }, computeZoomedViewBox: function () { @@ -78,17 +82,11 @@ else { shapeBBox.x = Math.max(0, shapeBBox.x - (((shapeBBox.h / imgRatio) - shapeBBox.w) / 2)); shapeBBox.w = shapeBBox.h / imgRatio; - console.log(shapeBBox.y); } viewBoxArray = [shapeBBox.x, shapeBBox.y, shapeBBox.w, shapeBBox.h]; if (!shapeBBox) { return false; } - - /* test compute zoom - agrandir de sorte max bbox.h==viewPort.h && bbox.w - */ - //var viewBoxArray = [shapeBBox.x, shapeBBox.y, imageWidth, imageHeight] - console.log(viewBoxArray); + return viewBoxArray.join(" "); }, @@ -102,7 +100,7 @@ } if (this.$options.ZOOM_IN === direction) { - mainSvgWrapper.setAttribute("viewBox", this.computeZoomedViewBox()); + mainSvgWrapper.setAttribute("viewBox", this.computeCentreredViewBox());//this.computeZoomedViewBox());// this.canZoom = false; } }, diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/shape-resizer.js --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/shape-resizer.js Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/shape-resizer.js Fri Jul 22 16:48:08 2016 +0200 @@ -1,9 +1,8 @@ /* Enabling us to resize a shape width a handler #http://stackoverflow.com/questions/32390028/how-to-drag-and-resize-svg-rectangle-using-cursor-types */ -import EventEmitter from "event-emitter" +import { eventEmitter } from "../utils" -var eventEmitter = EventEmitter({}); var ShapeResizer = function (paper, shape) { this.paper = paper; this.shape = shape; @@ -20,6 +19,7 @@ var api = ShapeResizer.prototype = { init: function () { + this.currentZoomFactor = {x: 1, y: 1}; this.showHandlers(); }, @@ -29,6 +29,8 @@ var handleX = bbox.x - this.HANDLER_SIZE/2; var handleY = bbox.y - this.HANDLER_SIZE/2; var handler = this.paper.rect(handleX, handleY, this.HANDLER_SIZE, this.HANDLER_SIZE).attr({fill: 'red'}); + handler.addClass("drawingHandler"); + this.shape.addClass("drawingHandler"); var handlerInfos = {position: "t_r", handler: handler}; this.handlers.push(handlerInfos); this.shapesGroup = this.paper.g(this.shape, handler); @@ -46,6 +48,7 @@ /*to the right => reduce the size */ var newWidth = (dx > 0) ? shapeBBox.width - dx : shapeBBox.width + Math.abs(dx); var newHeight = (dy > 0) ? shapeBBox.height - dy : shapeBBox.height + Math.abs(dy); + var transformValue = this.shape.data('origTransform') + (this.shape.data('origTransform') ? "T" : "t") + [dx, dy]; this.shape.attr({'transform': transformValue, width: newWidth, height: newHeight}); }, @@ -61,6 +64,8 @@ }, onMove: function (handlerData, dx, dy, x, y, e) { + dx = dx / this.currentZoomFactor.x; + dy = dy / this.currentZoomFactor.y; var transformValue = handlerData.handler.data('origTransform') + (handlerData.handler.data('origTransform') ? "T" : "t") + [dx, dy]; this.currentPosition.x = e.clientX; this.currentPosition.y = e.clientY; @@ -111,8 +116,14 @@ self.destroy(); }); + eventEmitter.on("zoomChanged", function (zoomInfos) { + self.currentZoomFactor = zoomInfos.zoomFactor; + }); + this.shapesGroup.drag(function (dx, dy) { if (self.isResizing) { return; } + dx = dx / self.currentZoomFactor.x; + dy = dy / self.currentZoomFactor.y; var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; this.transform(transformValue); }, function () { diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js Fri Jul 22 16:48:08 2016 +0200 @@ -6,40 +6,72 @@ constructor (params) { this.zoomFactor = 0.1 || params.zoomFactor; this.paper = params.paper; - this.viewport = {width: 529, height: 800}; + var width = parseInt(this.paper.select(".main-image").attr("width")); + var height = parseInt(this.paper.select(".main-image").attr("height")); + this.viewport = {width: width, height: height}; this.scale = 1; this.disableDrag = false; - this.paper.attr({"preserveAspectRatio": "xMidYMid meet"}); this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height]; - this.paper.drag(this.onDrag.bind(this), this.onStart.bind(this), this.onStop.bind(this)); this.lastPosition = []; } + testShowCenter (cx, cy) { + + if (this.center) { + this.center.remove(); + } + this.center = this.paper.rect(cx - 3, cy - 3, 20, 20); + this.center.attr({"fill" : "red"}); + } + + drawTestRectangle (cx, cy, w, h) { + var x = cx - w / 2; + var y = cy - h / 2; + this.paper.rect(x, y, w, h); + } + zoomIn () { - var viewBoxW = this.viewport.width - (this.viewport.width * this.zoomFactor * this.scale); - var viewBoxH = this.viewport.height - (this.viewport.height * this.zoomFactor * this.scale); - if (!viewBoxW || !viewBoxH) { return false; } - /* center the viewbox */ - var topX = (this.viewport.width - viewBoxW) / 2; - var topY = (this.viewport.height - viewBoxH) / 2; + /* current center */ + var currentCenterX = this.currentViewBox[0] + (this.currentViewBox[2] / 2); + var currentCenterY = this.currentViewBox[1] + (this.currentViewBox[3] / 2); + var scaleFactor = this.zoomFactor * this.scale; + var viewBoxW = this.viewport.width - (this.viewport.width * scaleFactor); + var viewBoxH = this.viewport.height - (this.viewport.height * scaleFactor); + + if (viewBoxW <= 0 && viewBoxH <=0) { + return false; + } - this.currentViewBox[0] = topX; - this.currentViewBox[1] = topY; + this.currentViewBox[0] = currentCenterX - viewBoxW / 2; + this.currentViewBox[1] = currentCenterY - viewBoxH / 2; this.currentViewBox[2] = viewBoxW; this.currentViewBox[3] = viewBoxH; - this.updateViewBox(); this.scale ++; } - updateViewBox () { + updateViewBox (currentViewBox, notify) { + notify = (typeof notify === "boolean") ? notify : true; + + if (currentViewBox && currentViewBox.length != 4) { throw new Error("Provided currentViewBox is not valid!"); } + if (currentViewBox) { + this.currentViewBox = currentViewBox; + } + this.paper.attr({"viewBox": this.currentViewBox}); + + if (!notify) { return false; } + + var self = this; eventEmitter.emit("zoomChanged", { + updateFunction: function (updatedViewBox) { + self.updateViewBox(updatedViewBox, false); + }, "zoomFactor": this.getZoomFactor(), "viewport": this.viewport, - "currentViewBox": this.currentViewBox + "currentViewBox": this.currentViewBox.slice() }); } @@ -103,15 +135,19 @@ zoomOut () { if (this.scale === 1) { return false; } + + var currentCenterX = this.currentViewBox[0] + (this.currentViewBox[2] / 2); + var currentCenterY = this.currentViewBox[1] + (this.currentViewBox[3] / 2); + var viewBoxW = this.currentViewBox[2] + (this.viewport.width * this.zoomFactor); var viewBoxH = this.currentViewBox[3] + (this.viewport.height * this.zoomFactor); - if (viewBoxW > this.viewport.width || viewBoxW > this.viewport.height) { + if (viewBoxW >= this.viewport.width || viewBoxW >= this.viewport.height) { return false; } + var topX = currentCenterX - viewBoxW / 2; + var topY = currentCenterY - viewBoxH / 2; - var topX = (this.viewport.width - viewBoxW) / 2; - var topY = (this.viewport.height - viewBoxH) / 2; - + /* fix size */ this.currentViewBox[0] = topX; this.currentViewBox[1] = topY; this.currentViewBox[2] = viewBoxW; diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js Fri Jul 22 16:48:08 2016 +0200 @@ -2,11 +2,9 @@ import Snap from 'snapsvg' import ShapeResizer from './shape-resizer' -import EventEmitter from 'event-emitter' +import { eventEmitter } from '../utils' import SnapsvgZoom from './snapsvg-zoom' -var eventEmitter = EventEmitter({}); - /* custom plugins */ Snap.plugin(function (Snap, Element, Paper, glob) { var elproto = Element.prototype; @@ -29,7 +27,7 @@ var mainImage = null; var pointData = []; var viewBoxBounds = {X: 100, Y:100}; -var zoomManager = null; +var zoomFactor = {x:1, y:1}; var config = null; var readOnly = false; var startPoint = null; @@ -189,11 +187,10 @@ var onMoveHandler = function (dx, dy, posX, posY, e) { isDragged = true; - /* update point then update the view */ - var zoomFactor = zoomManager.getZoomFactor(); - console.log(zoomFactor); - dx = dx / zoomFactor.x; - dy = dy / zoomFactor.y; + var factorX = zoomFactor.x ? zoomFactor.x : 1; + var factorY = zoomFactor.y ? zoomFactor.y : 1; + dx = dx / factorX; + dy = dy / factorY; var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; this.attr({ transform: transformValue}); var boxSize = this.getBBox(); @@ -216,7 +213,6 @@ }); point.handler.drag(onMoveHandler, function () { - console.log(this.transform().globalMatrix); this.data('origTransform', this.transform().local ); }, function () { if (!isDragged) { return true; } @@ -330,7 +326,7 @@ paper.mouseup(function () { if ((drawingMode === FREE_MODE) || pathIsClosed || !rectZone) { return false; } drawing_path = rectZone; - ShapeResizer.apply_resize(paper, rectZone); + ShapeResizer.enable_resizer(paper, rectZone); canDraw = false; pathIsClosed = true; }); @@ -347,18 +343,18 @@ }); }; + +var attachZoomEvents = function () { + eventEmitter.on("zoomChanged", function (zoomInfos) { + zoomFactor = zoomInfos.zoomFactor; + }); +} + + var API = { - increaseZoom: function () { - zoomManager.zoomIn(); - }, - - reset: function () { - zoomManager.reset(); - }, - - decreaseZoom: function () { - zoomManager.zoomOut(); + getPaper: function () { + return paper; }, setPath: function (pathString) { @@ -376,8 +372,8 @@ return; } /* deal with path nomalization x = ImageWith/MaxXBound */ - var xRatio = mainImage.width() / viewBoxBounds.X; - var yRatio = mainImage.height() / viewBoxBounds.Y; + var xRatio = mainImage.attr("width") / viewBoxBounds.X; + var yRatio = mainImage.attr("height") / viewBoxBounds.Y; if (isNaN(xRatio) || isNaN(yRatio)) { new Error('Ratio should be a number.'); @@ -439,6 +435,10 @@ var currentPath = this.getPath(); return Snap.path.getBBox(currentPath); }, + + getShape: function () { + return this.getPath(); + }, getPath: function () { /* retourne le chemin */ @@ -454,11 +454,10 @@ } else { - + var shapeX = drawing_path.node.getAttribute('x'); var shapeY = drawing_path.node.getAttribute('y'); - - var transformMatrix = transform.globalMatrix; + var transformMatrix = transform.totalMatrix; var fakeShape = paper.rect(transformMatrix.x(shapeX, shapeY),transformMatrix.y(shapeX, shapeY), bBox.width, bBox.height); shapePath = fakeShape.getBBox().path; fakeShape.remove(); @@ -472,8 +471,9 @@ } } - var xRatio = viewBoxBounds.X / mainImage.width(); - var yRatio = viewBoxBounds.Y / mainImage.height(); + var xRatio = viewBoxBounds.X / mainImage.attr("width"); + var yRatio = viewBoxBounds.Y / mainImage.attr("height"); + if(isNaN(xRatio) || isNaN(yRatio)) { new Error('ratio should be a number.'); } @@ -482,8 +482,8 @@ path = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE"; return path; } + var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); - var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0); path = Snap.path.map(path, normalizeMatrix).toString(); /* save the type */ @@ -494,6 +494,7 @@ path += type; + return path; } }; @@ -532,6 +533,12 @@ height: mainImage.attr('height'), //viewBox: '0 0 100 100' }); + + /* fix the container size */ + jQuery(config.wrapperId).css({ + width: mainImage.attr('width'), + height: parseInt(mainImage.attr('height')) + 5 + }); if (typeof config.readOnly === 'boolean' && config.readOnly === true) { readOnly = true; @@ -546,7 +553,7 @@ path.remove(); } /* enable zoom */ - zoomManager = SnapsvgZoom.enable_zoom({paper : paper}); + attachZoomEvents(); attachPointEvents(paper); attachRectEvents(paper); diff -r 8f1af46307e1 -r 22c88b2c325f src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue Wed Jul 13 17:57:35 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue Fri Jul 22 16:48:08 2016 +0200 @@ -4,31 +4,154 @@ {% endblock %} \ No newline at end of file