以前要实现图片的旋转或翻转,只能用ie的滤镜来实现,虽然canvas也实现,但ie不支持而且不是html标准。
css3出来后,终于可以用标准的transform来实现变换,而canvas也已成为html5标准的一部分。
css3和html5使web变得越来越强大,各种新奇的技术正等待我们发掘。
本程序分别通过滤镜(ie)、ccs3和canvas来实现图片的旋转、缩放和翻转变换效果,可以用作图片查看器。
有如下特色:
1,用滤镜、ccs3和canvas实现相同的变换效果;
2,可任意角度旋转;
3,可任意角度翻转;
4,可扩展滚轮缩放;
5,可扩展拖动旋转。
兼容:ie6/7/8, firefox 3.6.8, opera 10.6, safari 5.0.1, chrome 5.0

效果预览

程序说明

【基本原理】

变换主要是利用css3的变换样式transform的matrix方法来实现。
ie不支持css3,但有Matrix滤镜也能实现类似的效果。
程序还用canvas,通过画图实现相同的效果。

【模式设置】

程序包含三种模式:css3、filter和canvas,程序初始化时,会根据自定义模式进行模式设置。
各个模式相关的属性和方法都存放在ImageTrans.modes中。
每个模式对象都包含support属性,表示当前浏览器是否支持该模式,还有几个方法:
init:初始化执行程序
load:加载图片执行程序
show:变换显示程序
dispose:销毁程序

使用这样的格式来自定义模式:"css3|filter|canvas",判断过程主要在_initMode程序中:

var modes = ImageTrans.modes;
this._support = $$A.some( this.options.mode.toLowerCase().split("|"), function(mode){
    mode = modes[ mode ];
    if ( mode && mode.support ) {
        ...
        return true;
    }
}, this );

程序会按顺序逐个判断,当浏览器支持该模式时就会用该模式的方法设置程序函数。
再用_support记录浏览器是否支持指定的模式。

如果浏览器支持,才执行_initContainer容器初始化程序和_init模式初始化程序。

【加载图片】

完成初始化设置后,再执行load方法加载图片。
在load方法中,主要对图片进行设置:

img.onload || ( img.onload = this._LOAD );
img.onerror || ( img.onerror = function(){ oThis.onError("err image"); } );

最后设置src加载图片。

图片加载成功后,会执行_LOAD程序,在里面会执行_load加载程序和reset方法。
在reset中,会重置变换参数,并执行_show模式画图程序:

this._y = this._x = 1; this._radian = 0;
this._show();

这时,图片会以初始状态显示。

【图片变换】

图片加载完成后,就可以对图片进行变换。

各种变换方法保存在ImageTrans.transforms中,包括旋转、垂直翻转、水平翻转、缩放等。
变换结果是通过_y垂直变换参数、_x水平变换参数和_radian旋转变换参数计算得到的。
变换方法就是用来修改这些参数的方法。

一般的翻转是通过把_y或_x取反来实现的,是以图片本身为坐标的翻转。
但用户的习惯是按浏览器坐标来翻转的,当图片先旋转变换坐标后再翻转,就不符合用户习惯了。
为了能按视觉习惯坐标来翻转,程序使用的方法是先旋转再翻转来实现。
例如vertical垂直翻转是图片旋转180度,再进行一般的水平翻转:

this._radian = Math.PI - this._radian; this._x *= -1;

而horizontal水平翻转也类似:

this._radian = Math.PI - this._radian; this._y *= -1;

实际也是利用了一些坐标变换原理。

rotate旋转是以弧度为单位的,直接修改_radian参数。
rotatebydegress是以角度为单位的旋转,其实是用degress * Math.PI/180公式把角度转换成弧度。
left向左转90度是在原有弧度减Math.PI/2(即90度),而right向右转90度是加Math.PI/2。

scale缩放就是根据缩放比率分别对_y和_x进行修改。
程序定义了一个getZoom修正缩放比率函数:

function getZoom(scale, zoom) {
return scale > 0 && scale >-zoom ? zoom :
scale < 0 && scale < zoom ?-zoom : 0;
}

