各位高手帮忙解释一下下面代码的意思,来者有分

lai3345678 2012-08-19 09:51:37
希望各位高手指点一下小弟,把下面js的代码作一下注释,越详细越好(希望重点说明一下实现左右切换区域内的页面的代码是哪段以及代码的意思)

下面代码实现的是在一个区域内鼠标移动到该区域左右移动可以切换页面,就像ipad移动切换页面一样,下面两张图片是实现的效果图,但我不明白js的代码意思,希望高手指点一下,希望重点说明一下实现左右切换区域内的页面的代码是哪段以及代码的意思。




index.html源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>iOS Home Screen with CoffeeScript | Tutorialzine Demo</title>

<!-- Our CSS stylesheet file -->
<link rel="stylesheet" href="assets/css/styles.css" />

<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>

<body>


<section id="homeScreen">
<div id="mask" >
<div id="allScreens"></div>
</div>

<ul id="indicators"></ul>

<div id="dock"></div>
</section>

<footer>
<h2><i>Tutorial:</i> Creating an iOS-like Home Screen with CoffeeScript</h2>
<a class="tzine" href="http://tutorialzine.com/2011/10/ios-homescreen-coffeescript/">Head on to <i>Tutorial<b>zine</b></i> to download this example</a>
</footer>

<!-- JavaScript includes -->
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script src="assets/js/touchable.js"></script>
<script src="assets/js/coffee-script.js"></script>


<script type="text/coffeescript">

# The Icon class.

class Icon

# The constructor. The -> arrow signifies
# a function definition.

constructor: (@id, @title, @url) ->
# @ is synonymous for "this". The id and title parameters
# of the construtor are automatically added as this.id and this.title

# @markup holds the HTML of the icon. It is
# transformed to this.markup behind the scenes.


@markup = "<a class='icon' style='background-image:url(assets/img/icons/#{@id}.png)' title='#{@title}' href='#{@url}'></a>"


# The DockIcon class inherits from Icon

class DockIcon extends Icon
constructor: (id, title, url)->

# This calls the constructor if Icon

super(id, title, url)

# Changing the class name of the generated HTML
@markup = @markup.replace("class='icon'","class='dockicon'")


# The Screen Class

class Screen

# Function arguments can have default parameters
constructor: (icons = [])->
@icons = icons

attachIcons: (icons = [])->
Array.prototype.push.apply(@icons, icons)

generate: ->
markup = []

# Looping through the @icons array
markup.push(icon.markup) for icon in @icons

# The last line of every function is implicitly returned
"<div class='screen'>#{markup.join('')}</div>"


class Stage

# The width of our "device" screen. This is
# basically the width of the #mask div. 最要的宽度是mask层的宽度

screenWidth: 550

constructor: (icons)->

@currentScreen = 0
@screens = []

# Calculating the number of screens 计算屏幕图标的数量
# necessary to display all the icons 必须显示所有的图标

num = Math.ceil(icons.length / 15)
i = 0

while num--
# we pass a slice of the icons array
s = new Screen(icons[i...i+15])

# adding the screen to the local screens array
@screens.push(s)

i+=15

# This method populates the passed element with HTML
addScreensTo: (element)->

@element = $(element)
@element.width(@screens.length*@screenWidth)

for screen in @screens
@element.append(screen.generate())

addIndicatorsTo: (elem)->

# This method creates the small
# circular indicatiors

@ul = $(elem)

for screen in @screens
@ul.append('<li>')

@ul.find('li:first').addClass('active');

goTo: (screenNum)->

# This method animates the allScreen div in
# order to expose the needed screen in #mask

if @element.is(':animated')
return false

# if this is the first or last screen,
# run the end of scroll animation

if @currentScreen == screenNum

# Parallel assignment:
[from, to] = ['+=15','-=15']

if @currentScreen != 0
[from, to] = [to, from]

@element.animate( { marginLeft : from }, 150 )
.animate( { marginLeft : to }, 150 )
else
# If everything is ok, animate the transition between the screens.

# The fat arrow => preserves the context of "this"

