一、前言:

上一篇随笔中已经把拖动程序完成了,这篇主要把缩放程序完成,后面合并后可以做成一个图片裁剪的功能

简易缩放程序DEMO:http://jsfiddle.net/UN99R/
限制缩放程序DEMO:http://jsfiddle.net/kHWQZ/

二、设计思路:

1、在一个可以缩放元素中,共有8个触发点(上、下、左、右、左上、右上、左下、右下),首先分别设置好它们的CSS属性cursor值。

2、同拖放程序一样,在触发点上绑定鼠标按下事件,在文档(document)上绑定鼠标移动、弹起事件处理程序,在移动事件中,完成拖放元素css的操作,
在鼠标弹起事件中,解绑移动事件处理程序。

主要难点:在于如何处理拖放元素的CSS属性

三、源码实现细节:

在8个触发点的事件处理程序中,diffX, diffY 分别获取的是鼠标在移动与按下过程时指针的差值

var diffX = e.clientX - clientX, // 负数代表向左移动,反之向右
diffY = e.clientY - clientY; // 负数代表想上移动,反之向下

在鼠标按下事件处理中,w, h, l, t 分别记录的是拖放元素的width, height, left, top 属性值,下面讲一下鼠标移动处理程序
举一个示例:

up事件程序代码:

up = function(e){
var diffY = e.clientY - clientY;
$target.css({
height: h - diffY + 'px',
top: t + Math.min(diffY, h) + 'px'
});
e.preventDefault();
};

1、在up事件程序中,拖放元素变动的是height, top属性;

2、如果鼠标向上移动,diffY为负数,而height应增,因此 height = h - diffY, top则相反,top = t + diffY;

3、反之,diffY为正数,而height应减,因此 height = h - diffY, top = t + diffY;

4、为了让top值不为负数,top = t + Math.min(diffY, h);

最后阻止默认浏览器事件,避免鼠标拖动过程中出现禁止icon

处理完up事件后,其他down, left, right事件处理同理,而后 upLeft, upRight, downLeft, downRight 这些事件处理都是在叠加前四个事件处理就行了

主程序代码:

jQuery.fn.extend({
/**
* Autor: 博客园华子yjh 2014/02/26
*/
resize: function(options) {
var controlSelector = '.cursor-north, .cursor-south, .cursor-west, .cursor-east,' +
'.cursor-north-west, .cursor-north-east, .cursor-south-west, .cursor-south-east';
$(this).each(function(){
var
// 上、下、左、右、左上、右上、左下、右下 八个点的鼠标拖动时的事件处理程序
up, down, left, right, upLeft, upRight, downLeft, downRight, // 鼠标拖动时的事件处理程序
handleEvent, // 记录鼠标按下时鼠标的位置
clientX, clientY, // 记录鼠标按下时元素的大小及位置
w, h, l, t, // 目标元素
$target = $(this), self = this; up = function(e){
var diffY = e.clientY - clientY;
$target.css({
height: h - diffY + 'px',
top: t + Math.min(diffY, h) + 'px'
});
e.preventDefault();
};
down = function(e){
var diffY = e.clientY - clientY;
$target.css({
height: h + diffY + 'px'
});
e.preventDefault();
};
left = function(e){
var diffX = e.clientX - clientX;
$target.css({
width: w - diffX + 'px',
left: l + Math.min(diffX, w) + 'px'
});
e.preventDefault();
};
right = function(e){
var diffX = e.clientX - clientX;
$target.css({
width: w + diffX + 'px'
});
e.preventDefault();
};
upLeft = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
height: h - diffY + 'px',
top: t + Math.min(diffY, h) + 'px',
width: w - diffX + 'px',
left: l + Math.min(diffX, w) + 'px'
});
e.preventDefault();
};
upRight = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
height: h - diffY + 'px',
top: t + Math.min(diffY, h) + 'px',
width: w + diffX + 'px'
});
e.preventDefault();
};
downLeft = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
width: w - diffX + 'px',
left: l + Math.min(diffX, w) + 'px',
height: h + diffY + 'px'
});
e.preventDefault();
};
downRight = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
width: w + diffX + 'px',
height: h + diffY + 'px'
});
e.preventDefault();
}; $target.delegate(controlSelector, 'mousedown', function(e){
var className = $(this).attr('class');
clientX = e.clientX;
clientY = e.clientY; w = $target.width(),
h = $target.height(),
l = $target.get(0).offsetLeft,
t = $target.get(0).offsetTop; // 根据触发元素的className选择要触发的事件处理程序
switch (className) {
case 'cursor-north':
handleEvent = up;
break; case 'cursor-south':
handleEvent = down;
break; case 'cursor-west':
handleEvent = left;
break; case 'cursor-east':
handleEvent = right;
break; case 'cursor-north-west':
handleEvent = upLeft;
break; case 'cursor-north-east':
handleEvent = upRight;
break; case 'cursor-south-west':
handleEvent = downLeft;
break; case 'cursor-south-east':
handleEvent = downRight;
break; default:
break;
} $(document)
.bind('mousemove', handleEvent)
.bind('mouseup', function(){
$(document).unbind('mousemove', handleEvent);
$target.removeData('data-resize'); // 移除标志
});
$target.data('data-resize', true); // 缓存标志
});
});
return this;
}
});

