【CSON原创】CSS的障眼法:利用border实现图片的翻转

功能说明:

利用css的border实现图片的翻转效果,支持从上到下、从下到上,从左到右,从右到左四种翻转。

兼容IE 7 8 9 10 firefox chrome

效果预览:


 
 
 
 

 

实现原理:

  之所以说这是CSS的障眼法,是因为这种效果并不是使用CSS原生的属性进行实现的,并不仅仅是使用一张图片,然后通过特定属性使其翻转,因为我们知道CSS并不提供另图片翻转的接口。要实现这种效果,我们需要的是通过图片和外层div的border的配合,使图片看起来翻转了一定角度。

  细心的读者可能会发现,我在选择图片的时候,已经有所讲究,看看上面这幅图片,它具有两个特点

  1.完全对称。

  2.图形周围的空白(黑色部分)较多。

  如果不是满足上述两个特点的图片,翻转效果看起来也会没那么好,要知道原因,首先就要清楚这种翻转效果的实现原理了。

 

  以从右到左的翻转为例,使图片翻转的实现步骤

  1.首先添加一张你需要实现翻转效果的图片,图片绝对定位。

  2.然后我们需要的是一个div,div高度和图片高度相等。该div除了右边框外,其他边框为和背景色一样且borderWidth为0,右边框则为透明且borderWidth和图片宽相等,定位与图片一致,zIndex比图片大。经过这两步后,我们就可以把一个透明正方形(实质上为div的右边框)覆盖在图片上面

  3.之后我们需要的就是使右边框和图片的尺寸和大小动态改变,实现翻转效果。我们开始同时逐渐减少右边框和图片的宽度,并且同时逐渐增大上下边框的宽度和图片的高度,并且调整图片和div的定位,使它们始终保持在原位置,就可以实现图片的翻转效果。简单地说,实现视觉上翻转效果的实际上是div的右边框,但是我们通过把右边框设置为透明从而露出下面的图片,看上去就是图片在翻转。


  之所以我之前说的选择的图片最好要有上面那两个特点:完全对称和四周空白较多。那是因为如果图片不对称,那么图片翻转过去之后,图片的显示就会不合理(没有达到镜像的显示效果,显示位置不对),但是,我也在程序里提供了onHalfLoop和onFullLoop两个回调函数的接口,分别是翻转90度和180度后触发的回调函数。大家完全可以使用ps把一张图片左右(或上下)翻转,然后在onHalfLoop里把图片路径设置为该翻转后图片的路径,在onFullLoop里把路径还原,这样就可以完全克服需要使用完全对称图片这个障碍,使不对称的图片也可以实现翻转。

  至于另一个特点:使用四周空白较多的图片。使用这种图片的好处是消除翻转的时候处在图片边缘的图纹被隐藏所带来的视觉破绽,具体这里说不清楚,不过大家找一张图片四周也有较多图纹的图片试试就清楚了。

 

最后给出所有代码吧,结合代码应该就可以更清楚地了解其中的原理:

  

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<style type="text/css" rel="stylesheet">
#container
{width:600px; height:500px; background:white; position:relative;}
.borderWrap
{position:absolute; border-style:solid; border-color:white; border-width:0 0 0 0; z-index:10; height:100px; width:0;}
.turnImg
{position:absolute;z-index:1; width:150px; height:100px;}

#borderWrapper1
{ left:100px; top:100px;}
#borderWrapper2
{ left:300px; top:100px;}
#borderWrapper4
{ left:100px; top:300px;}
#borderWrapper3
{ left:300px; top:300px;}

#turnImg1
{left:100px; top:100px;}
#turnImg2
{left:300px; top:100px;}
#turnImg3
{left:100px; top:300px;}
#turnImg4
{left:300px; top:300px;}
</style>
</head>

<body>

