为你的DHTML添活力

dhtml

*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">
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};

function Init()
{
    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)
                ];

}

function element_onmousedown()
{
    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));

}

function element_onmouseup()
{
    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;
    }

    if (spd > 1) spd = 1;
    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));
}

function element_onmousemove()
{
    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;
}

function element_ondragstart()
{
    event.returnValue = false;
    return false;
}

function get_clickPoint()
{
    return m_clickPoint;
}

function put_clickPoint(o)
{
    if (typeof(o) == "object" && o.constructor == "Point")
    {
        m_clickPoint = o;
    }
    else
    {
        alert("Expected Point.");
    }
}

function get_interval()
{
    return m_interval;
}

function put_interval(n)
{
    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;
    }

    if (newY <= m_bounds[BOUNDS.top])
    {
        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.left = newX + "px";
    element.style.top = newY + "px";
    setTimeout("m_isMoving = false;", 1);
}
</script>

</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.bounds
{
    width: 800px;
    height: 600px;
    border: 1px red solid;
    overflow: hidden;

}

DIV.object
{
    position:absolute;
    left: 0px;
    top: 0px;
    border: 0px blue solid;
    behavior: url(component.htc);
    cursor: hand;

}
</style>

<script language="JavaScript">

function Point(pX, pY)
{
    this.posX = pX;
    this.posY = pY;
}

function CSlope(P1, P2)
{
    this.deltaY = P2.posY - P1.posY;
    this.deltaX = P2.posX - P1.posX;
    this.m = (P2.posY - P1.posY)/(P2.posX - P1.posX);
}

function _slopeAdd(P1)
{
    var lPoint = new Point((P1.posX + this.deltaX), (P1.posY + this.deltaY));
    return lPoint;
}

CSlope.prototype.add = _slopeAdd;

function CGeometry() {}

function _slope(P1, P2)
{
    var lSlope = new CSlope(P1, P2);
    return lSlope;
}

CGeometry.prototype.slope = _slope;
var Geometry = new CGeometry();
var objStack = [];

function startMove(obj, t)
{
    var id = objStack.push(obj);
    objStack[id-1].interval = setInterval("objStack[" + (id - 1) + "].moveMe()", t);
}
</script>

</head>

<body style="font-family: Verdana; font-size: 24pt;">

<center>
<div class="bounds" id="divBounds" name="divBounds" onselectstart="window.event.returnValue = false;">
<div class="object">dog</div>
</div>
</center>
</body>
</html>



HTML页面不过是包含<DIV>及作为组件元素的嵌套<DIV>。在JavaScript内,有一些支持对象与功能来帮助进行组件计算。值得注意的是,有一个对象栈— objStack —变量,在间隔中断过程中,可以用来帮助管理对组件moveMe()方法的调用。

拷贝这些代码并将它粘贴到你自己的文件中。记得把你的HTC文件命名为component.htc,特别用于行为样式特性。在IE 5.0或更高版本中运行这个例子,看着你的对象充满活力。

时间: 2024-12-24 02:37:47

为你的DHTML添活力的相关文章

旅游分享成时尚 为地方社区添活力

中介交易 SEO诊断 淘宝客 云主机 技术大厅 又至岁末年初时,这是一个节日和假期集中的日子,圣诞节,元旦,春节,情人节,不管是中国的传统节日,还是西方节日,在这个寒冷冬日里,节日气氛都给增添了许多温暖.同时,节假日的增多也让新旧年更替的时节成了各种休闲活动集中的时段.尤其带火了旅游市场,各种探亲游.休假游的增多,让辛苦繁忙一年的人们得到了放松,同时,分享旅游也成为了一种时尚. 有关旅游的奇闻趣事.出行线路.游览攻略.地方美食等话题在这个旅游旺季里成为人们茶余饭后闲谈的主要内容.而人们也不再仅仅

使用6款卓尔不群的Linux操作系统为你的上网本添活力

基于Linux的操作系统的优点是它们可以根据不同的需求定制.因此,在这里我们将为您呈现6款专为上网本设计不同于其它而又有趣的顶尖发行版. 评定一款上网本的OS是否良好,主要取决于它能否"物尽其用".当在闲置模式下,内存使用应该降到最小限度,你需要一个很好的导航系统来避免屏幕的错乱. 对于一名 Linux 爱好者来说,拥有一款对本本优化过的操作系统,同时还是基于开源技术,这该有多好啊. AntiX - 利用了 iceWM 窗口管理器,能帮助维持初始内存的低占用.虽然它并不像 Ubuntu

“互联网+”为经济发展添活力