@element.animate( { marginLeft:-screenNum*@screenWidth }, => @currentScreen = screenNum )
@ul.find('li').removeClass('active').eq(screenNum).addClass('active');

next: ->
toShow = @currentScreen+1

# If there is no next screen, show
# the current one

if toShow == @screens.length
toShow = @screens.length - 1

@goTo(toShow)

previous: ->
toShow = @currentScreen-1

# If there is no previous screen,
# show the current one

if toShow == -1
toShow = 0

@goTo(toShow)

# This is equivalent to $('document').ready(function(){}):

$ ->

allIcons = [
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.163.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
new Icon('Photos', 'Photo Gallery','http://www.qq.com'), new Icon('Maps', 'Google Maps','http://www.qq.com')
new Icon('Chuzzle', 'Chuzzle', 'http://www.qq.com'), new Icon('Safari', 'Safari' ,'http://www.qq.com')
]

dockIcons = [
new DockIcon('Camera', 'Camera' ,'http://www.qq.com')
new DockIcon('iPod', 'iPod' ,'http://www.qq.com')
new DockIcon('Calculator', 'Calculator' ,'http://www.qq.com')
new DockIcon('Camera', 'Camera' ,'http://www.qq.com')
new DockIcon('iPod', 'iPod' ,'http://www.qq.com')
]

allScreens = $('#allScreens')

# Using the Touchable plugin to listen for
# touch based events:

allScreens.Touchable();


# Creating a new stage object
stage = new Stage(allIcons)

stage.addScreensTo(allScreens)
stage.addIndicatorsTo('#indicators')

# Listening for the touchablemove event.
# Notice the callback function

allScreens.bind 'touchablemove', (e,touch)->
stage.next() if touch.currentDelta.x < -5
stage.previous() if touch.currentDelta.x > 5


# Adding the dock icons:

dock = $('#dock')

for icon in dockIcons
dock.append(icon.markup)


</script>

</body>
</html>

...全文
284 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
lai3345678 2012-08-20
  • 打赏
  • 举报
回复
如果不明白我说什么,需要测试的麻烦留一下邮箱我把代码发过去
zxc122333 2012-08-20
  • 打赏
  • 举报
回复
coffeeScript对缩进敏感,楼主的代码我没办法测试。。。楼主可以先把里面的coffeeScript翻译成js代码再读的,网上有在线翻译
泡泡鱼_ 2012-08-20
  • 打赏
  • 举报
回复
动画执行主要是:animate
参数:marginleft,参考点是其父级容器,值为:当前第几屏*当前屏的宽度。这个值为正数时,则从左向右划动,值为负数时,则从右向左划动;