<div id="container">
<div id="borderWrapper1" class="borderWrap"></div>
<img id="turnImg1" class="turnImg" src="https://i-blog.csdnimg.cn/blog_migrate/0c2bfd3dda00ca971cf300e92cc46368.png" />
<div id="borderWrapper2" class="borderWrap"></div>
<img id="turnImg2" class="turnImg" src="https://i-blog.csdnimg.cn/blog_migrate/0c2bfd3dda00ca971cf300e92cc46368.png" />

<div id="borderWrapper3" class="borderWrap"></div>
<img id="turnImg3" class="turnImg" src="https://i-blog.csdnimg.cn/blog_migrate/0c2bfd3dda00ca971cf300e92cc46368.png" />

<div id="borderWrapper4" class="borderWrap"></div>
<img id="turnImg4" class="turnImg" src="https://i-blog.csdnimg.cn/blog_migrate/0c2bfd3dda00ca971cf300e92cc46368.png" />

</div>


</body>
<script>
var overturnImg=(function(){

var _overturnImg=function(imgId,wrapperId,options){
this.init(imgId,wrapperId,options);

}
_overturnImg.prototype
=(function(){

var dirObj={//方向对应的扩大border
'RTL':{preHalf:'right',afterHalf:'left'},
'LTR':{preHalf:'left',afterHalf:'right'},
'TTB':{preHalf:'top',afterHalf:'bottom'},
'BTT':{preHalf:'bottom',afterHalf:'top'}
}



var $=function(id){return document.getElementById(id);};
var emptyFunction=function(){};


var changeTurningStyle=function(self){

var timeId;
var speed=self.speed;
var img=self.img;
var borderWrapper=self.borderWrapper;
var bwWidth,imgWidth,bwHeight,imgHeight,bwTop,imgTop,bwLeft,imgLeft,bwOther2Width;
var dir=self.direction;
var preHalf=true;
var enhanceBorder='border-'+dirObj[dir]['preHalf']+'-';//根据旋转方向映射出需要被扩大的border
bwWidth=imgWidth=img.clientWidth;
bwHeight
=imgHeight=img.clientHeight;
bwOther2Width
=0;
bwTop
=imgTop=img.offsetTop;
bwLeft
=imgLeft=img.offsetLeft;

return function(){

var reduceBorder;
if(dir=='RTL'||dir=='LTR'){

if(preHalf){

bwOther2Width
+=speed;
bwWidth
-=speed*2;
bwLeft
+=speed;
bwTop
-=speed;

if(bwWidth<=0){
preHalf
=false;
self.onHalfLoop(self);
enhanceBorder
='border-'+dirObj[dir]['afterHalf']+'-';//根据旋转方向映射出需要被扩大的border
}

}
else{

bwOther2Width
-=speed;
bwWidth
+=speed*2;
bwLeft
-=speed;
bwTop
+=speed;

if(bwWidth>=imgWidth){
preHalf
=true;
enhanceBorder
='border-'+dirObj[dir]['preHalf']+'-';//根据旋转方向映射出需要被扩大的border
self.onFullLoop(self);
}
}

borderWrapper.style.cssText
=enhanceBorder+'width:'+bwWidth+'px;'
+enhanceBorder+'color:transparent;'
+'width:0;'
+'border-top-width:'+bwOther2Width+'px;'
+'border-bottom-width:'+bwOther2Width+'px;'
+'top:'+bwTop+'px;'
+'left:'+bwLeft+'px;';

img.style.cssText
='height:'+(bwOther2Width*2+bwHeight)+'px;'
+'width:'+Math.max(0,bwWidth)+'px;'
+'top:'+bwTop+'px;'
+'left:'+bwLeft+'px;';


}
else if(dir=='TTB'||'BTT'){
if(preHalf){

bwOther2Width
+=speed;
bwHeight
-=speed*2;
bwLeft
-=speed;
bwTop
+=speed;

if(bwHeight<=0){
preHalf
=false;
enhanceBorder
='border-'+dirObj[dir]['afterHalf']+'-';//根据旋转方向映射出需要被扩大的border
self.onHalfLoop(self);
}

}
else{

bwOther2Width
-=speed;
bwHeight
+=speed*2;
bwLeft
+=speed;
bwTop
-=speed;

if(bwHeight>=imgHeight){
preHalf
=true;
enhanceBorder
='border-'+dirObj[dir]['preHalf']+'-';//根据旋转方向映射出需要被扩大的border
self.onFullLoop(self);
}
}

borderWrapper.style.cssText
=enhanceBorder+'width:'+bwHeight+'px;'
+enhanceBorder+'color:transparent;'
+'height:0;'
+'width:'+bwWidth+'px;'
+'border-left-width:'+bwOther2Width+'px;'
+'border-right-width:'+bwOther2Width+'px;'
+'top:'+bwTop+'px;'
+'left:'+bwLeft+'px;';
img.style.cssText
='width:'+(bwOther2Width*2+bwWidth)+'px;'
+'height:'+Math.max(0,bwHeight)+'px;'
+'top:'+bwTop+'px;'
+'left:'+bwLeft+'px;'



}
timeId
=window.setTimeout(arguments.callee,20);

}


}

return{
/* 初始化 */
init:
function(imgId,wrapperId,options){
var strArr=[];
var ags=arguments||[];
var ag;
for(var i=0,len=ags.length;i<len;i++){ //参数修复
ag=arguments[i];
(
typeof ag=='string')?strArr.push(ag):options=ag;
}
imgId
=ags[0];
wrapperId
=ags[1];

options
=options||{};

this.img=$(imgId||'turnImg');//获取要翻转的图片元素
this.borderWrapper=$(wrapperId||'borderWrapper');//获取制造翻转的div元素
this.speed=options.speed||2;
this.direction=options.direction||'RTL';
this.onHalfLoop=options.onHalfLoop||emptyFunction;
this.onFullLoop=options.onFullLoop||emptyFunction;


},
run:
function(){
changeTurningStyle(
this)();
}

};
})();

return _overturnImg;

})();
var b=new overturnImg('turnImg1','borderWrapper1');
b.run();
var b2=new overturnImg('turnImg2','borderWrapper2',{direction:'TTB'});
b2.run();
var b3=new overturnImg('turnImg3','borderWrapper3',{direction:'BTT'});
b3.run();
var b4=new overturnImg('turnImg4','borderWrapper4',{direction:'LTR'});
b4.run();