互联网具有打破信息不对称.降低交易成本.促进专业化分工和提升劳动生产率的特点,为经济转型升级提供了重要机遇.随着我国"互联网+"行动计划的大力推进,必将为社会经济发展带来巨大机遇.   经济发展"风口" "互联网+"受到追捧,是因为它已成为发展的重要"风口"."站在风口上,猪都能飞起来"."互联网+"正在给各行各业带来新的发展机会,零售.制造.教育.物流.医疗.交通--几乎所有行业都可能

如何促进身体机能代谢,填充活力

"你看起来健康吗?"在养生健康越来越被重视的今天,如何促进身体机能代谢,填充活力,成为日常生活中最热门的话题.而服用螺旋藻.西洋参等保健方式大都已是"昨日黄花",以服用奇魅植物酵素(酶)为代表的"补酶"养生方式正悄然走进了现代人的生活.事实上,植物酵素(酶)养生的流行,跟现代人对健康的焦虑有很大的关系.随着年纪增大,以及受饮食过量.偏食等不良生活习惯的影响,许多人都出现了身体机能减退.免疫力降低.消化不良.肠胃不适.体力不济等健康问题,而这与身体

“智慧的电力”战略及解决方案首次在国内发布

近日,IBM在针对国内电力行业发展的深刻洞察过后,首次提出并详细介绍了"智慧的电力"战略,并提出了一系列解决智能电网建设和新能源接入的具体方案.这是IBM公司在国内首次发布"智慧的电力"战略以及系列解决方案."智慧的电力"是IBM"智慧的城市"战略的一个重要组成部分,不仅能够为城市的发展提供强大的动力,更为人们创造美好的生活贡献出力量,这次方案这与2010年上海世博会的主题"城市,让生活更美好"十分契合.

数据“情结”左右A股

撰文申银万国证券研究所王晓亮 不知是偶然还是必然,每当一个月上中旬交替时,市场总归充满犹豫和浮躁情绪,特别是最近,多空在2600点关口展开了拉锯战.周一长阴拉下"狼来了"呼声不绝,周二周三多头却又举重若轻,蓝筹与题材股一起 发力,将指数创出了9个月来的新高.正当人们认为行情可能步入一边倒时,数据不利引发隔夜美股暴跌,亚太市场一片风声鹤唳,全球经济复苏的期盼降温,连累了A股低开走低,2600点整数关前又陷"泥潭". 为何会有如此反复,其实归根结底,"数据情结

财政部专家:水电不会成为明年水利建设重点

2011年的水利建设任务将以水库建设.城乡用水为重点,水电领域不会成为明年水利建设的重点 [财经网专稿] 记者 鲍喆 12月30日,财政部科学研究所副所长王朝才在接受记者电话采访时表示,2011年的水利建设任务将以水库建设.城乡用水为重点,水电领域不会成为明年水利建设的重点. 他表示,2011年水利建设将采用渐次铺开的方式,以水库建设.病库防治以及城乡用水作为明年在水利方面财政支持的核心内容,如果有条件的话,水利可能也会有一定的扶持.但是在现在的紧迫程度来看,水利并不会成为明年水利工作的重点.

中国兵装十年亮剑

--中国兵器装备集团十周年发展纪实 雷 明 易黎明 潘 超 十年,在历史长河中,不过短短的一瞬,但并不妨碍中国兵器装备集团公司发生沧桑巨变,创造人间奇迹. 十年前,它濒临破产,是国防科技工业技术力量最弱.产业基础最薄.亏损最为严重的企业集团. 十年后,它成长壮大为国防科技工业市场化程度最高.发展速度最快.民品规模最大.军民结合最好.最具活力的军工集团,其工业销售收入.民品销售收入.人均销售收入.人均利税均居国防科技工业第一位. 2008年与1999年相比,兵装集团主营业务收入由214亿元增长到1

西南地区首家跨境母婴特卖网站跨境优品火爆上线

摘要: 近日,记者了解到,西南地区首家跨境母婴特卖网站跨境优品火爆上线,为西南地区母婴市场再添活力,正式开启西南地区育婴接轨国际的征程之路. 跨境优品是一家主营全球精选母婴 近日,记者了解到,西南地区首家跨境母婴特卖网站--跨境优品火爆上线,为西南地区母婴市场再添活力,正式开启西南地区育婴接轨国际的征程之路. 跨境优品是一家主营全球精选母婴用品的综合性购物网站,作为重庆市政府试点的跨境电商试点单位,其依托重庆西永保税港区现有仓储物流资源和保税政策,提供包含通关.仓储.分拣.包装等在内的全产业链服