JavaScript与CSS — 元素的位置和各种坐标系

使用位置、尺寸和可见性基本就可以在现代浏览器中模拟绝大多数常见的用户效果了。元素的位置是实现交互效果的基础。在CSS中,元素使用偏移量来定位,它是通过元素到它父元素的左上角的偏移量来计算。CSS的坐标系如下图

css_coordinate.jpg (390×228)

页面上的所有元素都有left(水平位置)和top(垂直位置)的偏移量。为了更好理解这一点,先了解一下CSS的定位方式。基础的HTML代码是:

<html>
<head>
<style>
p {
    border: 3px solid red;
    padding: 10px;
    width: 400px;
    background: #FFF;
}

p.odd {
    /* 定位信息 */
    position: static;
    top: 0px;
    left: 0px;
}
</style>
</head>
<body>
    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam ...</p>
    <p class='odd'>Phasellus dictum dignissim justo. Duis nec risus id nunc ...</p>
    <p>Sed vel leo. Nulla iaculis, tortor non laoreet dictum, turpis diam ...</p>
</body>
</html>

通过对第二个段落的定位,分析一下CSS的定位方式。
□ 静态定位:这是默认方式。它遵循文档的普通流动(flow)。当静态定位中,top和left属性无效。下图的定位代码是 position:static; top:0px; left:0px; 的效果:
cssp1.jpg (435×232)
□ 相对定位:和静态定位类似,同样遵循文档的普通流动。如果设置了top和left属性则会产生相应的偏移。下图的定位代码是:position:relative; top:-50px; left:50px;
cssp2.jpg (486×231)
□ 绝对定位:绝对定位会使元素完全跳出页面布局的普通流动,会相对于它的第一个非静态定位的祖先元素而定位。如果没有这样的祖先元素,则相对于整个文档。下图的定位代码是:position:absolute; top:20px; left:0px;
cssp3.jpg (443×157)
□ 固定定位:固定定位相对于浏览器窗口而定位。设置top和left为0会使它在浏览器的左上角显示,而且不受滚动条的影响。下图的定位代码是:position:fixed; top:20px; right:0px;
cssp4.jpg (645×151)
元素的位置取决于CSS设置,同时又受其它因素的影响。所以单纯的访问CSS属性并不能获取元素的精确位置。为了获取元素相对于页面的位置,有一些CSS属性可以利用,在现代浏览器中都支持以下3个属性:
□ offsetParent : 理论上,这是元素的父元素,元素相对于它定位
□ offsetLeft 和 offfsetTop : 在 offsetParent 环境中的水平和垂直偏移量
为了获取元素相对于页面的精确位置,可以遍历DOM,使用offsetParent属性并累加它们的偏移量来计算元素的位置。下面是连个确定元素相对于整个文档的x和y位置的辅助函数:

// 获取元素的水平位置
function pageX(elem) {
    var p = 0;
    // 累加每一个父元素的偏移量
    while ( elem.offsetParent ) {
        // 增加偏移量
        p += elem.offsetLeft;

        // 遍历下一个父元素
        elem = elem.offsetParent;
    }
    return p;
}

// 获取元素的垂直位置
function pageY(elem) {
    var p = 0;
    // 累加每一个父元素的偏移量
    while ( elem.offsetParent ) {
        // 增加偏移量
        p += elem.offsetTop;

        // 遍历下一个父元素
        elem = elem.offsetParent;
    }
    return p;
}

接下来是获取元素相对于它的父元素的水品和垂直位置。简单地使用 style.left 或 style.top 并不够,因为需要处理的元素可能尚未经过JavaScript或CSS的格式化。要找到元素相对于它的父元素的位置,可以利用offsetParent属性,但该属性并不保证能够反追指定元素的真实父元素,所以还需要使用前面的pageX和pageY函数来计算父元素和子元素之间的差。在下面的函数中,如果是当前元素的父元素,则使用offsetParent;否则继续遍历DOM,使用pageX和pageY函数来确定它的真实位置。

// 获取相对于父元素的水平位置
function parentX(elem) {
    // 如果 offsetParent 是元素的父元素,则返回
    return elem.parentNode == elem.offsetParent ?
        elem.offsetLeft :

        // 否则计算元素和其父元素的水平差值
        pageX( elem ) - pageX( elem.parentNode );
}