</script>

 

  可以看看最后的调用方法:

var b=new overturnImg('turnImg1','borderWrapper1');
b.run();
var b2=new overturnImg('turnImg2','borderWrapper2',{direction:'TTB'});
b2.run();
var b3=new overturnImg('turnImg3','borderWrapper3',{direction:'BTT'});
b3.run();
var b4=new overturnImg('turnImg4','borderWrapper4',{direction:'LTR'});
b4.run();


  我们想要使图片向不同的方向翻转,需要的就是在direction中传入不同的数值:RTL(右向左翻转)、LTR(左向右翻转)、BTT(下向上翻转)、TTB(上向下翻转)。

 

  欢迎转载,请标明出处:http://www.cnblogs.com/Cson/archive/2012/02/01/2335087.html

 

  

转载于:https://www.cnblogs.com/Cson/archive/2012/02/01/2335087.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: protobuf是一种语言无关的数据序列化格式,可以将结构化数据以二进制形式进行存储、传输和解析。相比其他序列化格式(如JSON和XML),protobuf具有更高的效率和更小的存储空间,特别适用于性能要求较高的场景。 CSON是一种基于文本的数据交换格式,它的语法和JSON类似,但更加简洁易读。CSON可以直接嵌入到许多编程语言中,而无需额外的解析器或库。相比JSON,CSON有更好的人机可读性,可以更快地编写和解析。在一些开发工具中,如Atom编辑器,CSON被广泛用于配置文件。 当我们使用protobuf和CSON时,两者的作用是不同的。protobuf主要用于高效的数据存储和传输,主要用于网络通信和持久化存储。它定义了用于描述结构化数据的消息格式,并生成相应的编解码代码。protobuf允许我们使用预定义的消息结构定义数据模型,并将其序列化为二进制数据进行传输或存储。在接收端,我们可以将二进制数据反序列化为原始的消息结构,以进行后续处理。 CSON则更适用于配置文件和简单数据的存储和交换。与JSON相比,CSON的语法更简洁易读,可以更方便地进行人工编辑和修改。在开发过程中,我们可以使用CSON格式的配置文件来定义应用程序的设置和参数,以及其他需要在运行时进行调整的数据。CSON可以与各种编程语言一起使用,通过相应的解析库来读取和写入CSON数据。 综上所述,protobuf和CSON都是用于数据交换和存储的格式,但其使用场景和特点有所不同。protobuf适合高效的网络通信和持久化存储,而CSON则适用于配置文件和简单数据的存储和交换。 ### 回答2: protobuf cson 是 Google 开发的一种数据序列化格式,可以用于不同编程语言之间的数据交换。cson 是 CSN(CoffeeScript Object Notation)的缩写,它是一种类似于 JSON 的数据格式,但具有更简洁和易读的语法。 protobuf cson 结合了 Protocol Buffers(一种用于结构化数据的语言无关、平台无关、可扩展的序列化格式)和 cson 的优势,既可以确定数据结构,又可以通过人类可读的方式来表示数据。相比于 JSON,protobuf cson 使用更少的字符来表示相同的数据结构,因此也更加紧凑和高效。 使用 protobuf cson,开发者可以根据预先定义好的消息结构来序列化和反序列化数据。通过定义消息类型和字段,我们可以精确控制所要传输的数据结构,在不同语言中实现数据的互相转换。同时,protobuf cson 还支持扩展和向后兼容性,可以轻松地向已有的消息类型添加新的字段。 protobuf cson 在分布式系统、微服务架构以及网络通信中广泛应用。它的高效和灵活性使得数据的传输和解析更加方便和高效。此外,由于具备易读的特性,一些配置文件和参数文件也可以使用 protobuf cson 进行存储和传输。 总而言之,protobuf cson 是一种强大的数据序列化格式,它兼具 Protocol Buffers 和 cson 的优势。通过结构化和紧凑的表示,protobuf cson 提供了高效的数据传输和解析方式,广泛应用于不同领域和语言环境中。 ### 回答3: protobuf是一种数据序列化格式,用于将结构化数据转化为可传输和存储的二进制格式。而CSON则是一种用于存储和表示数据的文本格式,类似于JSON,但更接近于CoffeeScript语法。 protobuf和CSON在功能和用途上有一些差异。protobuf适合用于高效地序列化和反序列化数据,并且可以在多种编程语言之间进行数据交换。它使用二进制格式,因此在数据传输和存储方面更高效,尤其是对于大量数据和复杂结构的数据。protobuf还提供了强大的扩展和版本控制机制,使得在不同版本之间进行数据兼容性处理更加方便。 CSON则更加适用于人类可读和可编辑的数据表示。它使用文本格式并支持类似于CoffeeScript的语法,因此更加容易阅读和理解。与JSON相比,CSON提供了一些额外的功能,比如支持注释和多行字符串。但是,CSON相对于protobuf而言在性能上差一些,因为它需要将文本转换为内部数据结构,并且在解析和生成过程中需要进行额外的处理。 总的来说,如果需要高效的数据传输和存储,或者需要跨多种编程语言进行数据交换,protobuf是更好的选择。而如果需要人类可读和可编辑的数据表示,或者对数据格式有更高的灵活性要求,使用CSON可能更合适。但是,具体使用哪种格式还是要根据具体的应用场景和需求来决定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值