/**
* starZoom jquery扩展
* date: 2015-6-3
* canvas实现 图片移动缩放 旋转 效果
*
* 参数可用 data-options 及 starZoom({}) 形参两种形式
*
* ///////
* <div class="iamge_wrap">
* <img src="" class="star_zoom" data-options="{'width':400,'height':300}">
* </div>
*
* $(".star_zoom").starZoom();
* //////
*
*/
(function ($) {
var Events = {
REDRAW: 'redraw',
MOUSE_WHEEL: 'mousewheel',
MOUSE_DOWN: 'mousedown',
MOUSE_UP: 'mouseup',
MOUSE_MOVE: 'mousemove',
};
/**
* 类定义
* @param options
* @constructor
*/
var StarZoom = function (options) {
this.$s = -1; //当前操作的imgDOM
this.$wrapper = -1;
this.$canvas = -1;
this.$blank = -1; //appended DOM object
this.backgroundColor = 'white'; //canvas background
this.ctx = -1; //canvas context
this.img = -1;
this.ratio = 0; //image dom image ratio
this.width = 0;
this.height = 0; //canvas width height
this.mouseIsDown = false;
this.ow = 0;
this.oh = 0; //image original width height
this.sx = 0;
this.sy = 0;
this.sw = 0;
this.sh = 0;
this.dx = 0;
this.dy = 0; //drawImage()
this.dw = 0;
this.dh = 0; //drawImage()
this.mouseX = 0;
this.mouseY = 0; //mouse position
this.zoomStep = 30;
this.minWidth = 50;
this.centerx = 0;
this.centery = 0;
this.olddw = 0;
this.olddh = 0;
this.degree = 0; //旋转的角度
this.btnRotateLeft = '.btn_rotate_left'; //向左转class
this.btnRotateRight = '.btn_rotate_right';
this.btnZoomIn = '.btn_zoom_in'; //放大按钮
this.btnZoomOut = '.btn_zoom_out'; //缩小按钮
this.initialize(options);
};
StarZoom.prototype = {
initialize: function (options) {
var self = this;
$.extend(this, options);
self.img = new Image();
self.img.onload = function () {
self.ow = self.img.width;
self.oh = self.img.height;
self.initDom(); //初始化所需DOM
self.bindEvents(); //绑定相关事件
self.ctx = self.$canvas[0].getContext('2d');
self.initImage(); //初始化图片绘制
};
self.img.src = this.$s.attr('src');
},
bindEvents: function () {
var self = this;
//空白层 mouse wheel down up move事件
self.$blank.on(
Events.MOUSE_WHEEL +
' ' +
Events.MOUSE_DOWN +
' ' +
Events.MOUSE_UP +
' ' +
Events.MOUSE_MOVE,
function (e) {
switch (e.type) {
case Events.MOUSE_MOVE:
self.handleBlankMouseMove(e);
break;
case Events.MOUSE_DOWN:
self.mouseX = e.pageX;
self.mouseY = e.pageY;
self.mouseIsDown = true;
self.$blank.css({ cursor: 'move' });
//console.log(e.pageX - self.$canvas.offset().left);
break;
case Events.MOUSE_UP:
self.mouseIsDown = false;
self.$blank.css({ cursor: 'auto' });
break;
case Events.MOUSE_WHEEL:
e.preventDefault();
self.handleBlankMouseWheel(e);
break;
}
}
);
//绑定重绘事件
self.$canvas.bind(Events.REDRAW, function () {
self.ctx.fillStyle = self.backgroundColor;
self.ctx.fillRect(0, 0, self.width, self.height); //重置背景
self.getCenter(); //获取图片中心在canvas上的坐标值
self.ctx.save();
self.ctx.translate(self.centerx, self.centery); //参考点移动到图片中心
self.ctx.rotate((self.degree * Math.PI) / 180); //旋转
self.ctx.translate(-self.centerx, -self.centery); //重置参考点
self.ctx.drawImage(
self.img,
self.sx,
self.sy,
self.sw,
self.sh,
self.dx,
self.dy,
self.dw,
self.dh
);
self.ctx.restore();
});
var $parent = self.$s.parent();
$parent.find(self.btnRotateLeft).on('click', function () {
self.degree -= 90;
self.redraw();
});
$parent.find(self.btnRotateRight).on('click', function () {
self.degree += 90;
self.redraw();
});
$parent.find(self.btnZoomIn).on('click', function () {
self.olddw = self.dw;
self.olddh = self.dh;
self.resizeByDelta(1, 0.5, 0.5);
self.redraw();
});
$parent.find(self.btnZoomOut).on('click', function () {
self.olddw = self.dw;
self.olddh = self.dh;
self.resizeByDelta(-1, 0.5, 0.5);
self.redraw();
});
},
//获取当前图片中心点坐标 相对canvas
getCenter: function () {
var self = this;
self.centerx = self.dw / 2 + self.dx;
self.centery = self.dh / 2 + self.dy;
},
//初始化图片绘制
initImage: function () {
var self = this;
self.ratio = self.ow / self.oh;
self.sh = self.oh;
self.sw = self.ow;
if (self.width >= self.height) {
//显示区域宽大与高
self.initByHeight();
if (self.dw > self.width) {
self.initByWidth();
}
} else {
self.initByWidth();
if (self.dh > self.height) {
self.initByHeight();
}
}
self.redraw();
self.$canvas.stop(true, false).animate({ opacity: 1 }, 1500, 'linear');
},
//鼠标移动事件
handleBlankMouseMove: function (e) {
var self = this;
if (!self.mouseIsDown) return;
self.dx += e.pageX - self.mouseX;
self.dy += e.pageY - self.mouseY;
self.mouseX = e.pageX;
self.mouseY = e.pageY;
self.redraw();
},
//滚轮事件
handleBlankMouseWheel: function (e) {
var self = this,
delta,
posx,
posy,
deltax = 0.5,
deltay = 0.5;
self.olddw = self.dw;
self.olddh = self.dh;
if (e.deltaY > 0) {
delta = 1;
} else {
delta = -1;
}
posx = Math.abs(e.pageX - self.$canvas.offset().left - self.dx);
posy = Math.abs(e.pageY - self.$canvas.offset().top - self.dy);
deltax = posx / self.olddw;
deltay = posy / self.olddh;
self.resizeByDelta(delta, deltax, deltay);
self.redraw();
},
resizeByDelta: function (delta, deltax, deltay) {
var self = this;
self.dw += delta * self.zoomStep;
self.dw = self.dw < self.minWidth ? self.minWidth : self.dw;
self.dh = self.dw / self.ratio;
self.dx -= delta * Math.abs(self.olddw - self.dw) * deltax;
self.dy -= delta * Math.abs(self.olddh - self.dh) * deltay;
},
//触发重绘事件
redraw: function () {
this.$canvas.trigger(Events.REDRAW);
},
//以高为准定位图片位置
initByHeight: function () {
var self = this;
self.dh = self.height;
self.dw = self.dh * self.ratio;
self.dy = 0;
self.dx = (self.width - self.dw) / 2;
},
//以宽为准定位
initByWidth: function () {
var self = this;
self.dw = self.width;
self.dh = self.dw / self.ratio;
self.dx = 0;
self.dy = (self.height - self.dh) / 2;
},
//初始化所需的DOM
initDom: function () {
var self = this;
self.$wrapper = $('<div class="star_zoom sw"></div>');
self.$canvas = $('<canvas class="star_zoom sc"></canvas>');
self.$blank = $(
'<div class="star_zoom sl" unselectable="on"></div>'
);
self.$canvas
.css({
position: 'absolute',
top: 0,
left: 0,
zIndex: 100,
opacity: 0,
})
.attr({ width: self.width, height: self.height })
.appendTo(self.$wrapper);
self.$blank
.css({
width: self.width + 'px',
height: self.height + 'px',
position: 'absolute',
top: 0,
left: 0,
zIndex: 110,
})
.appendTo(self.$wrapper);
self.$wrapper
.css({
width: self.width + 'px',
height: self.height + 'px',
overflow: 'hidden',
position: 'relative',
})
.appendTo(self.$s.css({ display: 'none' }).parent());
},
};
///////添加到jquery扩展
$.fn.starZoom = function (args) {
$.each(this, function (i, n) {
var $s = $(n);
var options = $s.data('options');
options = !options ? {} : $.parseJSON(options.replace(/'/gi, '"'));
if (typeof args == 'object') {
options = $.extend(args, options);
}
options.$s = $s;
new StarZoom(options);
});
return this;
};
})(jQuery);