// 获取相对于父元素的垂直位置
function parentY(elem) {
    // 如果 offsetParent 是元素的父元素,则返回
    return elem.parentNode == elem.offsetParent ?
        elem.offsetTop :

        // 否则计算元素和其父元素的水平差值
        pageY( elem ) - pageY( elem.parentNode );
}

最后是获取元素相对于它的CSS容器的位置。在CSS定位方式的讨论中我么知道,即使元素包含在另一个元素内,它也可以相对于其他的父元素定位(使用相对和绝对定位)。这种情形可以使用getStyle函数得到CSS偏移的最终值,这等于元素的位置值。

// 左侧位置
function posX(elem) {
    // 获取样式并得到数值
    return parseInt( getStyle( elem, "left" ) );
}

// 顶端位置
function posY(elem) {
    // 获取样式并得到数值
    return parseInt( getStyle( elem, "top" ) );
}

设置位置
调整元素位置的唯一方法就是修改它的CSS属性,仅需要修改left和top属性即可(尽管还有right和bottom属性)。这样就可以设置元素的位置,不管元素的当前位置在哪儿里。

// 设置元素的水平位置
function setX(elem, pos) {
    // 设置CSS的 'left' 属性
    elem.style.left = pos + "px";
}

// 设置元素的垂直位置
function setY(elem, pos) {
    // 设置CSS的 'top' 属性
    elem.style.top = pos + "px";
}

最后,实现一对函数用来增加相对于当前位置的偏移量。利用这个函数可以调整元素的位置向上偏移5像素,从而实现各种动画效果。

// 增加水平偏移量
function addX(elem,pos) {
    setX( posX(elem) + pos );
}

// 增加垂直偏移量
function addY(elem,pos) {
    setY( posY(elem) + pos );

}


===============================================坐标系文一=================================

在JavaScript中有三种不同的坐标系:屏幕坐标,窗口(viewport)坐标和文档(document)坐标。其中要注意的是文档坐标和窗口坐标的关系。窗口坐标的原点是其视口的作上角,由于窗口具有滚动条,文档的坐标原点可能会滚动到窗口以外,这时要注意两者的关系。在代码的书写过程中要注意的是JavaScript的AIP返回的值是基于什么坐标系的。在利用javaScript来操纵css style的时候中的时候absolute的坐标是相对于document坐标系的。
 
以下是一些常见的坐标问题
1.document中elemenet的位置和大小
   每个element都有四个属性:offsetleft,offsetTop,OffsetHeight,offsetWidth,这四个属性分别代表的是element的左上角和高宽。
最初是由IE4引入的,后来也得到了其他浏览器的支持。但是这些属性值相对于该element的offsetParent的坐标.在<html>文件中中<body>的offsetParent为null,因此要得到一个elment的坐标的正确方法是
getElementX(e)
{
 var x=0;
 while(e)
  {
   x+=e.offsetLeft;
   e=e.offsetParent;
  }
 return x;
}
这个方法的返回值是相对于document的坐标的,它不会受到窗口是否滚动的影响。
但是这种方法还有一个小问题,那就是一个element通过设置它的css属性overflow可以拥有自身的滚动条,这时以这种方法得到的只是不正确的。这时正确的方法如下
function getY(element) 
{
// Iterate the offsetParents
// Add up offsetTop values
    var y = 0;
    for(var e = element; e; e = e.offsetParent) 
        y += e.offsetTop;                      

    // Now loop up through the ancestors of the element, looking for
    // any that have scrollTop set. Subtract these scrolling values from
    // the total offset. However, we must be sure to stop the loop before
    // we reach document.body, or we'll take document scrolling into account
    // and end up converting our offset to window coordinates.
    for(e = element.parentNode; e && e != document.body; e = e.parentNode)
     // subtract scrollbar values
  if (e.scrollTop) y -= e.scrollTop; 
    // This is the Y coordinate with document-internal scrolling accounted for.
    return y;
}
2.鼠标事件中的坐标问题
 在DOM2的时间模型中的MouseEvent对象和IE的时间模型中的Event对象都有一对属性clinetX和clientY属性,它们表明的是鼠标事件发生时鼠标在viewport坐标中的位置,他们都没有考虑doucument的滚动。如果要得到docuemnt做坐标系下的位置,则应加上windows.pageOffsetX和windows.pageOffsetY的值.

