new zoom viewport
authorHarris Baptiste <harris.baptiste@iri.centrepompidou.fr>
Tue, 26 Jul 2016 14:26:12 +0200
changeset 78 7257527afd4a
parent 74 d1cdbbfff73f
child 79 329606de509a
new zoom viewport
src/iconolab/static/iconolab/css/iconolab.css
src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js
src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js
src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js
src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue
src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html
src/iconolab/static/iconolab/js/iconolab-bundle/webpack.config.js
src/iconolab/templates/iconolab/change_annotation.html
src/iconolab/templates/iconolab/detail_annotation.html
--- a/src/iconolab/static/iconolab/css/iconolab.css	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/css/iconolab.css	Tue Jul 26 14:26:12 2016 +0200
@@ -7,6 +7,11 @@
 .form-drawing-wrapper .selected {border: 1px solid orange; color: white; background-color: orange}
 .showPointer {cursor: pointer;}
 
+.zoom-action-list {padding-left:21px;}
+.zoomTarget-wrapper { padding: 0px;}
+#zoomTarget, .cut-canvas {border: 1px solid #C3C3C3; padding-top: 2px; padding-bottom: 2px}
+
+.no-padding {padding-left: 0; padding-right: 0;}
 .annotation-content{
 	margin-top: 15px;
 	margin-bottom: 15px;
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js	Tue Jul 26 14:26:12 2016 +0200
@@ -6,13 +6,21 @@
 	constructor (params) {
 		this.zoomFactor = 0.1 || params.zoomFactor;
 		this.paper = params.paper;
-		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.MIN_SIZE = 40;
+		this.imageWidth = parseInt(this.paper.select(".main-image").attr("width"));
+		this.imageHeight = parseInt(this.paper.select(".main-image").attr("height"));
+		
+		this.viewport = {
+			width: parseInt(this.paper.attr("width")),
+			height: parseInt(this.paper.attr("height"))
+		};
+
 		this.scale = 1;
+		this.paper.attr({stroke: 2, "fill": "blue" });
 		this.disableDrag = false;
-		this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height];
+		this.imgMinSize = Math.min(this.imageWidth, this.imageHeight);
 		this.lastPosition = []; 
+		this.updateViewBox([0 , 0, this.imageWidth, this.imageHeight], false);
 	}
 
 	testShowCenter (cx, cy) {
@@ -33,23 +41,20 @@
 	zoomIn () {
 
 		/* current center */
+		if ( this.scale === 9) { this.scale--; return; }
 		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);
+		var viewBoxW = this.imgMinSize - (this.imgMinSize * scaleFactor);  
+		var viewBoxH = viewBoxW;
 		
-		if (viewBoxW <= 0 && viewBoxH <=0) {
-			return false;
-		}
-
 		this.currentViewBox[0] = currentCenterX - viewBoxW / 2;
 		this.currentViewBox[1] = currentCenterY - viewBoxH / 2;
 
 		this.currentViewBox[2] = viewBoxW;
 		this.currentViewBox[3] = viewBoxH;
+		this.scale ++;
 		this.updateViewBox();
-		this.scale ++;
 	}
 	
 	updateViewBox (currentViewBox, notify) {
@@ -71,6 +76,9 @@
 			},
 			"zoomFactor": this.getZoomFactor(),
 			"viewport": this.viewport,
+			"currentScale": this.scale,
+			"imageSize": {width: this.imageWidth, height: this.imageHeight}, 
+			"minSize": Math.min(this.imageWidth, this.imageHeight),
 			"currentViewBox": this.currentViewBox.slice()
 		});
 	}