只有当比率不会导致结果是反值的情况才会返回正确的比率。
这里主要是保证缩到最小时不会因为比率太大得到反值,导致图片翻转并放大。
当垂直和水平比率都不是0,才会对参数进行修改:

var hZoom = getZoom( this._x, zoom ), vZoom = getZoom( this._y, zoom );
if ( hZoom && vZoom ) {
this._x += hZoom; this._y += vZoom;
}

这样可以保证水平和垂直缩放同时进行,保持图片比例。
要注意zoomin放大时要保证缩放比率为正数,zoomout缩小就要负数。

这些方法会在模式设置中扩展到程序中:

$$A.forEach( ImageTrans.transforms, function(transform, name){
this[ name ] = function(){
transform.apply( this, [].slice.call(arguments) );
this._show();
}
}, this );

在执行完变换方法后,就会执行_show来显示变换。

【transform】

变换换流程介绍完,就进入主题,介绍三个变换方法了。
先看看css3的transform,它包含以下变换方法:
matrix:矩阵变形,使用它就可以做到后面所有的变换,但使用相对麻烦;
translate/translateX/translateY:坐标变换,就是移动坐标的意思;
scale/scaleX/scaleY:缩放变换,放大缩小,取负值可以做翻转;
rotate:旋转变换,根据角度旋转;
skew/skewX/skewY:拉扯变换,就是上下或左右向不同的方向扯开的效果。
更详细的介绍请看w3c的CSS 2D Transforms或者MDC的-moz-transform。

要进行变换,首先要看看浏览器是否支持:

var style = document.createElement("div").style;
return $$A.some(
[ "transform", "MozTransform", "webkitTransform", "OTransform", "msTransform" ],
function(css){ if ( css in style ) {
css3Transform = css; return true;
}});

由于程序运行时文档可能还没载入,所以要手动创建一个元素来测试。
虽然w3c标准使用的是transform,但现阶段各浏览器还是需要各自的前缀。
当元素样式包含其中一个变换样式,说明该浏览器支持,再用css3Transform记录样式名字。

在css3模式的init程序中,会执行initImg方法对图片进行设置:

$$D.setStyle( img, {
position: "absolute",
border: 0, padding: 0, margin: 0, width: "auto", height: "auto",
visibility: "hidden"
});
container.appendChild( img );

主要是设置绝对定位、隐藏和重置样式,最后插入容器。
ps:图片对象虽然是用new Image()创建的,但也可以当作img元素来操作。

在load加载程序中,再对图片样式进行设置:

$$D.setStyle( img, {
top: ( this._clientHeight - img.height ) / 2 + "px",
left: ( this._clientWidth - img.width ) / 2 + "px",
visibility: "visible"
});

设置left和top使图片在容器里居中,并显示图片。

关键的show程序,用来进行图片变换,这里用的是matrix变换。
matrix有6个参数,前4个是矩阵变换参数,后两个是坐标变换参数。
要根据弧度旋转,可以这样设置矩阵:
cos(a) -sin(a)
sin(a) cos(a)
而缩放变换就这样设置:
sx 0
0 sy
旋转同时缩放,矩阵相乘得到:
cos(a)*sx -sin(a)*sy
sin(a)*sx cos(a)*sy
关于Matrix矩阵变换可以看w3c的Transform Matrix。

getMatrix函数就是通过以上矩阵计算matrix参数:

var Cos = Math.cos(radian), Sin = Math.sin(radian);
return {
M11: Cos * x, M12:-Sin * y,
M21: Sin * x, M22: Cos * y
};

在show程序里面,用getMatrix得到参数后,就可以设置样式:

this._img.style[ css3Transform ] = "matrix("
+ matrix.M11 + "," + matrix.M21 + ","
+ matrix.M12 + "," + matrix.M22 + ", 0, 0)";

在实际使用中,使用matrix可能要设置一堆可读性很差的数字,所以还是推荐用其他变换方法。

【Matrix滤镜】