====================================坐标系文二========================================

Window Geometry 
窗口几何关系 

引用
Screen coordinates describe the position of a browser window on the desktop; they are measured relative to the upper-left corner of the desktop.


Screen坐标系是描述浏览器窗口和桌面之间的几何关系的,其坐标是相对于桌面左上角的。 

引用
Window coordinates describe a position within the web browser's viewport; they are measured relative to the upper-left corner of the viewport.


Window坐标系描述了浏览器页面可视区域的几何关系,其坐标是相对于可视区域的左上角。 

引用
Document coordinates describe a position within an HTML document; they are measured relative to the upper-left corner of the document. When the document is longer or wider than the viewport (as web pages often are), document coordinates and window coordinates are not the same, and you'll need to take the position of the scrollbars into account when converting between these two coordinate systems.


Document坐标系描述了HTML元素与document文档的几何关系,其坐标是相对于document对象的左上角的。 
当document足够长而产生滚动条,document坐标系和window坐标系就会产生差异,两个坐标系之间就要考虑转换的方法。 

引用
For some reason, IE places these window geometry properties on the <body> of the HTML document. And, further confusing matters, IE 6, when displaying a document with a <!DOCTYPE> declaration, places the properties on the document.documentElement element instead of document.body.


IE在默认状态下将这些相关属性放在document.body下,但如果有<!DOCTYPE>声明,那么就会放在document.documentElement下。 
浏览器window对象坐标大小可视区域大小滚动条document对象坐标大小
FFscreenX/YinnerWidth/HeightpageXOffset/YOffsetdocumentElement.scrollLeft/Top
IE with doctypescreenLeft/TopdocumentElement.clientWidthdocumentElement.scrollLeft/Top/HeightdocumentElement.scrollLeft/Top


以下是一个获取几何参数的函数 