例如:
<div id="container">
<div id="item"></div>
</div>
想像一下,container中包含屏幕列表item[如果不绑定效果,则item原效果应该是N个屏幕一直X轴平铺过去的]
假如有2个屏,每个屏宽500px,那么针对allScreens而言,第1屏的left值为0,第二屏的left值即为500px
那向要实现滚动到下一个屏的思路就是将其left值-500px,
则第1屏的left值实际变为:-500px,第2屏的left值变更为:0px了。
这个时候你就看不到第1屏,只能看到第2屏了。
如果从item来操作方法就是$('#item).animate({left:-=500px},1000)
想实现滚动至上一个屏的方法就应该是:$('#item).animate({left:+=500px},1000)

你如果知道“焦点图”的实现方法,你就应该大致的原理了。
lai3345678 2012-08-19
  • 打赏
  • 举报
回复




touchable.js源码:
/*
* jQuery Touchable
*
* Simplified BSD License (@see License)
* @author Gregor Schwab
* @copyright (c) 2010 Gregor Schwab
* Usage Command Line: $(elem).Touchable() (@see Readme.md)
* @version 0.0.5
* @requires jQuery
*/


(function($) {

$.fn.Touchable = function(conf) {
return this.each(function() {
var t= $(this).data['Touchable']=new Touchable(this, conf);
return t;
});
}
$.fn.newHover = function(fn1, fn2, disableHover) {
return this.each(function() {
$(this).bind('newHoverIn', fn1).bind('newHoverOut', fn2);
});
}
$.fn.newHover2 = function(fn1, fn2) {
return this.each(function() {
$(this).bind('newHoverIn2', fn1).bind('newHoverOut2', fn2);
});
}

$.Touchable=Touchable;

/**
* @constructor
*/

function Touchable(elem, conf)
{

this.logging=false; //set to false to disabele logging gets overwritten by conf see below
var log=function(a){if(self.logging && (typeof console !== 'undefined')){
console.log(Array.prototype.slice.call(arguments));}
}; //private logging function

this.elem=elem;
this.$elem=$(elem);
this.is_doubleTap=false;
this.is_currentlyTouching=false;
this.isOneFingerGesture = false;

this.startTouch={x:0,y:0};
this.currentTouch={x:0,y:0};
this.previousTouch={x:0,y:0};
this.currentDelta={x:0,y:0};//measured from previous move event
this.currentStartDelta={x:0,y:0}; //measured from start 测量开始
this.currentPosition={x:0,y:0};
this.doubleTapTimer=null, this.longTapTimer=null;

var self=this;

if (typeof conf!=='undefined'){
if(typeof conf.logging!=='undefined'){this.logging=conf.logging;}
}
//make IE happy
var addEventListener=elem.addEventListener||elem.attachEvent
var removeEventListener = elem.removeEventListener||elem.detachEvent
//add touchstart eventlistener
addEventListener.call(elem, 'touchstart', function(){self.$elem.trigger('touchstart')}, true);
addEventListener.call(elem, 'touchend', function(){self.$elem.trigger('touchend')}, false);
addEventListener.call(elem, 'touchmove', function(){self.$elem.trigger('touchmove')}, false);

addEventListener.call(elem, 'touchstart', touchstart, false);
this.$elem.mousedown(touchstart);

function touchstart (e) {
if(typeof e.touches!== "undefined")
{
log('Touchable Touchstart touches length ' + e.touches.length);
//only handle 1 or 2 touches
if (e.touches.length !== 1 && e.touches.length !== 2) {
return false;
}
if (self.isCurrentlyTouching) {
return false;
}


self.isCurrentlyTouching = true;
if (e.touches.length == 1) { //1 finger
self.isOneFingerGesture = true;
//init pos
self.startTouch.x = self.previousTouch.x = e.touches[0].clientX;
self.startTouch.y = self.previousTouch.y = e.touches[0].clientY;
} else if (e.touches.length == 2) { //two fingers
self.isOneFingerGesture = false;
if (e.touches[0].clientY > e.touches[1].clientY) {//0 is lower
self.startTouch.x = self.previousTouch.x = e.touches[0].clientX;
self.startTouch.y = self.previousTouch.y = e.touches[0].clientY;
} else {
self.startTouch.x = self.previousTouch.x = self.touches[1].clientX;
self.startTouch.y = self.previousTouch.y = self.touches[1].clientY;
}
}

addEventListener.call(document, 'touchmove', touchmove, false);
addEventListener.call(document, 'touchend', touchend, false);
}else{
log('Touchable Touchstart touches length ' + e.pageX + ' ' + e.pageY);
self.startTouch.x = self.previousTouch.x = e.pageX;
self.startTouch.y = self.previousTouch.y = e.pageY;
$(document).mousemove(touchmove);
$(document).mouseup(touchend);
}
//don't shallow links, but all the rest
self.target=e.target;//some browser loose the info here
self.currentTarget=e.currentTarget;//some browser loose the info here so save it for later
var x=self.startTouch.x; var y=self.startTouch.y;
self.hitTarget = ( document.elementFromPoint ) ? (document.elementFromPoint(x, y)):'';
//if (self.hitTarget && !(self.hitTarget instanceof HTMLAnchorElement) &&!(e.currentTarget instanceof HTMLAnchorElement))
e.preventDefault()


//setup double tapping
if (!self.inDoubleTap) {
self.inDoubleTap = true;
//setup a timer
self.doubleTapTimer = setTimeout(function() {
self.inDoubleTap = false;
}, 500);
} else {//we are double tapping
// call function to run if double-tap
log('Touchable doubleTap');
self.$elem.trigger('doubleTap', self); //trigger a doubleTap
//reset doubleTap state
clearTimeout(self.doubleTapTimer);
self.inDoubleTap = false;
}
//setup long tapping and long mousedown
//setup a timer
self.longTapTimer = setTimeout(function() {
log('Touchable longTap'/*, self.hitTarget, self.target, self.currentTarget, self.elem*/);
$(self.elem).trigger('longTap', self); //trigger a longTap
}, 1000);

log('Touchable Tap');
$(self.elem).trigger('tap', self); //trigger a tap
$(self.elem).trigger('touchablestart', self); //trigger a tap


}


//called on iPad/iPhone when touches started and the finger is moved
function touchmove(e) {

if (typeof e.touches !== 'undefined'){
log('Touchable Touchsmove touches length ' + e.touches.length);
if (e.touches.length !== 1 && e.touches.length !== 2) //use touches to track all fingers on the screen currently (also the ones not in the pane) if there are more than 2 its a gesture
return false;

//1 finger
if (e.touches.length == 1 || self.isOneFingerGesture) {//we ignore the second finger if we are already in movement
self.currentTouch.x = e.touches[0].clientX;
self.currentTouch.y = e.touches[0].clientY;
//2 finger
} else if (self.touches.length == 2 && !self.isOneFingerGesture) {//two fingers move , take the upper finger as reference
if (e.touches[0].clientY > e.touches[1].clientY) {//0 is lower
self.currentTouch.x = e.touches[0].clientX;
self.currentTouch.y = e.touches[0].clientY;
} else {
self.currentTouch.x = e.touches[1].clientX;
self.currentTouch.y = e.touches[1].clientY;
}
}
}else{
self.currentTouch.x = e.pageX;
self.currentTouch.y = e.pageY;
}
//if we are moving stop any css animations currently running
$(self.elem).removeClass('webkitAnimate');
//e.preventDefault();

self.currentDelta.x = (self.currentTouch.x - self.previousTouch.x);///s.currentScale;
self.currentDelta.y = (self.currentTouch.y - self.previousTouch.y);///s.currentScale;
self.currentStartDelta.x = (self.currentTouch.x - self.startTouch.x);///s.currentScale;
self.currentStartDelta.y = (self.currentTouch.y - self.startTouch.y);///s.currentScale;
//just for the records (accumulation)
self.currentPosition.x = self.currentPosition.x + self.currentDelta.x;
self.currentPosition.y = self.currentPosition.y + self.currentDelta.y;
//reset the start position for the next delta
self.previousTouch.x = self.currentTouch.x;
self.previousTouch.y = self.currentTouch.y;
log('Touchable Touchablemove self e.target' + e.target + 'e.currentTarget '+ e.currentTarget +' x:'+ self.currentStartDelta.x);
//Target handling
self.target=e.target;//some browser loose the info here
self.currentTarget=e.currentTarget;//some browser loose the info here so save it for later
var x=self.currentTouch.x; var y=self.currentTouch.y;
self.hitTarget = ( document.elementFromPoint ) ? (document.elementFromPoint(x, y)):'';
$(self.elem).trigger('touchablemove', self);

//clear the long tap timer on mousemove
if (self.longTapTimer) clearTimeout(self.longTapTimer);
}
function touchend(e) {
if (typeof e.touches !== 'undefined'){
if (e.targetTouches.length > 0)
return false;
removeEventListener.call(self.elem, 'touchmove', touchmove, false);
removeEventListener.call(self.elem, 'touchend', touchend, false);
}else{
$(document).unbind('mousemove',touchmove);
$(document).unbind('mouseup',touchend);
}

//e.preventDefault();
self.isCurrentlyTouching = false;
//clear the long tap timer on mouseup
if (self.longTapTimer) clearTimeout(self.longTapTimer);
log('Touchable Touchend self ' + self.currentStartDelta.x);
$(self.elem).trigger('touchableend', self);
log('Touchable: touchableend');
$(self.hitTarget).trigger('click', self);//trigger a click on the hittarget cause on iPad/Mobile Safari preventdefault seems to shallow click events
log('Touchable: Hittarget click');

}
}
})(jQuery);//end closure


87,910

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