/** * 弹出层图片放大缩小 ImageMoveable(selector) * ======================================== * * 实现描述:点击页面相关dom出现弹出框进行相关图片缩放移动等细节查看 * dependency: * [jQuery](http://jquery.com/) * [underscore](http://underscorejs.org/) * [Backbone.js](http://backbonejs.org/) * * author: MeanOfWind * QQ: 316841740 * created time: 2014.6.12 * * * dom标签属性: * tagName: any * id: any (not required) * class: any 如果页面有多个图片处理传递class 程序会遍历所有的对象单独实例化 * src: any (not required) * data-config: 配置选项 参数格式:为JSON格式 不加花括号 键名不加引号 键值如为字符串加单引号 * 可选参数: * width: 弹出框及图片宽 default 0 * height: 弹出框及图片高 default 0 * scale: 图片缩放比例 default 1/8 * src: 图片url 如果是img标签存在src属性可不用指定 *-------------------------------------------- * * 函数调用示例: * * (function($){ * $(function(){ * ImageMoveable( ".img_moveable" ); * }) * })(jQuery) * * * Tips: * 定点缩放 主要算法实现: * 缩放后图片位置(top)=图片的当前位置(top) [+ 或 -] (鼠标按下时距图片左上角距离(disX)*缩放因子(scale)) * */ (function($, _, Backbone){ //弹出框样式 var css = '.clear{clear:both;height:0;display:block}.imdia{z-index:1000;position:absolute;top:0;left:0}.imdia .dh{cursor:move;height:30px}.imdia .dh .dtit{margin:0;padding:0;display:block;float:left}.imdia .dh .btn{display:block;float:left;cursor:pointer;height:20px;line-height:20px;padding:0 10px;border-radius:3px;font-family:"微软雅黑";font-size:14px;color:#fff;background-color:#0082cb;margin:5px 5px 0}.imdia .dh .btn.zoom{background-color:#ccccd1;opacity:.5}.imdia .dh .btn.active{background-color:#0082cb;opacity:1}.imdia .dh .close{float:right}.imdia .dcon{background-color:#fff;width:100px;height:50px;position:relative;overflow:hidden;border-shadow:10px 10px 5px #888}.imdia .dcon img{display:block;position:absolute;top:0;left:0}#imdiabg{display:block;width:100%;height:100%;background-color:#000;opacity:.7;position:fixed;z-index:900;top:0;left:0}'; var gnum = 0; //保存当前实例序号 自加用于生成唯一ID var diaClassName = "imdia";// 弹出框class var bgid = diaClassName + "bg"; //弹出框背景层ID var zoomIn = true;//big 放大缩小控制 /** * 弹出框model * @type {*} */ var DialogModel = Backbone.Model.extend({ defaults:{ id: "dia_", width:0, height:0, diaheight: 0, marginLeft:0, marginTop:0, top:0, left:0 }, initialize: function(){ var app = this.get("app"); //根据当前appid 设置相关参数 this.set({id: this.get("id")+app.id}); this.set({diaheight: (this.get("height") + 30)}); this.setPosition(); }, setPosition: function(){ var scrolltop = $(window).scrollTop(); var winh = $(window).height(); var top = winh>this.get("height")? ((winh-this.get("height"))/2) : scrolltop; var scrollleft = $(window).scrollLeft(); var winw = $(window).width(); var left = winw>this.get("width")? (winw-this.get("width"))/2 : scrollleft; this.set({top: top + scrolltop}); this.set({left: left + scrollleft}); } }); /** * 图片model * @type {*} */ var ImageModel = Backbone.Model.extend({ defaults: { id: "img_", width:0, height:0, top:0, left:0, scale: 1/8, // src: '' }, initialize: function(){ var app = this.get("app"); //根据当前appid 设置相关参数 this.set({id: this.get("id")+app.id}); this.set({scale: eval(this.get("scale"))}); } }); /** * dialog view * @type {*} */ var DialogView = Backbone.View.extend({ tagName: "div", className: diaClassName, mouseDown: false, //鼠标是否按下 mouseMove: false, disX: 0, //鼠标按下位置和dialog left距离 disY: 0, //弹出框html模板 template: '<div class="dh">\ <h4 class="dtit"></h4>\ <div class="btn zoom zoom_in active">放大</div>\ <div class="btn zoom zoom_out">缩小</div>\ <div class="btn close">关闭</div><div class="clear"></div>\ </div>\ <div class="dcon"></div>\ <div class="db"></div><div class="clear"></div>', initialize: function(){ _.bindAll(this, "setPosition","dh_mousemove"); this.listenTo(this.model,"change",this.setPosition); //监听model change $("body").mousemove(this.dh_mousemove); //绑定鼠标move事件 }, events: { "click .close": "diaClose", "mousedown .dh": "dh_mousedown", "mouseup .dh": "dh_mouseup", "click .zoom_in": "zoom_in", "click .zoom_out": "zoom_out" // "mousemove .dh": "dh_mousemove" }, render: function(){ this.$el.attr("id",this.model.get("id")); this.$el.html(this.template); this.$el.find(".dcon").append(this.model.get("app").imageView.el); this.$el.css({ //dia 样式 display:"none", left: this.model.get("left")+ "px", top: this.model.get("top") + "px", width:this.model.get("width") + "px", height: this.model.get("diaheight") + "px" });//内容样式 this.$el.find(".dcon").css({ width:this.model.get("width") + "px", height: this.model.get("height") + "px" }); //console.log(this) return this; }, //关闭 diaClose: function(){ this.hide(); }, show: function(){ $("#"+bgid).css("display","block"); this.$el.show(); }, hide: function(){ $("#"+bgid).css("display","none"); this.$el.hide(); }, setPosition: function(){ this.$el.css({ top: this.model.get("top") + "px", left: this.model.get("left") + "px" }); }, //处理托动 dh_mousedown: function(e){ this.mouseDown = true; this.disX = Math.abs(e.pageX - this.model.get("left")); this.disY = Math.abs(e.pageY - this.model.get("top")); //console.log(this.disX); //console.log(this.mouseDownX) }, dh_mouseup: function(){ this.mouseDown = false; this.mouseMove = false; }, dh_mousemove: function(e){ this.mouseMove = true; //console.log(3) if(this.mouseDown){ var x = e.pageX; //当前鼠标位置 var y = e.pageY; this.model.set({top: y-this.disY}); this.model.set({left: x-this.disX}); //console.log(x-this.mouseDownX) } }, //放大 zoom_in: function(e){ zoomIn = true;// 全局变量 //改变button class切换对应颜色 this.$el.find(".zoom").removeClass("active"); $(e.target).addClass("active"); }, //缩小 zoom_out: function(e){ zoomIn = false; this.$el.find(".zoom").removeClass("active"); $(e.target).addClass("active"); } }); /** * 图片view类 * @type {*} */ var ImageView = Backbone.View.extend({ tagName:"img", disX:0, //鼠标按下时的点 离 图片左上角距离 disY:0, dconX: 0, //图片外层div dconY: 0, mouseDown: false, //鼠标没有按下 mouseMove: false, //鼠标没有移动 initialize: function(){ _.bindAll(this, "img_mouse_move","setPosition"); this.$el.attr({//设置当前image dom id及src值 id: this.model.get("id"), src: this.model.get('src') }); this.$el.css({ width: this.model.get("width") + "px", height: this.model.get("height") + "px" }); //监听鼠标移动事件 $(document).mousemove(this.img_mouse_move); this.listenTo(this.model,"change",this.setPosition); //监听model change }, render: function(){ return this; }, events: { "mousedown": "imgmousedown",//鼠标按下 "mouseup": "imgmouseup" //鼠标弹起 }, //鼠标按下具体处理 imgmousedown: function(e){ this.mouseDown = true; var $con = this.model.get("app").dialogView.$el.find(".dcon"); //dcon 左上角相对屏幕 this.dconX = $con.offset().left; this.dconY = $con.offset().top; //图片相对屏幕 var imgY = this.$el.offset().top; var imgX = this.$el.offset().left; //按下时鼠标位置 var mouseX = e.pageX; var mouseY = e.pageY; // 计算鼠标距离图片左上角距离 this.disX = Math.abs(mouseX - imgX); this.disY = Math.abs(mouseY - imgY); //console.log(disx); //console.log(this.$el.offset()) }, /** * 鼠标弹起事件具体处理 * 如果鼠标按下并未移动则进行图片缩放操作 */ imgmouseup: function(){ //console.log(2) if(this.mouseDown && !this.mouseMove){ var w = this.model.get("width");//图片当前尺寸 var h = this.model.get("height"); var scale = this.model.get("scale"); //绽放比例 var width, height,top=this.model.get("top"),//图片当前位置 left=this.model.get("left"); //定点缩放 主要算法实现 //缩放后图片位置(top) = 图片的当前位置(top) [+ 或 -] (鼠标按下时距图片左上角距离(disX)*缩放因子(scale)) if(zoomIn){ //放大 width = w+w*scale; height = h+h*scale; top = top - this.disY*scale; left = left - this.disX*scale; }else{ width = w-w*scale; height = h-h*scale; top = top + this.disY*scale; left = left + this.disX*scale; } //重设图片model数据 this.model.set({ "width":width, "height": height, top:top, left: left }); } this.mouseDown = false; this.mouseMove = false; }, //鼠标移动具体处理 img_mouse_move: function(e){ var top,left; if(this.mouseDown){ this.mouseMove = true; //或取图片相对于容器div.dcon 的top left //e.pageX: 事件触发时鼠标相对于document的坐标 //算法: 图片位置=鼠标坐标-容器坐标-鼠标在当前图片坐标系的位置 top = e.pageY - this.dconY - this.disY; left = e.pageX - this.dconX - this.disX; //console.log(left) this.model.set({top: top}); this.model.set({left: left}); } }, //根据model值重设当前图片位置及尺寸 setPosition: function(){ this.$el.css({ top: this.model.get("top") + "px", left: this.model.get("left") + "px", width: this.model.get("width") + "px", height: this.model.get("height") + "px" }); } }); /** * 主控制类 实例化相关资源 * @type {*} */ var App = Backbone.View.extend({ initialize: function(options){ _.bindAll(this,"winScroll"); this.id = "g_img_idx_" + gnum++; //设置当前操作对象单一ID options.data.app = this; //当前引用到对应实例 //Model实例 this.dialogModel = new DialogModel(options.data); //弹出框model this.imageModel = new ImageModel(options.data); //图片model //View 实例化 this.imageView = new ImageView({model:this.imageModel});//图片view this.dialogView = new DialogView({model:this.dialogModel}); //console.log(options); //console.log(this.imageView.render().el); //console.log(this.el) $(window).scroll(this.winScroll); this.render(); }, render: function(){ $("body").append(this.dialogView.render().el); }, events:{ "click": "elClick" }, //当前对象点击 elClick: function(){ this.dialogView.show(); }, //预留window sroll事件 winScroll: function(){ this.dialogModel.setPosition(); } }); //工具函数 // parse data-config attr string to json function attrToJson(data_config){ var arr = data_config.split(","); //split to array for(var i = 0; i<arr add return add andd parse to json param selector constructor imagemoveable="function(selector){" return foreach every selector the starter function var var data="attrToJson(data_config);" var src="src;" new bg mask var></div>"; var $css = "<style>"+ css +"</style>"; $("body").append(bg).append($css);//添加弹出层背景 及对应CSS样式 } })(jQuery, _, Backbone);