ie的Matrix滤镜跟css3的matrix差不多,也能实现类似的变换。
Matrix滤镜有以下属性:
Dx/Dy:坐标变换参数;
enabled:是否可用;
FilterType:定义新内容的像素的方法;
M11/M12/M21/M22:矩阵变换参数;
SizingMethod:容器是否改变尺寸去适应目标图像。
详细参考msdn的Matrix Filter和中文Matrix说明。

判断浏览器是否支持,也是创建一个div,看它有没有"filters"属性:

function(){ return "filters" in document.createElement("div"); }()

在init程序中也用initImg方法对图片进行设置,此外还需要设置Matrix滤镜:

this._img.style.filter = "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand')";

这里会设置SizingMethod属性,它有两个值,分别是:clip to original(容器不改变尺寸)和auto expand(容器改变尺寸以适应目标图像)。
如果使用默认值clip to original,容器的大小不会变,那么变换时超出容器的部分就会隐藏不见,所以这里要设为'auto expand'才能完整显示图片。

在load程序中显示图片,为了防止ie重复加载gif的bug还要重置onload为null。
ps:该bug的研究可以参考这里的显示预览部分。

而show程序也跟css3模式类似,通过getMatrix方法获取变换参数,并设置到滤镜中:

$$.extend(
img.filters.item("DXImageTransform.Microsoft.Matrix"),
getMatrix( this._radian, this._x, this._y )
);

滤镜使用了'auto expand'后,变换时图片元素尺寸会随着内容变化,所以要重新设置居中:

img.style.top = ( this._clientHeight - img.offsetHeight ) / 2 + "px";
img.style.left = ( this._clientWidth - img.offsetWidth ) / 2 + "px";

ie还有其他变换滤镜,例如FlipH(水平翻转)、FlipV(垂直翻转)、Wave(扭曲)等。

【canvas】

通过滤镜和css3已经能在主流的浏览器上兼容实现相同的变换,最后再用canvas来实现。
canvas是一个用来绘制图形的元素,它最强大的地方在于结合js来绘制图形甚至制作动画和游戏。
ps:这里推荐几个入门文章:Opera的HTML 5 canvas和深入了解canvas标签系列。

要知道浏览器是否支持canvas,可以创建一个canvas元素,看它是否有"getContext"方法来判断:

function(){ return "getContext" in document.createElement('canvas'); }()

getContext方法用来获取渲染空间(也叫上下文),之后会在这个空间绘图,相当于获取画布。

在init程序中,创建并设置canvas及其上下文context:

var canvas = this._canvas = document.createElement('canvas'),
context = this._context = canvas.getContext('2d');
$$D.setStyle( canvas, { position: "absolute", left: 0, top: 0 } );
canvas.width = this._clientWidth; canvas.height = this._clientHeight;
this._container.appendChild(canvas);

程序中只需要2D canvas,所以用getContext('2d')就行了。
ps:关于3D canvas在Opera的HTML 5 canvas有相关的介绍。
还需要设置尺寸,这里要注意要用width和height来设置,我试过用样式来设置,结果画图不正常。

在show程序中进行变换和画图:

context.save();
context.clearRect( 0, 0, clientWidth, clientHeight );
context.translate( clientWidth / 2 , clientHeight / 2 );
context.rotate( this._radian );
context.scale( this._x, this._y );
context.drawImage( img, -img.width / 2, -img.height / 2 );
context.restore();
这里用到了canvas几种方法:
save:保存状态;
clearRect:清除画布;
translate:水平/垂直移动坐标;
rotate:旋转坐标;
scale:缩放坐标;
drawImage:插入图像;
restore:恢复状态。

canvas没有直接清除整个画布的方法,只能用clearRect来间接实现。
它的四个参数用来定义一个矩形,只要定义一个画布大小的矩形就能清除整个画布了。

在canvas里面没有left/top,位置的变换只能用translate来设置,程序用它把坐标移到画布中心。
canvas没有Matrix那样的东西,只能用rotate和scale来变换,用法跟css3的类似。
canvas也没有css3的skew(拉扯)变换。

最后用drawImage画图,可以是img元素、Image对象或Canvas元素,另外两个参数是画图位置,程序用它来居中图像。