@@ -129,33 +137,31 @@
 
 	reset () {
 		this.scale = 1;
-		this.currentViewBox = [0, 0, this.viewport.width, this.viewport.height];
+		this.currentViewBox = [0, 0, this.imageWidth, this.imageHeight];
 		this.updateViewBox();
 	}
 
 	zoomOut () {
-		if (this.scale === 1) { return false; }
-		
+		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 scaleFactor = this.zoomFactor * (this.scale - 1);
 
-		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 viewBoxW = this.imgMinSize - (this.imgMinSize * scaleFactor);
+		var viewBoxH = viewBoxW;
+
 		var topX = currentCenterX - viewBoxW / 2;
 		var topY = currentCenterY - viewBoxH / 2;
 
-		/* fix size */ 
-		this.currentViewBox[0] = topX;
+		this.currentViewBox[0] = topX; //deal with X and Y
 		this.currentViewBox[1] = topY; 
 		this.currentViewBox[2] = viewBoxW;
 		this.currentViewBox[3] = viewBoxH;
-
+		this.updateViewBox();
 		this.scale--;
-		this.updateViewBox();
-		
 	}
 }
 
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/cutout/svgboard.js	Tue Jul 26 14:26:12 2016 +0200
@@ -524,21 +524,20 @@
 		
 
 		cutCanvas.css({
-			position: 'absolute', 
+			/*position: 'absolute', 
 			top: '0px', 
-			left: '15px',
+			left: '15px',*/
 			marginLeft: 'auto',
 			marginRight: 'auto',
-			width: mainImage.attr('width'),
-			height: mainImage.attr('height'),
-			//viewBox: '0 0 100 100'
+			width: 850,
+			height: 850
 		});
 		
 		/* fix the container size */
