src_js/iconolab-bundle/src/components/cutout/snapsvg-zoom.js
author ymh <ymh.work@gmail.com>
Thu, 02 Aug 2018 16:15:39 +0200
changeset 593 f8310b7ddef0
parent 146 f912b591e1c1
permissions -rw-r--r--
Added tag 0.1.10 for changeset a87ffe8e08e5

/* enable zoom */
import { eventEmitter } from '../utils'

class ZoomHandler {

	constructor (params) {
		this.zoomFactor = 0.1 || params.zoomFactor;
		this.paper = params.paper;
		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.imgMinSize = Math.min(this.imageWidth, this.imageHeight);
		this.lastPosition = []; 
		this.updateViewBox([0 , 0, this.imageWidth, this.imageHeight]);
	}

	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 () {

		/* 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.imgMinSize - (this.imgMinSize * scaleFactor);  
		var viewBoxH = viewBoxW;
		
		this.currentViewBox[0] = currentCenterX - viewBoxW / 2;
		this.currentViewBox[1] = currentCenterY - viewBoxH / 2;

		this.currentViewBox[2] = viewBoxW;
		this.currentViewBox[3] = viewBoxH;
		this.scale ++;
		this.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,
			"currentScale": this.scale,
			"imageSize": {width: this.imageWidth, height: this.imageHeight}, 
			"minSize": Math.min(this.imageWidth, this.imageHeight),
			"currentViewBox": this.currentViewBox.slice()
		});
	}
	
	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.imageWidth, this.imageHeight];
		this.updateViewBox();
	}

	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 scaleFactor = this.zoomFactor * (this.scale - 1);

		var viewBoxW = this.imgMinSize - (this.imgMinSize * scaleFactor);
		var viewBoxH = viewBoxW;

		var topX = currentCenterX - viewBoxW / 2;
		var topY = currentCenterY - viewBoxH / 2;

		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--;
	}
}

export default {

	enable_zoom: function (params) {
		return new ZoomHandler(params);
	}
}