带限制范围缩放代码:

jQuery.fn.extend({
/**
* Autor: 博客园华子yjh 2014/02/26
*/
resize: function(options) {
var defaultOptions, boundaryElem, limitObj, controlSelector;
controlSelector = '.cursor-north, .cursor-south, .cursor-west, .cursor-east, .cursor-north-west, .cursor-north-east, .cursor-south-west, .cursor-south-east';
defaultOptions = { // 默认配置项
boundaryElem: 'body' // 边界容器
};
options = jQuery.extend( defaultOptions, options || {} );
boundaryElem = $(options.boundaryElem).get(0);
limitObj = {
_left: boundaryElem.offsetLeft,
_top: boundaryElem.offsetTop,
_right: boundaryElem.offsetLeft + boundaryElem.clientWidth,
_bottom: boundaryElem.offsetTop + boundaryElem.clientHeight
}; $(this).each(function(){
var up, down, left, right, upLeft, upRight, downLeft, downRight,
clientX, clientY, w, h, l, t,
$target = $(this), self = this,
handleEvent = function(){}; up = function(e){
var diffY = e.clientY - clientY;
$target.css({
height: h + Math.min(0 - diffY, t) + 'px',
top: Math.max(t + Math.min(diffY, h), 0) + 'px'
});
e.preventDefault();
};
down = function(e){
var diffY = e.clientY - clientY;
$target.css({
height: h + Math.min(diffY, limitObj._bottom - limitObj._top - t - h) + 'px'
});
e.preventDefault();
};
left = function(e){
var diffX = e.clientX - clientX;
$target.css({
width: w + Math.min(0- diffX, l) + 'px',
left: Math.max(l + Math.min(diffX, w), 0) + 'px'
});
e.preventDefault();
};
right = function(e){
var diffX = e.clientX - clientX;
$target.css({
width: w + Math.min(diffX, limitObj._right - limitObj._left - l - w) + 'px'
});
e.preventDefault();
};
upLeft = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
height: h + Math.min(0 - diffY, t) + 'px',
top: Math.max(t + Math.min(diffY, h), 0) + 'px',
width: w + Math.min(0- diffX, l) + 'px',
left: Math.max(l + Math.min(diffX, w), 0) + 'px'
});
e.preventDefault();
};
upRight = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
height: h + Math.min(0 - diffY, t) + 'px',
top: Math.max(t + Math.min(diffY, h), 0) + 'px',
width: w + Math.min(diffX, limitObj._right - limitObj._left - l - w) + 'px'
});
e.preventDefault();
};
downLeft = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
width: w + Math.min(0- diffX, l) + 'px',
left: Math.max(l + Math.min(diffX, w), 0) + 'px',
height: h + Math.min(diffY, limitObj._bottom - limitObj._top - t - h) + 'px'
});
e.preventDefault();
};
downRight = function(e){
var diffX = e.clientX - clientX,
diffY = e.clientY - clientY;
$target.css({
width: w + Math.min(diffX, limitObj._right - limitObj._left - l - w) + 'px',
height: h + Math.min(diffY, limitObj._bottom - limitObj._top - t - h) + 'px'
});
e.preventDefault();
}; $target.delegate(controlSelector, 'mousedown', function(e){
var className = $(this).attr('class');
clientX = e.clientX;
clientY = e.clientY; w = $target.width(),
h = $target.height(),
l = $target.get(0).offsetLeft,
t = $target.get(0).offsetTop; switch (className) {
case 'cursor-north':
handleEvent = up;
break; case 'cursor-south':
handleEvent = down;
break; case 'cursor-west':
handleEvent = left;
break; case 'cursor-east':
handleEvent = right;
break; case 'cursor-north-west':
handleEvent = upLeft;
break; case 'cursor-north-east':
handleEvent = upRight;
break; case 'cursor-south-west':
handleEvent = downLeft;
break; case 'cursor-south-east':
handleEvent = downRight;
break; default:
break;
}
$(document)
.bind('mousemove', handleEvent)
.bind('mouseup', function(){
$(document).unbind('mousemove', handleEvent);
$target.removeData('data-resize'); // 移除标志
});
$target.data('data-resize', true); // 缓存标志
})
});
return this;
}
});