Js代码   收藏代码
  1. /** 
  2.  * Geometry.js: portable functions for querying window and document geometry 
  3.  * 
  4.  * This module defines functions for querying window and document geometry. 
  5.  * 
  6.  * getWindowX/Y( ): return the position of the window on the screen 
  7.  * getViewportWidth/Height( ): return the size of the browser viewport area 
  8.  * getDocumentWidth/Height( ): return the size of the document 
  9.  * getHorizontalScroll( ): return the position of the horizontal scrollbar 
  10.  * getVerticalScroll( ): return the position of the vertical scrollbar 
  11.  * 
  12.  * Note that there is no portable way to query the overall size of the 
  13.  * browser window, so there are no getWindowWidth/Height( ) functions. 
  14.  * 
  15.  * IMPORTANT: This module must be included in the <body> of a document 
  16.  *            instead of the <head> of the document. 
  17.  */  
  18. var Geometry = {};  
  19.   
  20. if (window.screenLeft) { // IE and others  
  21.     Geometry.getWindowX = function( ) { return window.screenLeft; };  
  22.     Geometry.getWindowY = function( ) { return window.screenTop; };  
  23. }  
  24. else if (window.screenX) { // Firefox and others  
  25.     Geometry.getWindowX = function( ) { return window.screenX; };  
  26.     Geometry.getWindowY = function( ) { return window.screenY; };  
  27. }  
  28.   
  29. if (window.innerWidth) { // All browsers but IE  
  30.     Geometry.getViewportWidth = function( ) { return window.innerWidth; };  
  31.     Geometry.getViewportHeight = function( ) { return window.innerHeight; };  
  32.     Geometry.getHorizontalScroll = function( ) { return window.pageXOffset; };  
  33.     Geometry.getVerticalScroll = function( ) { return window.pageYOffset; };  
  34. }  
  35. else if (document.documentElement && document.documentElement.clientWidth) {  
  36.     // These functions are for IE 6 when there is a DOCTYPE  
  37.     Geometry.getViewportWidth =  
  38.         function( ) { return document.documentElement.clientWidth; };  
  39.     Geometry.getViewportHeight =  
  40.         function( ) { return document.documentElement.clientHeight; };  
  41.     Geometry.getHorizontalScroll =  
  42.         function( ) { return document.documentElement.scrollLeft; };  
  43.     Geometry.getVerticalScroll =  
  44.         function( ) { return document.documentElement.scrollTop; };  
  45. }  
  46. else if (document.body.clientWidth) {  
  47.     // These are for IE4, IE5, and IE6 without a DOCTYPE  
  48.     Geometry.getViewportWidth =  
  49.         function( ) { return document.body.clientWidth; };  
  50.     Geometry.getViewportHeight =  
  51.         function( ) { return document.body.clientHeight; };  
  52.     Geometry.getHorizontalScroll =  
  53.         function( ) { return document.body.scrollLeft; };  
  54.     Geometry.getVerticalScroll =  
  55.         function( ) { return document.body.scrollTop; };  
  56. }  
  57.   
  58. // These functions return the size of the document. They are not window  
  59. // related, but they are useful to have here anyway.  
  60. if (document.documentElement && document.documentElemnet.scrollWidth) {  
  61.     Geometry.getDocumentWidth =  
  62.         function( ) { return document.documentElement.scrollWidth; };  
  63.     Geometry.getDocumentHeight =  
  64.         function( ) { return document.documentElement.scrollHeight; };  
  65. }  
  66. else if (document.body.scrollWidth) {  
  67.     Geometry.getDocumentWidth =  
  68.         function( ) { return document.body.scrollWidth; };  
  69.     Geometry.getDocumentHeight =  
  70.         function( ) { return document.body.scrollHeight; };  
  71. }  

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个示例代码,它展示了如何使用canvas和动画来展示极坐标转换为直角坐标系中的坐标的过程。 HTML: ``` <canvas id="canvas"></canvas> ``` CSS: ``` canvas { border: 1px solid black; } ``` JavaScript: ``` // 获取canvas元素和上下文 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // 设置canvas的宽度和高度 canvas.width = 500; canvas.height = 500; // 定义极坐标和直角坐标系中的坐标 var polarCoord = {r: 100, theta: 0}; var cartesianCoord = {x: 0, y: 0}; // 定义动画的变量 var animationFrameId; var animationStartTime; var animationDuration = 1000; // 毫秒 // 开始动画 function startAnimation() { animationStartTime = new Date().getTime(); animationFrameId = requestAnimationFrame(updateAnimation); } // 更新动画 function updateAnimation() { // 计算动画的进度 var progress = Math.min(1, (new Date().getTime() - animationStartTime) / animationDuration); // 计算当前的极坐标和直角坐标系中的坐标 polarCoord.theta = Math.PI * 2 * progress; cartesianCoord.x = polarCoord.r * Math.cos(polarCoord.theta); cartesianCoord.y = polarCoord.r * Math.sin(polarCoord.theta); // 清除画布 ctx.clearRect(0, 0, canvas.width, canvas.height); // 绘制极坐标中的点 ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, polarCoord.r, 0, Math.PI * 2); ctx.stroke(); // 绘制直角坐标系中的点 ctx.beginPath(); ctx.arc(canvas.width / 2 + cartesianCoord.x, canvas.height / 2 - cartesianCoord.y, 5, 0, Math.PI * 2); ctx.fill(); // 如果动画未完成,则继续更新动画 if (progress < 1) { animationFrameId = requestAnimationFrame(updateAnimation); } } // 停止动画 function stopAnimation() { cancelAnimationFrame(animationFrameId); } // 注册事件监听器 document.getElementById("startButton").addEventListener("click", startAnimation); document.getElementById("stopButton").addEventListener("click", stopAnimation); ``` 该示例代码使用canvas绘制两个圆,一个表示极坐标中的点,另一个表示直角坐标系中的点。它使用动画来逐步更新极坐标和直角坐标系中的坐标,从而展示极坐标转换为直角坐标系中的坐标的过程。您可以点击“开始”按钮来启动动画,点击“停止”按钮来停止动画。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值