-		jQuery(config.wrapperId).css({ 
+		/*jQuery(config.wrapperId).css({ 
 			width: mainImage.attr('width'),
 			height: parseInt(mainImage.attr('height')) + 5
-		});
+		});*/
 
 		if (typeof config.readOnly === 'boolean' && config.readOnly === true) {
 			readOnly = true;
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/utils/index.js	Tue Jul 26 14:26:12 2016 +0200
@@ -1,11 +1,12 @@
 import EventEmitter from 'event-emitter' 
 var eventEmitter = EventEmitter({});
 
+
 var generateId = (function () {
 		var cpt = 0;
 		var defautPrefix = "item_"; 
 		return function (prefix) {
-			prefix = (typeof prefix === 'string') ? prefix : defautPrefix;
+			prefix = (typeof prefix === "string") ? prefix : defautPrefix;
 			cpt = cpt + 1;
 			return prefix + cpt; 
 		}
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/Zoomview.vue	Tue Jul 26 14:26:12 2016 +0200
@@ -3,21 +3,26 @@
 
 <script>
 
-import {eventEmitter} from '../utils'
+import {eventEmitter, computeElementSize} from '../utils'
 import ZoomHandler from '../cutout/snapsvg-zoom'
 
 import Snap from 'snapsvg'
 
 export default {
 
-	props: ['image-url', 'width', 'height', 'zoomTarget'],
+	props: ['image-url', 'image-width', 'image-height', 'zoomTarget', 'main-image-id'],
 	
 	mounted () {
 		this.root = new Snap(this.$refs['root-svg']);
 		this.handler = this.root.select('#zoom-handler');
 		this.image = this.root.select('#small-image');
-		//this.ratio = this.image.attr('width') / this.image.attr('height');
-		this.root.attr({width: this.width, height: this.height});
+		this.root.attr({width: 101, height: 101});
+		var imageWidth = parseInt(this.image.attr("width"));
+		var imageHeight = parseInt(this.image.attr("height"));
+		/* center image in the viewport */
+		this.root.attr({viewBox: [0, 0, imageWidth, imageHeight]});
+		this.imgMinSize = Math.min(imageWidth, imageHeight);
+
 		this.handlerSize = 20;
 		this.handler.attr({'width': this.handlerSize, 'height': this.handlerSize});
 		this.currentViewBox  = null;
@@ -39,12 +44,16 @@
 	methods: {
 		
 		setZoomTarget: function (zoomtarget) {
+			
 			if (zoomtarget.hasOwnProperty("type") && zoomtarget.type === 'svg') {
 				this.paper = zoomtarget; 	
+			} else {
+
+				this.paper = new Snap(zoomtarget);
+				var mainImage = this.paper.select("#" + this.mainImageId);
+				if (!mainImage) { throw new Error("A main image wasn't found."); };
 			}
-			else {
-				this.paper = new Snap(zoomtarget);
-			}
+
 			this.zoomHandler =  ZoomHandler.enable_zoom(this.paper);
 		},
 
@@ -115,8 +124,10 @@
 			 }});
 
 			if (!this.currentViewBox || !this.currentViewport || typeof this.updateFunction !== 'function') { return false; }
-			var xRatio = this.currentViewport.width / this.image.attr('width');
-			var yRatio = this.currentViewport.height / this.image.attr('height');
+
+			/*longueur image=> longueur viewbox */
+			var xRatio = this.currentImageSize.width / this.image.attr('width');
+			var yRatio = this.currentImageSize.height / this.image.attr('height');
 			var newX = x * xRatio;
 			var newY = y * yRatio;
 			this.currentViewBox[0] = newX;
@@ -126,7 +137,7 @@
 
 		handleZoomChanged: function (zoomInfos) {
 			
-			if (zoomInfos.zoomFactor.x === 1 && zoomInfos.zoomFactor.y === 1) { 
+			if (zoomInfos.currentScale === 1) { 
 				this.showHandler = false;
 				return; 
 			}
@@ -135,22 +146,16 @@
 
 			this.currentViewport = zoomInfos.viewport;
 			this.currentViewBox = zoomInfos.currentViewBox;
+			this.currentImageSize = zoomInfos.imageSize; 
 			this.updateFunction = zoomInfos.updateFunction;
-
-			var vpW = zoomInfos.viewport.width;
-			var vpH = zoomInfos.viewport.height;
+			var handlerSize = zoomInfos.currentViewBox[2] * this.imgMinSize / zoomInfos.minSize;
 			
-			/* handler size */
-			var minSize = Math.min(zoomInfos.currentViewBox[2], zoomInfos.currentViewBox[3]);
-			var HSize = minSize * Math.min(this.image.attr("width"),this.image.attr("height")) / Math.min(vpW,vpH);
-			this.handler.attr("width", HSize);
-			this.handler.attr("height", HSize);
-			//this.handler.attr("width", (zoomInfos.currentViewBox[2]) * this.image.attr("width") / vpW);
-			//this.handler.attr("height", (zoomInfos.currentViewBox[2]) * this.image.attr("width") / vpW);
+			this.handler.attr("width", handlerSize);
+			this.handler.attr("height", handlerSize);
 
 			/*compute handler x, y */
-			var x = zoomInfos.currentViewBox[0] * this.image.attr("width") / vpW;
-			var y = zoomInfos.currentViewBox[1] * this.image.attr("height")/ vpH;
+			var x = zoomInfos.currentViewBox[0] * this.image.attr("width") / zoomInfos.imageSize.width;
+			var y = zoomInfos.currentViewBox[1] * this.image.attr("height")/ zoomInfos.imageSize.height;
 			this.handler.transform( "T" + [x, y]);
 		} 
 	}
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/src/components/zoomview/template.html	Tue Jul 26 14:26:12 2016 +0200
@@ -9,12 +9,12 @@
 			y="0" 
 			xmlns:xlink="http://www.w3.org/1999/xlink" 
 			:xlink:href="imageUrl" 
-			:width="width" 
-			:height="height"></image>
-		<rect v-show="showHandler" id="zoom-handler" ref="handler" x="0" y="0" style="fill:orange; opacity:0.7"></rect>
+			:width="imageWidth" 
+			:height="imageHeight"></image>
+		<rect v-show="showHandler" id="zoom-handler" ref="handler" x="0" y="0" style="fill:black; opacity:0.4"></rect>
 	</svg>
 
-	<ul class="form-drawing-wrapper list-inline">
+	<ul class="form-drawing-wrapper zoom-action-list list-inline">
 		<li class="small showPointer" @click="incraseDrawingZoom"><i class="fa fa-search-plus"></i> </li>
 		<li class="small showPointer" @click="resetDrawingZoom"><i class="fa fa-square"></i> </li>
 		<li class="small showPointer" @click="decreaseDrawingZoom"><i class="fa fa-search-minus"></i> </li>
--- a/src/iconolab/static/iconolab/js/iconolab-bundle/webpack.config.js	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/static/iconolab/js/iconolab-bundle/webpack.config.js	Tue Jul 26 14:26:12 2016 +0200
@@ -53,7 +53,8 @@
     }),
     new webpack.optimize.UglifyJsPlugin({
       compress: {
-        warnings: false
+        warnings: false,
+        minimize: true
       }
     }),
     new webpack.optimize.OccurenceOrderPlugin()
--- a/src/iconolab/templates/iconolab/change_annotation.html	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/templates/iconolab/change_annotation.html	Tue Jul 26 14:26:12 2016 +0200
@@ -7,7 +7,11 @@
 {% block content %}
 
 	<div id="drawing-zone" class="row" style="padding-top: 10px; padding-bottom: 10px; border:1px solid orange">
+		
 		<div v-show='!formView' style="display:none" class="editor-wrapper col-md-12">
+			<div class="col-md-12 no-padding">
+				<p @click="cancel" class="btn btn-link pull-right"><i class="fa fa-close"></i> Annuler</p>
+			</div>
 			<div class='col-md-2'>
 				<ul class="form-drawing-wrapper list-inline">
 					<p class='form-drawing pullright'><strong>Type de dessin</strong></p>
@@ -16,7 +20,7 @@
 				</ul>
 
 				{% thumbnail image.media "100x100" crop=False as im %}
-					<zoomview ref="zoomview" :image-url="'{{ im.url }}'" :width="{{ im.width }}" :height="{{ im.height }}">
+					<zoomview ref="zoomview" :image-url="'{{ im.url }}'" :image-width="{{ im.width }}" :image-height="{{ im.height }}">
 					</zoomview>
 				{% endthumbnail %}
 
@@ -29,21 +33,16 @@
 				</ul>
 			</div>
 			
-			<div class="col-md-8">
+			<div class="col-md-10">
 				<div ref="image" id="iconolab-image-wrapper">
 					{% thumbnail image.media "835x835" crop=False as im %}
-						<svg class="cut-canvas">
+						<svg class="cut-canvas" width="850" height="850">
 							<image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
 	    					<path class="image-path" d="{% if annotation %}{{ annotation.current_revision.fragment }}{% endif %}"></path>
 	    				</svg>
 					{% endthumbnail %}
 				</div>
 			</div>
-
-			<div class="col-md-2">
-				<a @click="cancel"><i class="fa fa-close"></i> Annuler</a>
-			</div>
-
 		</div>
 
 		<div v-show="formView" class="col-md-12">
--- a/src/iconolab/templates/iconolab/detail_annotation.html	Fri Jul 22 17:33:48 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_annotation.html	Tue Jul 26 14:26:12 2016 +0200
@@ -50,28 +50,22 @@
         </div>
         <!-- zoomView -->
         <div class="col-md-12 zoom-view" style="display:none" v-show="showZoom">
-          
+          <div class="col-md-12 no-padding"><p @click="toggleZoomView" class="btn btn-link pull-right"><i class="fa fa-close"></i></i> Fermer</p></div>
           <div class="col-md-2">
             {% thumbnail annotation.image.media "100x100" crop=False as im %}
-            <zoomview ref="zoomview" :zoomtarget="'zoomTarget'" :image-url="'{{ im.url }}'" :width="{{ im.width }}" :height="{{ im.height }}"></zoomview>
+            <zoomview ref="zoomview" main-image-id="main-image" zoomtarget="zoomTarget" :image-url="'{{ im.url }}'" :image-width="{{ im.width }}" :image-height="{{ im.height }}"></zoomview>
             {% endthumbnail %}
           </div>
-  
-          <div class="col-md-8">
-            {% thumbnail annotation.image.media "900x900" crop=False as im %}
-              <svg id="zoomTarget" ref="zoomTarget" width="{{ im.width }}" height="{{ im.height }}">
-                <image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
+          <div class="col-md-10 zoomTarget-wrapper">
+            {% thumbnail annotation.image.media "835x835" crop=False as im %}
+              <svg id="zoomTarget" ref="zoomTarget" width="920" height="920"> 
+                <image id="main-image" class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
                 <g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
                   <path d="{{ annotation.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
                 </g>
               </svg>
             {% endthumbnail %}
             </div>
-            <div class="col-md-2">
-              <p class="showPointer" @click="toggleZoomView">
-              <i class="fa fa-close"></i>Voir le détail</p>
-            
-            </div>
           </div>
 
 		</div>