# HG changeset patch # User Harris Baptiste # Date 1468425455 -7200 # Node ID 8f1af46307e1014c7857979c42ba9562934c4cb9 # Parent b30fa6fabee84f52f7bc4187b7399f9ea2b0c2d8 new zoom component diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/css/iconolab.css --- a/src/iconolab/static/iconolab/css/iconolab.css Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/css/iconolab.css Wed Jul 13 17:57:35 2016 +0200 @@ -5,4 +5,5 @@ .form-drawing {border-bottom: 1px solid #C3C3C3; } .form-drawing-wrapper .selected {border: 1px solid orange; color: white; background-color: orange} -.showPointer {cursor: pointer;} \ No newline at end of file +.showPointer {cursor: pointer;} +.zoomview-wrapper {border: 1px solid red; width: 135px; height: 100px; text-align: center;} \ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/index.html --- a/src/iconolab/static/iconolab/js/iconolab-bundle/index.html Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/index.html Wed Jul 13 17:57:35 2016 +0200 @@ -5,12 +5,10 @@ iconolab-bundle -
- diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/package.json --- a/src/iconolab/static/iconolab/js/iconolab-bundle/package.json Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/package.json Wed Jul 13 17:57:35 2016 +0200 @@ -4,7 +4,6 @@ "author": "hbaptiste", "private": true, "scripts": { - "dev": "webpack-dev-server --inline --hot", "start": "webpack --progress --colors --watch", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, diff -r b30fa6fabee8 -r 8f1af46307e1 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 Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/Cutout.vue Wed Jul 13 17:57:35 2016 +0200 @@ -2,14 +2,17 @@ import svgboard from './svgboard' import Typeahead from '../typeahead/Typeahead.vue' + import Zoomview from '../zoomview/Zoomview.vue' export default { el: '#drawing-zone', MODE_RECT: 'RECT', - MODE_FREE: 'FREE', + MODE_FREE: 'FREE', + ZOOM_IN: 'in', + ZOOM_OUT: 'out', - components: {typeahead: Typeahead}, + components: {typeahead: Typeahead, zoomview: Zoomview}, data: { mode:"", isRect: true, @@ -19,6 +22,7 @@ useClipPath: false, transformMatrix: "", fragmentPath: "", + canZoom: true, displayMask: false }, @@ -38,8 +42,71 @@ }, methods: { + + incraseDrawingZoom: function () { + this.drawingComponent.increaseZoom(); + }, - + decreaseDrawingZoom: function () { + this.drawingComponent.decreaseZoom(); + }, + + resetDrawingZoom: function () { + this.drawingComponent.reset(); + }, + + computeZoomedViewBox: function () { + var viewBoxArray = []; + var zoomSvg = this.$refs.zoomSvg; + var shapeBBox = this.drawingComponent.getShapeBBox(); + var imageWidth = zoomSvg.getAttribute("width"); + var imageHeight = zoomSvg.getAttribute("height"); + var xRatio = imageWidth / 100; + var yRatio = imageHeight / 100; + /* denormalize coordonate, max is imageX * 100x = imageHeigth*/ + shapeBBox.x = shapeBBox.x * xRatio; + shapeBBox.y = shapeBBox.y * yRatio; + + shapeBBox.w = shapeBBox.w * xRatio; + shapeBBox.h = shapeBBox.h * yRatio; + + var imgRatio = imageWidth / imageHeight; + if (shapeBBox.w > shapeBBox.h) { + shapeBBox.y = Math.max(0, shapeBBox.y - (((shapeBBox.w * imgRatio) - shapeBBox.h) / 2)); + shapeBBox.h = shapeBBox.w * imgRatio; + } + 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(" "); + }, + + zoom: function (direction) { + + var mainSvgWrapper = this.$refs.smallSvgWrapper; + if (this.$options.ZOOM_OUT === direction) { + var defaultViewBox = [0, 0, mainSvgWrapper.getAttribute("width"), mainSvgWrapper.getAttribute("height")]; + mainSvgWrapper.setAttribute("viewBox", defaultViewBox.join(" ")); + this.canZoom = true; + } + + if (this.$options.ZOOM_IN === direction) { + mainSvgWrapper.setAttribute("viewBox", this.computeZoomedViewBox()); + this.canZoom = false; + } + }, + setDrawingMode: function (mode, updateComponent) { if (!this.initialDrawingMode) { this.initialDrawingMode = mode;//useful for cancel @@ -61,10 +128,6 @@ } }, - showEditor: function () { - this.formView = false; - }, - highLightZone: function () { if (!this.displayMask) { this.displayMask = true; @@ -77,14 +140,23 @@ displayEditedPath: function () { var normalizePath = this.drawingComponent.getPath(); }, + + resetZoom: function () { + this.zoom(this.$options.ZOOM_OUT); + }, + + showEditor: function () { + this.formView = false; + this.resetZoom(); + /* on edit mode reset*/ + }, showForm: function () { this.normalizePath = this.drawingComponent.getPath(); var smallImage = this.$refs.smallImage; - console.log(this.$refs); this.formView = true; - var xRatio = smallImage.width / 100; - var yRatio = smallImage.height / 100; + var xRatio = smallImage.getAttribute("width") / 100; + var yRatio = smallImage.getAttribute("height") / 100; var transformMatrix = [xRatio, 0, 0, yRatio, 0, 0].join(','); this.transformMatrix ="matrix(" + transformMatrix + ")"; this.fragmentPath = this.normalizePath.split(';')[0]; diff -r b30fa6fabee8 -r 8f1af46307e1 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 Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/shape-resizer.js Wed Jul 13 17:57:35 2016 +0200 @@ -123,7 +123,7 @@ export default { - apply_resize : function (paper, rect) { + enable_resizer : function (paper, rect) { new ShapeResizer(paper, rect); } } \ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js Wed Jul 13 17:57:35 2016 +0200 @@ -0,0 +1,131 @@ +/* enable zoom */ +import { eventEmitter } from '../utils' + +class ZoomHandler { + + constructor (params) { + this.zoomFactor = 0.1 || params.zoomFactor; + this.paper = params.paper; + this.viewport = {width: 529, height: 800}; + 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 = []; + } + + 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; + + this.currentViewBox[0] = topX; + this.currentViewBox[1] = topY; + + this.currentViewBox[2] = viewBoxW; + this.currentViewBox[3] = viewBoxH; + + this.updateViewBox(); + this.scale ++; + } + + updateViewBox () { + this.paper.attr({"viewBox": this.currentViewBox}); + eventEmitter.emit("zoomChanged", { + "zoomFactor": this.getZoomFactor(), + "viewport": this.viewport, + "currentViewBox": this.currentViewBox + }); + } + + getZoomFactor () { + return { + x: this.viewport.width / this.currentViewBox[2], + y: this.viewport.height / this.currentViewBox[3] + }; + } + + onStart (x, y, e) { + + this.lastPosition[0] = this.currentViewBox[0]; + this.lastPosition[1] = this.currentViewBox[1]; + + if (e.target.className.baseVal === "drawingHandler") { + this.disableDrag = true; + } + } + + canDrag () { + return !this.disableDrag; + } + + onStop () { + this.disableDrag = false; + } + + onDrag (dx, dy, x, y, event) { + + if (!this.canDrag()) { return true; } + + var newX = this.lastPosition[0] - dx; + var newY = this.lastPosition[1] - dy; + + /* maxX bound */ + if (newX + this.currentViewBox[2] >= this.viewport.width) { + newX = this.viewport.width - this.currentViewBox[2]; + } + + /* maxY bound */ + if (newY + this.currentViewBox[3] >= this.viewport.height) { + newY = this.viewport.height - this.currentViewBox[3]; + } + + if (newX <= 0) { newX = 0; } + + if(newY <= 0) { newY = 0; } + + this.currentViewBox[0] = newX; + this.currentViewBox[1] = newY; + + this.updateViewBox(); + } + + reset () { + this.scale = 1; + this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height]; + this.updateViewBox(); + } + + zoomOut () { + if (this.scale === 1) { return false; } + 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) { + return false; + } + + var topX = (this.viewport.width - viewBoxW) / 2; + var topY = (this.viewport.height - viewBoxH) / 2; + + this.currentViewBox[0] = topX; + this.currentViewBox[1] = topY; + this.currentViewBox[2] = viewBoxW; + this.currentViewBox[3] = viewBoxH; + + this.scale--; + this.updateViewBox(); + + } +} + +export default { + + enable_zoom: function (params) { + return new ZoomHandler(params); + } +} \ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 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 Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js Wed Jul 13 17:57:35 2016 +0200 @@ -1,12 +1,13 @@ -var Snap = require('snapsvg'); -//import Snap from 'snapsvg' +import Snap from 'snapsvg' import ShapeResizer from './shape-resizer' import EventEmitter from 'event-emitter' +import SnapsvgZoom from './snapsvg-zoom' + var eventEmitter = EventEmitter({}); -/* custom plugin */ +/* custom plugins */ Snap.plugin(function (Snap, Element, Paper, glob) { var elproto = Element.prototype; @@ -28,6 +29,7 @@ var mainImage = null; var pointData = []; var viewBoxBounds = {X: 100, Y:100}; +var zoomManager = null; var config = null; var readOnly = false; var startPoint = null; @@ -73,7 +75,7 @@ drawing_path = rectZone; canDraw = false; pathIsClosed = true; - ShapeResizer.apply_resize(paper, drawing_path); + ShapeResizer.enable_resizer(paper, drawing_path); }; @@ -188,6 +190,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 transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]; this.attr({ transform: transformValue}); var boxSize = this.getBBox(); @@ -210,6 +216,7 @@ }); point.handler.drag(onMoveHandler, function () { + console.log(this.transform().globalMatrix); this.data('origTransform', this.transform().local ); }, function () { if (!isDragged) { return true; } @@ -224,7 +231,7 @@ var handleY = point.y - HANDLE_SIZE/2; handler = p.rect(handleX, handleY, HANDLE_SIZE, HANDLE_SIZE); - + handler.addClass("drawingHandler"); point.handler = handler; point.handler.data('point', point); if (pointData.length === 0) { @@ -341,11 +348,23 @@ }; var API = { - + + increaseZoom: function () { + zoomManager.zoomIn(); + }, + + reset: function () { + zoomManager.reset(); + }, + + decreaseZoom: function () { + zoomManager.zoomOut(); + }, + setPath: function (pathString) { /* redraw the path */ var pathInfos = pathString.split(';'); - if( availableModes.indexOf(pathInfos[1]) === -1) { + if ( availableModes.indexOf(pathInfos[1]) === -1) { /* We assume then it is a free path */ pathInfos[1] = "FREE"; } @@ -353,14 +372,14 @@ this.setDrawingMode(pathInfos[1]); var pathData = pathInfos[0]; - if(!pathData.length) { + if (!pathData.length) { return; } - /* deal with path nomalization x = ImageWith/MaxXBound*/ + /* deal with path nomalization x = ImageWith/MaxXBound */ var xRatio = mainImage.width() / viewBoxBounds.X; var yRatio = mainImage.height() / viewBoxBounds.Y; - if(isNaN(xRatio) || isNaN(yRatio)) { + if (isNaN(xRatio) || isNaN(yRatio)) { new Error('Ratio should be a number.'); } @@ -416,6 +435,11 @@ ENABLE_NEW_NODE = true; }, + getShapeBBox: function () { + var currentPath = this.getPath(); + return Snap.path.getBBox(currentPath); + }, + getPath: function () { /* retourne le chemin */ /* send path and BBox | implement edit and load path */ @@ -478,22 +502,25 @@ export default { init: function(config) { - mainImage = jQuery(config.wrapperId).find('img').eq(0); + mainImage = jQuery(config.wrapperId).find('.main-image').eq(0); var cutCanvas = jQuery(config.wrapperId).find('.cut-canvas').eq(0); var path = jQuery(config.wrapperId).find('.image-path').eq(0); if (typeof config.onDrawingModeChange === 'function') { onChangeCallback = config.onDrawingModeChange; } + + if (!mainImage.length) { + throw new Error("The main image Can't be found ..."); + } if (!cutCanvas.length) { var cutCanvas = jQuery('').addClass('cut-canvas'); jQuery(config.wrapperId).append(cutCanvas); + cutCanvas.append(mainImage); } - if (!mainImage) { - new Error(config.wrapperId + "Can't be found ..."); - } + cutCanvas.css({ position: 'absolute', @@ -501,9 +528,9 @@ left: '15px', marginLeft: 'auto', marginRight: 'auto', - width: mainImage.width(), - height: mainImage.height(), - viewBox: '0 0 100 100' + width: mainImage.attr('width'), + height: mainImage.attr('height'), + //viewBox: '0 0 100 100' }); if (typeof config.readOnly === 'boolean' && config.readOnly === true) { @@ -514,9 +541,12 @@ if (path.length) { jQuery(cutCanvas).append(path); - API.setPath(path.attr("d")); + var pathData = path.attr("d"); + API.setPath(pathData); + path.remove(); } - + /* enable zoom */ + zoomManager = SnapsvgZoom.enable_zoom({paper : paper}); attachPointEvents(paper); attachRectEvents(paper); diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/src/components/typeahead/Typeahead.vue --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/typeahead/Typeahead.vue Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/typeahead/Typeahead.vue Wed Jul 13 17:57:35 2016 +0200 @@ -6,7 +6,7 @@ import Taglist from '../taglist/Taglist.vue' var autoCompletePath = "http://lookup.dbpedia.org/api/search/PrefixSearch?MaxHits=5"; - var wikipediaPath= "http://fr.wikipedia.org/w/api.php" + var wikipediaPath = "http://fr.wikipedia.org/w/api.php" var parentsMethods = { reset: typeahead.methods.reset }; diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js --- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js Wed Jul 13 17:57:35 2016 +0200 @@ -1,3 +1,6 @@ +import EventEmitter from 'event-emitter' +var eventEmitter = EventEmitter({}); + var generateId = (function () { var cpt = 0; var defautPrefix = "item_"; @@ -7,4 +10,5 @@ return prefix + cpt; } }()); -export { generateId } \ No newline at end of file + +export { generateId , eventEmitter } \ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue Wed Jul 13 17:57:35 2016 +0200 @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html Wed Jul 13 17:57:35 2016 +0200 @@ -0,0 +1,12 @@ +
+ + + + +
\ No newline at end of file diff -r b30fa6fabee8 -r 8f1af46307e1 src/iconolab/templates/iconolab/change_annotation.html --- a/src/iconolab/templates/iconolab/change_annotation.html Tue Jul 05 14:28:04 2016 +0200 +++ b/src/iconolab/templates/iconolab/change_annotation.html Wed Jul 13 17:57:35 2016 +0200 @@ -14,6 +14,17 @@
  • Rect.
  • Libre
  • + + + {% thumbnail image.media "x100" crop="center" as im %} + + + {% endthumbnail %} -
    +
    {% if form.errors %}