每次画图都可能会改变坐标,下次想还原坐标来画图要逐个恢复会很麻烦,这时应该用save和restore来保存和还原状态。
save和restore能保存和还原包括translate、rotate、scale变换后的画布状态,常常配合clearRect来做动画。

除了以上方法,canvas还有很多属性和方法来绘图,详细可以看HTML DOM CanvasRenderingContext2D 对象。

【拖动旋转/滚轮缩放】

拖动旋转效果是在容器按下鼠标并拖动的过程中,图像会跟着鼠标转动。
原理是以容器中点为中心,计算按下鼠标位置的弧度R1和拖动到达位置的弧度R2,两者的差就是根据鼠标要旋转的弧度,再加上原来的弧度R0,即R2-R1+R0,就能得到当前要设置的弧度了。
关键的地方就在于如何获取这个弧度,如果要手动计算这个值会很复杂,好在js提供了Math.atan2(y,x)方法,可以返回由 X 轴到 (y,x) 点的弧度,这样直接用坐标就可以得到弧度。
例如中心坐标是(x,y),某一点的坐标是(x1,y1),可以这样得到那个点相对中心坐标的弧度:Math.atan2(y1-y,x1-x)。

首先在鼠标的mousedown中记录容器的中心坐标:

var rect = $$D.clientRect( this._container );
this._mrX = rect.left + this._clientWidth / 2;
this._mrY = rect.top + this._clientHeight / 2;

再根据clientX/clientY当前位置坐标计算弧度:

this._mrRadian = Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._radian;

这里把原来的弧度也顺便计算了。
在拖动的过程中,根据移动坐标获取弧度,并调用rotate来旋转:

this.rotate( Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._mrRadian );

ps:拖动效果请看这里关于拖动的研究。

滚轮缩放效果就是在容器上滚动鼠标会自动实现缩放效果。
这个比较简单,主要是一些兼容问题,相关研究可以参考这里的鼠标滚动缩放。

使用技巧

【模式选择】

模式设置中说明了自定义模式可以用这样的格式:"css3|filter|canvas"。
程序会自动按优先顺序选择支持的模式。
为了尽量保证浏览器支持选择的模式,可以把三个模式都用上。
一般filter是必须的,因为目前ie只支持这个,而css3和canvas可以自行选择。
我在自己的电脑做了效率测试(就是用鼠标狂转图片),看cpu的占用情况:
ff css3 40%
ff canvas 35%
opera css3 30%
opera canvas 35%
chrome css3 25%
chrome canvas 55%
safari css3 20%
safari canvas 55%
看来在ff和opera是canvas好一点,在WebKit就是css3快得多。
但canvas只能画静态图片,对于gif那样的动态图片只能显示一帧,所以还是选css3比较好。

还有css3的变换能用在所有元素中(ie8的滤镜也可以),适用在html的变换,而canvas就更适合做复杂的图形和动画。

【选择图片】

程序实例化之后,还需要调用load方法加载指定的图片。
参数可以是图片的路径,data url(支持的话),ie6还可以用本地路径。
如果是gif图片,就要注意不要用canvas,原因上面也说了,canvas只能显示一帧图片。

使用说明

实例化时,必须有容器对象或id作为参数:

var trans = new ImageTrans( container );

然后调用load方法加载图片:

trans.load(img);

可选参数用来设置系统的默认属性,包括:
属性: 默认值//说明
mode: "css3|filter|canvas",
zoom: .1,//缩放比率
onPreLoad: function(){},//图片加载前执行
onLoad: function(){},//图片加载后执行
onError: function(err){}//出错时执行
其中zoom、onPreLoad、onLoad、onError属性可以在程序初始化后动态设置。

提供以下变换方法:
vertical:垂直翻转
horizontal:水平翻转
rotate: 旋转
left:向左转90度
right:向右转90度
rotatebydegress:根据角度旋转
scale:缩放
zoomin:放大
zoomout:缩小

还提供了以下方法:
load:加载图片;
reset:重置图像为默认状态;
dispose:销毁程序。