PS: 如有描述错误,请帮忙指正,如果你们有不明白的地方也可以发邮件给我,

  如需转载,请附上本文地址及出处:博客园华子yjh,谢谢!

JavaScript简易缩放程序的更多相关文章

  1. JavaScript简易教程(转)

    原文:http://www.cnblogs.com/yanhaijing/p/3685304.html 这是我所知道的最完整最简洁的JavaScript基础教程. 这篇文章带你尽快走进JavaScri ...

  2. JavaScript简易教程

    这是我所知道的最完整最简洁的JavaScript基础教程. 这篇文章带你尽快走进JavaScript的世界——前提是你有一些编程经验的话.本文试图描述这门语言的最小子集.我给这个子集起名叫做“Java ...

  3. J2msi 自己制作的把exe打成安装包简易GUI程序(第二版 带DLL注册)

    J2msi 自己制作的把exe打成安装包简易GUI程序(第二版 带DLL注册) 之前那一版本(http://www.cnblogs.com/rojas/p/4794684.html)没考虑 DLL 注 ...

  4. JavaScript中国象棋程序(0) - 前言

    “JavaScript中国象棋程序” 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.希望通过这个系列,我们对博弈程序的算法有一定的了解.同时,我们也将构建出一个不错的中国象棋程序 ...

  5. JavaScript中国象棋程序(1) - 界面设计

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第1节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  6. JavaScript中国象棋程序(2) - 校验棋子走法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第2节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  7. JavaScript中国象棋程序(3) - 电脑自动走棋

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第3节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  8. JavaScript中国象棋程序(4) - 极大极小搜索算法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第4节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  9. JavaScript中国象棋程序(5) - Alpha-Beta搜索

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第5节. 这一系列共有9个部分: 0.JavaScript中国象 ...

随机推荐

  1. [CareerCup] 7.7 The Number with Only Prime Factors 只有质数因子的数字

    7.7 Design an algorithm to find the kth number such that the only prime factors are 3,5, and 7. 这道题跟 ...

  2. linux实践——简单程序破解

    一.运行login可执行程序,屏幕显示需要输入密码,随便输入一串字符,结果是Drop dead! 二.objdump -d login,对login进行反汇编,找到main函数,找到含有scanf的那 ...

  3. 使用IDEA进行代码托管

    在idea菜单栏的file中打开settings/搜索git,配置path to Git executable:C:\Program Files\Git\bin\git.exe(git bash的安装 ...

  4. 数据挖掘系列(2)--关联规则FpGrowth算法

    上一篇介绍了关联规则挖掘的一些基本概念和经典的Apriori算法,Aprori算法利用频繁集的两个特性,过滤了很多无关的集合,效率提高不少,但是我们发现Apriori算法是一个候选消除算法,每一次消除 ...

  5. PHP+MD5

    echo substr(md5("admin"),8,16);//16位MD5加密,16位加密是32位加密从第8个字符开始到16个字符,用substr函数截取了字符得到.. ech ...

  6. SQL Server 2008 过期

    最近SQL Serve 2008 过期,不能正常运行,通过如下方式解决此问题: (1) 修改注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQ ...

  7. 使用Nginx解决IIS绑定域名导致应用程序重启的问题

    在将多个站点迁移到一个站点(Tenant Feature)的时候碰到了一个棘手的问题,用户需要绑定自定义域名,但IIS绑定域名的时候会导致这个站点重启,那么只要一个用户绑定了一个域名则会导致这个应用上 ...

  8. 程序员的出路在哪里?挣钱的机会来了续-福利来了,仿QQ界面,放出全部源码,打造创业框架及实现思路

    上一篇:程序员的出路在哪里?挣钱的机会来了!, 原来搞技术,挣钱,不一定非得要多高精尖,有时候抓住小白用户,解决他们一个很小但是很常用的功能,也是一条很好的出路. 其实很多软件产品,要实现出来没有你想 ...

  9. javascript基础知识拾遗

    1 下面列出的值被当作假 false null undefined '' 0 NaN 其它所有值被当作是真 console.log(undefined || true); //true console ...

  10. centos 6.5下安装mysql+nginx+redmine 3.1.0 笔记

    centos 6.5下安装mysql+nginx+redmine 3.1.0 笔记 目录[-] 过程 1.安装RVM 2.利用rvm安装 Ruby 1.9.3 并设为默认 3.安装rails 4.安装 ...