*purpleendurer修正了原文中的一些錯誤 你可以通過IE為你的HTML元素添加行為,建立面向對象的頁面設計方法。Phillip Perkins建立了一個<DIV>對象,當用戶拖動它時,它會在限定的<DIV>內繼續定向運行。 Macromedia Flash可以使開發者免受網絡瀏覽器與互操作解決方案的限制。但是,局限于Flash讓你無法體驗到網絡瀏覽器的許多特色。 例如,你可以通過IE為HTML元素添加行為,建立對象面向的頁面設計方法。在這個例子中,我會建立了一個<DIV>對象,當用戶拖動它時,它會在限定的<DIV>內繼續定向運行。 為HTML添加行為的能力是設計的一個關鍵部分。在IE中,這通過相關的樣式來實現。添加行為的樣式特性即“behavior”。你可以通過嵌套的<STYLE>標簽來添加行為,就像這樣: <style>DIV.object { behavior: url(Behavior.htc);} 從這段腳本中,你可以發現一個行為會提及到一個HTC(HTML組件)文件。既然我們具有對象化這些HTML元素的基礎,我們就能建立控制它們的行為腳本。 表A中包含了為我們的嵌套<DIV>對象建立行為的所有代碼。在這一個組件內就有許多的代碼。 表 A --文件component.htc的內容 <public:component lightweight="true"> <public:attach event="onmousedown" onevent="element_onmousedown()"/> <public:attach event="onmousemove" onevent="element_onmousemove()"/> <public:attach event="onmouseup" onevent="element_onmouseup()"/> <public:attach event="onmouseout" onevent="element_onmouseup()"/> <public:attach event="onselectstart" onevent="element_onselectstart()"/> <public:attach event="ondragstart" onevent="element_ondragstart()"/> <public:attach event="onload" for="window" onevent="Init()"/> <public:method name="moveMe"/> <public:property name="clickPoint" get="get_clickPoint" put="put_clickPoint"/> <public:property name="interval" get="get_interval" put="put_interval"/> <script language="JScript"> function Init() } function element_onmousedown() } function element_onmouseup() if (spd > 1) spd = 1; function element_onmousemove() function element_ondragstart() function get_clickPoint() function put_clickPoint(o) function get_interval() function put_interval(n) if (newY <= m_bounds[BOUNDS.top]) element.style.left = newX + "px"; </public:component> 如果你注意到了腳本的頂部,在那里有一個特殊的標簽告訴瀏覽器該用何種樣式呈現特性和包含組件的方法,以及將這一組件添加到哪些事件中。這些事件都是標準的HTML事件。 當組件(在裝載事件中)初始化時,它獲得一個uniqueID,將其包含的母體記錄在一個數字變量中,并為進程計算設定缺省值。當你逐句通過這一對象的目標處理器時,你會看到每當用戶點擊對象時--- element_onmousedown()---一些變量進行了初始化。下一步,用戶應該將對象拖動到另一個位置。 當用戶在屏幕上拖動對象時― element_onmousemove() ―對象的位置發生改變,以與鼠標的運動相匹配。然后,用戶應該釋放鼠標按鈕,讓對象自行移動。 當用戶釋放鼠標按鈕― element_onmouseup() ―或是鼠標脫離了對象區域― element_onmouseout() ―時,釋放點即被記錄下來,并對用戶點擊對象到釋放對象的時間進行計算,對象則獲得永恒運動。通過計算得出點擊起始點與釋放終止點的斜度,這個斜度成為對象新的移動路徑。通過對象移動的距離與拖動時間可計算出用戶拖動對象的速度。這個速度再又用來建立對象的移動方式。最終,速度的倒數被用來建立對象位置更新的時間間隔。 在間隔中斷事件― moveMe() ―中,對象的上升(rise)與運動(run)將方向斜度轉換成計算的運動路徑。將較大的方向改變與較小的方向改變區分開來,我們就可以做到這點。結果是,其中一個方向改變總是1,而另一個則小于1。在每次中斷中,兩個方向改變中較大的一個由一個向量單元增加,可能是-2或是2個像素。另一個則增加較小方向改變的兩倍(即,如果上升為2而運動為1的話,那么上升將增加1 *向量而運動每次增加.5 * 2單元)。如果較小的改變增量超過向量單元(-2或2)的話, 如果對象的新位置位于限定元素之外,向量則發生改變以與之相匹配。這種方法將對象“反彈”到限定元素之外。 表B是含有這些組件的HTML頁面。 表 B --demo.htm的內容 <html> <head> <style> } DIV.object } <script language="JavaScript"> function Point(pX, pY) function CSlope(P1, P2) function _slopeAdd(P1) CSlope.prototype.add = _slopeAdd; function CGeometry() {} function _slope(P1, P2) CGeometry.prototype.slope = _slope; function startMove(obj, t) </head> <body style="font-family: Verdana; font-size: 24pt;"> <center> HTML頁面不過是包含<DIV>及作為組件元素的嵌套<DIV>。在JavaScript內,有一些支持對象與功能來幫助進行組件計算。值得注意的是,有一個對象棧― objStack ―變量,在間隔中斷過程中,可以用來幫助管理對組件moveMe()方法的調用。 拷貝這些代碼并將它粘貼到你自己的文件中。記得把你的HTC文件命名為component.htc,特別用于行為樣式特性。在IE 5.0或更高版本中運行這個例子,看著你的對象充滿活力。
var m_bStarted = false;
var m_bMoving = false;
var m_clickPoint = null;
var m_tStart = 0;
var m_tEnd = 0;
var m_ptStart = null;
var m_Slope = null;
var m_interval = 0;
var m_isMoving = false;
var m_trash = 0;
var m_dX = 0;
var m_dY = 0;
var m_vectX = 0;
var m_vectY = 0;
var m_pNode = null;
var m_bounds = [];
var BOUNDS = {"left":0,"top":1,"right":2,"bottom":3};
var m_dimensions = [];
var DIMS = {"width":0,"height":1};
{
element.id = element.document.uniqueId;
var m_pNode = element.parentNode;
m_bounds = [
0,
0,
parseInt(m_pNode.currentStyle.width),
parseInt(m_pNode.currentStyle.height)
];
m_dimensions = [
Node parseInt(element.offsetWidth),
parseInt(element.offsetHeight)
];
{
m_bStarted = true;
m_tStart = new Date();
clearInterval(m_interval);
m_Slope = null;
m_ptStart = null;
m_trash = 0;
m_dX = 0;
m_dY = 0;
m_vectX = 0;
m_vectY = 0;
m_clickPoint = new Point(event.x, event.y);
m_ptStart = new Point(part(element.currentStyle.left), parseInt(element.currentStyle.top));
{
if (!m_bMoving) return;
m_bMoving = false;
m_bStarted = false;
m_tEnd = new Date();
var t = m_tEnd.valueOf() - m_tStart.valueOf();
var lPoint = new Point(event.x, event.y);
m_Slope = Geometry.slope(m_clickPoint, lPoint);
var ptEnd = m_Slope.add(m_ptStart);
element.style.left = ptEnd.posX + "px";
element.style.top = ptEnd.posY + "px";
var spd = 0;
if (m_Slope.deltaX != 0 && m_Slope.deltaY != 0)
{
spd = Math.sqrt(Math.pow(m_Slope.deltaX, 2) + Math.pow(m_Slope.deltaY,2))/t;
}
else
{
spd = (m_Slope.deltaX + m_Slope.deltaY)/t;
}
m_dX = m_Slope.deltaX;
m_dY = m_Slope.deltaY;
if (m_dX != 0) m_vectX = (m_dX > 0) ? 2 : -2;
if (m_dY != 0) m_vectY = (m_dY > 0) ? 2 : -2;
startMove(element, parseInt(1/spd));
}
{
m_bMoving = m_bStarted;
if (!m_bMoving) return;
var lPoint = new Point(event.x, event.y);
var lSlope = Geometry.slope(m_clickPoint, lPoint);
var ptEnd = lSlope.add(m_ptStart);
element.style.left = ptEnd.posX + "px";
element.style.top = ptEnd.posY + "px";
}
function element_onselectstart()
{
event.returnValue = false;
return false;
}
{
event.returnValue = false;
return false;
}
{
return m_clickPoint;
}
{
if (typeof(o) == "object" && o.constructor == "Point")
{
m_clickPoint = o;
}
else
{
alert("Expected Point.");
}
}
{
return m_interval;
}
{
m_interval = n;
}
function moveMe()
{
if (m_isMoving) return;
setTimeout("m_isMoving = true;", 1);
var newX = parseInt(element.currentStyle.left);
var newY = parseInt(element.currentStyle.top);
var dXabs = Math.abs(m_dX);
var dYabs = Math.abs(m_dY);
if (dXabs > dYabs)
{
//divide both by deltaX
//each call move X by 1 and Y by Y/X
//if iteration > 1, then move Y by 1
//and add remainder back on Y
newX += m_vectX;
var l_step = (m_dY/m_dX) * 2;
m_trash = m_trash + l_step;
if (m_trash > 2 || m_trash < -2)
{
newY += m_vectY;
m_trash -= m_vectX;
}
}
else
{
//vice-versa
newY += m_vectY;
var l_step = (m_dX/m_dY) * 2;
m_trash = m_trash + l_step;
if (m_trash > 2 || m_trash < -2)
{
newX += m_vectX;
m_trash -= m_vectX;
}
}
if (newX <= m_bounds[BOUNDS.left])
{
newX = m_bounds[BOUNDS.left] + 1;
m_vectX *= -1;
}
else if ((newX + m_dimensions[DIMS.width]) >= m_bounds[BOUNDS.right])
{
newX = m_bounds[BOUNDS.right] - m_dimensions[DIMS.width] - 1;
m_vectX *= -1;
}
{
newY = m_bounds[BOUNDS.top] + 1;
m_vectY *= -1;
}
else if ((newY + m_dimensions[DIMS.height]) >= m_bounds[BOUNDS.bottom])
{
newY = m_bounds[BOUNDS.bottom] - m_dimensions[DIMS.height] - 1;
m_vectY *= -1;
}
element.style.top = newY + "px";
setTimeout("m_isMoving = false;", 1);
}
</script>
DIV.bounds
{
width: 800px;
height: 600px;
border: 1px red solid;
overflow: hidden;
{
position:absolute;
left: 0px;
top: 0px;
border: 0px blue solid;
behavior: url(component.htc);
cursor: hand;
</style>
{
this.posX = pX;
this.posY = pY;
}
{
this.deltaY = P2.posY - P1.posY;
this.deltaX = P2.posX - P1.posX;
this.m = (P2.posY - P1.posY)/(P2.posX - P1.posX);
}
{
var lPoint = new Point((P1.posX + this.deltaX), (P1.posY + this.deltaY));
return lPoint;
}
{
var lSlope = new CSlope(P1, P2);
return lSlope;
}
var Geometry = new CGeometry();
var objStack = [];
{
var id = objStack.push(obj);
objStack[id-1].interval = setInterval("objStack[" + (id - 1) + "].moveMe()", t);
}
</script>
<div class="bounds" id="divBounds" name="divBounds" onselectstart="window.event.returnValue = false;">
<div class="object">dog</div>
</div>
</center>
</body>
</html>