加入拖动旋转扩展程序或滚轮缩放扩展程序后,会自动启用,可以自定义mouseRotate或mouseZoom属性为false来取消。

程序源码

var ImageTrans = function(container, options){
this._initialize( container, options );
this._initMode();
if ( this._support ) {
this._initContainer();
this._init();
} else {//模式不支持
this.onError("not support");
}
};
ImageTrans.prototype = {
//初始化程序
_initialize: function(container, options) {
var container = this._container = $$(container);
this._clientWidth = container.clientWidth;//变换区域宽度
this._clientHeight = container.clientHeight;//变换区域高度
this._img = new Image();//图片对象
this._style = {};//备份样式
this._x = this._y = 1;//水平/垂直变换参数
this._radian = 0;//旋转变换参数
this._support = false;//是否支持变换
this._init = this._load = this._show = this._dispose = $$.emptyFunction;
var opt = this._setOptions(options);
this._zoom = opt.zoom;
this.onPreLoad = opt.onPreLoad;
this.onLoad = opt.onLoad;
this.onError = opt.onError;
this._LOAD = $$F.bind( function(){
this.onLoad(); this._load(); this.reset();
this._img.style.visibility = "visible";
}, this );
$$CE.fireEvent( this, "init" );
},
//设置默认属性
_setOptions: function(options) {
this.options = {//默认值
mode: "css3|filter|canvas",
zoom: .1,//缩放比率
onPreLoad: function(){},//图片加载前执行
onLoad: function(){},//图片加载后执行
onError: function(err){}//出错时执行
};
return $$.extend(this.options, options || {});
},
//模式设置
_initMode: function() {
var modes = ImageTrans.modes;
this._support = $$A.some( this.options.mode.toLowerCase().split("|"), function(mode){
mode = modes[ mode ];
if ( mode && mode.support ) {
mode.init && (this._init = mode.init);//初始化执行程序
mode.load && (this._load = mode.load);//加载图片执行程序
mode.show && (this._show = mode.show);//变换显示程序
mode.dispose && (this._dispose = mode.dispose);//销毁程序
//扩展变换方法
$$A.forEach( ImageTrans.transforms, function(transform, name){
this[ name ] = function(){
transform.apply( this, [].slice.call(arguments) );
this._show();
}
}, this );
return true;
}
}, this );
},
//初始化容器对象
_initContainer: function() {
var container = this._container, style = container.style, position = $$D.getStyle( container, "position" );
this._style = { "position": style.position, "overflow": style.overflow };//备份样式
if ( position != "relative" && position != "absolute" ) { style.position = "relative"; }
style.overflow = "hidden";
$$CE.fireEvent( this, "initContainer" );
},
//加载图片
load: function(src) {
if ( this._support ) {
var img = this._img, oThis = this;
img.onload || ( img.onload = this._LOAD );
img.onerror || ( img.onerror = function(){ oThis.onError("err image"); } );
img.style.visibility = "hidden";
this.onPreLoad();
img.src = src;
}
},
//重置
reset: function() {
if ( this._support ) {
this._x = this._y = 1; this._radian = 0;
this._show();
}
},
//销毁程序
dispose: function() {
if ( this._support ) {
this._dispose();
$$CE.fireEvent( this, "dispose" );
$$D.setStyle( this._container, this._style );//恢复样式
this._container = this._img = this._img.onload = this._img.onerror = this._LOAD = null;
}
}
};
//变换模式
ImageTrans.modes = function(){
var css3Transform;//ccs3变换样式
//初始化图片对象函数
function initImg(img, container) {
$$D.setStyle( img, {
position: "absolute",
border: 0, padding: 0, margin: 0, width: "auto", height: "auto",//重置样式
visibility: "hidden"//加载前隐藏
});
container.appendChild( img );
}
//获取变换参数函数
function getMatrix(radian, x, y) {
var Cos = Math.cos(radian), Sin = Math.sin(radian);
return {
M11: Cos * x, M12:-Sin * y,
M21: Sin * x, M22: Cos * y
};
}
return {
css3: {//css3设置
support: function(){
var style = document.createElement("div").style;
return $$A.some(
[ "transform", "MozTransform", "webkitTransform", "OTransform" ],
function(css){ if ( css in style ) {
css3Transform = css; return true;
}});
}(),
init: function() { initImg( this._img, this._container ); },
load: function(){
var img = this._img;
$$D.setStyle( img, {//居中
top: ( this._clientHeight - img.height ) / 2 + "px",
left: ( this._clientWidth - img.width ) / 2 + "px",
visibility: "visible"
});
},
show: function() {
var matrix = getMatrix( this._radian, this._y, this._x );
//设置变形样式
this._img.style[ css3Transform ] = "matrix("
+ matrix.M11 + "," + matrix.M21 + ","
+ matrix.M12 + "," + matrix.M22 + ", 0, 0)";
},
dispose: function(){ this._container.removeChild(this._img); }
},
filter: {//滤镜设置
support: function(){ return "filters" in document.createElement("div"); }(),
init: function() {
initImg( this._img, this._container );
//设置滤镜
this._img.style.filter = "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand')";
},
load: function(){
this._img.onload = null;//防止ie重复加载gif的bug
this._img.style.visibility = "visible";
},
show: function() {
var img = this._img;
//设置滤镜
$$.extend(
img.filters.item("DXImageTransform.Microsoft.Matrix"),
getMatrix( this._radian, this._y, this._x )
);
//保持居中
img.style.top = ( this._clientHeight - img.offsetHeight ) / 2 + "px";
img.style.left = ( this._clientWidth - img.offsetWidth ) / 2 + "px";
},
dispose: function(){ this._container.removeChild(this._img); }
},
canvas: {//canvas设置
support: function(){ return "getContext" in document.createElement('canvas'); }(),
init: function() {
var canvas = this._canvas = document.createElement('canvas'),
context = this._context = canvas.getContext('2d');
//样式设置
$$D.setStyle( canvas, { position: "absolute", left: 0, top: 0 } );
canvas.width = this._clientWidth; canvas.height = this._clientHeight;
this._container.appendChild(canvas);
},
show: function(){
var img = this._img, context = this._context,
clientWidth = this._clientWidth, clientHeight = this._clientHeight;
//canvas变换
context.save();
context.clearRect( 0, 0, clientWidth, clientHeight );//清空内容
context.translate( clientWidth / 2 , clientHeight / 2 );//中心坐标
context.rotate( this._radian );//旋转
context.scale( this._y, this._x );//缩放
context.drawImage( img, -img.width / 2, -img.height / 2 );//居中画图
context.restore();
},
dispose: function(){
this._container.removeChild( this._canvas );
this._canvas = this._context = null;
}
}
};
}();
//变换方法
ImageTrans.transforms = {
//垂直翻转
vertical: function() {
this._radian = Math.PI - this._radian; this._y *= -1;
},
//水平翻转
horizontal: function() {
this._radian = Math.PI - this._radian; this._x *= -1;
},
//根据弧度旋转
rotate: function(radian) { this._radian = radian; },
//向左转90度
left: function() { this._radian -= Math.PI/2; },
//向右转90度
right: function() { this._radian += Math.PI/2; },
//根据角度旋转
rotatebydegress: function(degress) { this._radian = degress * Math.PI/180; },
//缩放
scale: function () {
function getZoom(scale, zoom) {
return scale > 0 && scale >-zoom ? zoom :
scale < 0 && scale < zoom ?-zoom : 0;
}
return function(zoom) { if( zoom ){
var hZoom = getZoom( this._y, zoom ), vZoom = getZoom( this._x, zoom );
if ( hZoom && vZoom ) {
this._y += hZoom; this._x += vZoom;
}
}}
}(),
//放大
zoomin: function() { this.scale( Math.abs(this._zoom) ); },
//缩小
zoomout: function() { this.scale( -Math.abs(this._zoom) ); }
};
拖动旋转扩展
ImageTrans.prototype._initialize = (function(){
var init = ImageTrans.prototype._initialize,
methods = {
"init": function(){
this._mrX = this._mrY = this._mrRadian = 0;
this._mrSTART = $$F.bind( start, this );
this._mrMOVE = $$F.bind( move, this );
this._mrSTOP = $$F.bind( stop, this );
},
"initContainer": function(){
$$E.addEvent( this._container, "mousedown", this._mrSTART );
},
"dispose": function(){
$$E.removeEvent( this._container, "mousedown", this._mrSTART );
this._mrSTOP();
this._mrSTART = this._mrMOVE = this._mrSTOP = null;
}
};
//开始函数
function start(e){
var rect = $$D.clientRect( this._container );
this._mrX = rect.left + this._clientWidth / 2;
this._mrY = rect.top + this._clientHeight / 2;
this._mrRadian = Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._radian;
$$E.addEvent( document, "mousemove", this._mrMOVE );
$$E.addEvent( document, "mouseup", this._mrSTOP );
if ( $$B.ie ) {
var container = this._container;
$$E.addEvent( container, "losecapture", this._mrSTOP );
container.setCapture();
} else {
$$E.addEvent( window, "blur", this._mrSTOP );
e.preventDefault();
}
};
//拖动函数
function move(e){
this.rotate( Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._mrRadian );
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
};
//停止函数
function stop(){
$$E.removeEvent( document, "mousemove", this._mrMOVE );
$$E.removeEvent( document, "mouseup", this._mrSTOP );
if ( $$B.ie ) {
var container = this._container;
$$E.removeEvent( container, "losecapture", this._mrSTOP );
container.releaseCapture();
} else {
$$E.removeEvent( window, "blur", this._mrSTOP );
};
};
return function(){
var options = arguments[1];
if ( !options || options.mouseRotate !== false ) {
//扩展钩子
$$A.forEach( methods, function( method, name ){
$$CE.addEvent( this, name, method );
}, this );
}
init.apply( this, arguments );
}
})();

滚轮缩放扩展

ImageTrans.prototype._initialize = (function(){
var init = ImageTrans.prototype._initialize,
mousewheel = $$B.firefox ? "DOMMouseScroll" : "mousewheel",
methods = {
"init": function(){
this._mzZoom = $$F.bind( zoom, this );
},
"initContainer": function(){
$$E.addEvent( this._container, mousewheel, this._mzZoom );
},
"dispose": function(){
$$E.removeEvent( this._container, mousewheel, this._mzZoom );
this._mzZoom = null;
}
};
//缩放函数
function zoom(e){
this.scale((
e.wheelDelta ? e.wheelDelta / (-120) : (e.detail || 0) / 3
) * Math.abs(this._zoom) );
e.preventDefault();
};
return function(){
var options = arguments[1];
if ( !options || options.mouseZoom !== false ) {
//扩展钩子
$$A.forEach( methods, function( method, name ){
$$CE.addEvent( this, name, method );
}, this );
}
init.apply( this, arguments );
}
})();

完整实例下载


本文转自博客园cloudgamer的博客,原文链接:图片(旋转/缩放/翻转)变换效果(ccs3/滤镜/canvas),如需转载请自行联系原博主。


图片(旋转/缩放/翻转)变换效果(ccs3/滤镜/canvas)相关推荐

  1. iOS transform解决连续多次旋转缩放,实现图片旋转缩放效果

    一.需求 实现imageView的缩放旋转效果,一般有两种方式: 1.底层加scrollview,利用scrollview的属性实现.(推荐这种,这是我比较后发现的,手势做缩放旋转会有点弊端) 2.利 ...

  2. css中图片有缩放和转动效果

    现在html中利用div来包裹住一张图片. <div class="xuanzhuan"><img src="images/top.png" ...

  3. 深度学习数据增强方法,利用仿射变换实现图像进行各种操作如平移、缩放、旋转、翻转

    导读 在深度学习的数据增强中,我们经常需要对图像进行各种增强操作如平移.缩放.旋转.翻转等,这些其实都是图像的仿射变换.通过本篇文章,你能够知道它们的实现原理以及如何应用它们.本文讲述如何通过仿射变换 ...

  4. html网页中怎么让图片旋转90度,css怎么让图片旋转90度

    css让图片旋转90度的方法:利用transform属性来进行图片旋转,如[transform:rotate(90deg)].transform属性用于元素的2D或3D转换,该属性允许我们将元素旋转. ...

  5. css 中图片旋转,倾斜,位移,平滑

    在开发中,我们常常需要对图片有一些绚丽的效果,比如是图片旋转,平移,倾斜等.其实这些在css3中都已经存在,整理下作为demo,以后参考使用,也希望供大家交流学习.如果不足,多多指导. <!DO ...

  6. Java 使图片旋转以及水平翻转垂直翻转(详细且可用)

    最近在做小型游戏,遇到了要翻转图片的苦恼,经过我一下午的研究,终于发现了一种好用的方法. 部分代码来源于别人,我在这个基础上修改了下,变得更好用了,之前的别人Image输入都是BufferedImag ...

  7. php反转图片颜色,PHP 图片处理类(水印、透明度、缩放、相框、锐化、旋转、翻转、剪切、反色)...

    /** * 图片处理函数功能:缩放.剪切.相框.水印.锐化.旋转.翻转.透明度.反色 * 处理并保存历史记录的思路:当有图片有改动时自动生成一张新图片,命名方式可以考虑在原图片的基础上加上步骤,例如: ...

  8. PHP 图片处理类(水印、透明度、缩放、相框、锐化、旋转、翻转、剪切、反色)...

    最新PHP 图片处理类(水印.透明度.缩放.相框.锐化.旋转.翻转.剪切.反色) 以下是三零网为大家整理的最新PHP 图片处理类(水印.透明度.缩放.相框.锐化.旋转.翻转.剪切.反色)的文章,希望大 ...

  9. GD图片处理——缩放、剪切、相框、水印、锐化、旋转、翻转、透明度、反色

    该图片处理函数功能:缩放.剪切.相框.水印.锐化.旋转.翻转.透明度.反色,处理并保存历史记录的思路:当有图片有改动时自动生成一张新图片,命名方式可以考虑在原图片的基础上加上步骤,例如:图片名称+__ ...

最新文章

  1. 学计算机应用英语词汇,计算机应用常用英语词汇 10
  2. java父类调用被子类重写的方法
  3. jack语言编译器的实现过程
  4. ITK:用内核卷积图像
  5. SAP附件UI里选择的文件是如何传到ABAP服务器的
  6. Unicode和Utf-8
  7. 公文写作与计算机应用,德阳市事业单位《计算机应用和公文写作》真题.doc
  8. Uncaught (in promise) Error: Avoided redundant navigation to current location: “/index“. 解决方法
  9. 【新闻发布系统】登录和注销的实现
  10. SQL Server数据库基础知识
  11. word输入带圈字符快捷键(0-20)
  12. App Inventer制作蓝牙通讯软件
  13. 海康萤石云硬盘录像机SDK使用
  14. GIMP:图层蒙版应用小例
  15. 科技云报道:科技巨头们为什么要“跨界造芯”?
  16. SaaSpace:9种最好的免费幻灯片制作工具
  17. 图论初步(存储+最短路)
  18. unity虚拟仿真PC端需要掌握的技术
  19. AI实战: YOLOv4: Optimal Speed and Accuracy of Object Detection
  20. 无法往开启kerberos的zookeeper上注册服务_英雄联盟手游拳头账号有几个区?lol手游韩国账号怎么注册?...

热门文章

  1. ListView和CheckBox的混乱问题
  2. 数据结构与算法——左程云08
  3. 【CSS】内联样式,内部样式表,外部样式表
  4. 大学c语言活动策划,大学校园文化班级趣味运动会活动方案
  5. java中record,Java 中的 record 关键字
  6. 代换密码详解+CTF事例
  7. GridView常见问题
  8. SpringBoot集成knif4j创建在线API文档
  9. python-web开发[10]之初始前端
  10. 安卓一键清理内存_【安卓】手机垃圾清理,拯救内存空间