介紹
在web應用的很多場合,需要讓浮動窗口跟隨鼠標而動。比如這兒舉的一個例子:當用戶選中網頁上一段內容時,彈出工具條讓用戶進行標記。可以想象一下,有一個在線看書的應用,支持讀者在閱讀的時候隨時做筆記。當讀者選中一段文字時,彈出一個小工具條,讓用戶保存成筆記標題或筆記內容。在這種場景下,讓小工具條出現在選中文字的旁邊是必要的用戶體驗。在實際應用場合,還必須確保在不同的瀏覽器中、當文字內容有滾動條時,小工具條的位置都不錯。
下面就來看看如何實現這種效果(代碼已經在Firefox 17.0.9,Chrome 30.0.1599.101,IE 10下面測過)。
首先用Dojo widget(Dojo 1.7.3)搭建一個網頁框架。在主模塊中放入文字內容。接下來要做的就是創建一個浮動窗口,讓它在用戶選中一段文字內容的時候出現。
代碼實現
test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@import "../js/dijit/themes/tundra/tundra.css";
@import "../css/main.css";
</style>
</head>
<body class="tundra">
<div data-dojo-type="dijit.layout.BorderContainer"
style="width: 100%; height: 100%; margin: 0px; padding: 0px; ">
<div data-dojo-type="dojox.layout.ContentPane"
data-dojo-props="region:'top'"
style="height:38px;width:100%;background-color: black; color: white;font-family: arial;font-size: 28px;">
在線閱讀器
</div>
<div data-dojo-type="dojox.layout.ContentPane"
data-dojo-props="region:'center', splitter: true"
style="width: 100%; height: 100%; border: none; padding: 0px; background-color: #ffffff;">
<div style="width: 99%; margin: -3px 0px -2px 2px;">
<button id="open_model_btn" data-dojo-type="dijit.form.Button"
class="menu_button" type="button">打開文章</button>
</div>
<div data-dojo-type="dijit.layout.BorderContainer"
data-dojo-props="design:'sidebar', gutters:true, liveSplitters:true"
style="width: 100%; height: 300px;">
<div data-dojo-type="dojox.layout.ContentPane" data-dojo-props="splitter:true,region:'left'"
style="width: 300px;">
<div style="background-color: lightgray;">筆記列表</div>
</div>
<div data-dojo-type="dojox.layout.ContentPane" style="font-size: 16px;"
data-dojo-props="splitter:true,region:'center'">
<div id="resource_text_container">
<div>閱讀 reading</div>
<div>1、從書面材料中獲取信息的過程。書面材料主要是文字,也包括符號、公式、圖表等。首先是把文字符號變成聲音,後達到對書面材料的理解。閱讀是一種主動的過程,是由閱讀者根據不同的目的加以調節控制的。</div>
<div>2、朗讀是一種閱讀方式。朗讀是指出聲誦讀,默讀則指沒有明顯發聲的誦讀。在某些情況下,如詩詞欣賞。朗讀有特殊功用,可高度集中注意力,但就從書面材料中獲取知識而言,默讀更爲重要,理解文字材料主要靠默讀。閱讀時的眼動是一系列的跳動,跳動本身歷時很短,而且不能產生對文字的清晰視覺。對文字的清晰視覺都是在注視時得到的。</div>
<div>3、影響閱讀理解的外部因素包括文字材料和情境的物理特點,如照明條件,文字的字體、型號等;文字材料的易讀度,如字詞的常用程度
,句子的長短與結構的繁簡
,命題密度(即在一定長度的材料中出現的概念數)等;材料的概括與抽象的程度;由外部確定的閱讀目的等等。影響閱讀理解的內部因素主要是閱讀者的知識基礎。此外,閱讀者的注意、記憶和思維也都是重要的內部因素。</div>
<div>閱讀可以分成四種情況。第一種是信息式閱讀法。這類閱讀的目的只是爲了瞭解情況。我們閱讀報紙、廣告、說明書等屬於這種閱讀方法。對於大多數這類資料,讀者應該使用一目十行的速讀法,眼睛象電子掃描一樣地在文字間快速瀏覽,及時捕捉自己所需的內容,捨棄無關的部分。任何人想及時瞭解當前形勢或者研究某一段歷史,速讀法是不可少的,然而,是否需要中斷、精讀或停頓下來稍加思考,視所讀的材料而定。</div>
<div>第二種是文學作品閱讀法。文學作品除了內容之外,還有修辭和韻律上的意義。因此閱讀時應該非常緩慢,自己能聽到其中每一個詞的聲音,嘴脣沒動,是因爲偷懶。例如讀“壓力”這個詞時,喉部肌肉應同時運動。閱讀詩詞更要注意聽到聲音,即使是一行詩中漏掉了一個音節,照樣也能聽得出來。閱讀散文要注意它的韻律,聆聽詞句前後的聲音,還需要從隱喻或詞與詞之間的組合中獲取自己的感知。文學家的作品,唯有充分運用這種接受語言的能力,才能汲取他們的聰明才智、想象能力和寫作技巧。這種依賴耳聽—一通過眼睛接受文字信號,將它們轉譯成聲音,到達喉嚨,然後加以理解的閱讀方法,最終同我們的臆想能力相關。</div>
<div>第三種是經典著作閱讀法,這種方法用來閱讀哲學、經濟、軍事和古典著作。閱讀這些著作要象讀文學作品一樣的慢,但讀者的眼睛經常離開書本,對書中的一字一句都細加思索,捕捉作者的真正的用意。從而理解其中的深奧的哲理。值得注意的是,如果用經典著作閱讀法閱讀文學作品,往往容易忽略文學作品的特色,以
使讀者自己鑽進所謂文學觀念史的牛角尖中去。</div>
<div>第四種閱讀方法是麻醉性的閱讀法。這種閱讀只是爲了消遣。如同服用麻醉品那樣使讀者忘卻了自己的存在,飄飄然於無限的幻想之中。這類讀者一般對自己的經歷和感受不感興趣,把自己完全置身於書本之外。如果使用麻醉性的閱讀方法閱讀名著,讀者只能得到一些已經添加了自己的幻想的膚淺的情節,使不朽的名著下降到鴛鴦蝴蝶派作家的庸俗作品的水平。如果漫不經心地閱讀《安娜•卡列尼娜》,猶如讀一本拙劣的三角戀愛小說。麻醉性的閱讀在將進入成年的時候達到頂峯。年輕人的麻醉閱讀是造成大量的文學作品質量低劣的原因。</div>
</div>
<div id="resource_text_floating_pane"
style="border: 1px solid #BBBBBB;position: absolute;width: 85px;z-index: 10;display:none;">
<div data-dojo-type="dijit.Toolbar" style="padding: 3px 0 0 3px;">
<div id="add_paragraph" data-dojo-type="dijit.form.Button" data-dojo-props="showLabel:true">
段落
</div>
<div id="add_content" data-dojo-type="dijit.form.Button" data-dojo-props="showLabel:true">
內容
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
dojoConfig = {
isDebug : false,
parseOnLoad : true,
async : true
};
</script>
<script type="text/javascript" src="../js/dojo/dojo.js"></script>
<script>
require([ "dojo/parser", "dijit/form/Button", "dijit/Toolbar",
"dijit/layout/BorderContainer", "dojox/layout/ContentPane"]);
</script>
<script>
require(
[ "dojo/ready",
"dijit/registry",
"dojo/dom",
"dojo/on"
],
function(ready, registry, dom, on) {
ready(function() {
var resource_text_container = dom.byId("resource_text_container");
on(resource_text_container, "mouseup", function(e){
//拿到鼠標位置
var selection = document.getSelection();
var start = selection.anchorOffset;
var end = selection.focusOffset;
var fp = dom.byId("resource_text_floating_pane");
if(start-end != 0){
//根據鼠標位置,計算浮動窗口的位置
if(dojo.isChrome != undefined){//Chrome
var cx = e.layerX;
var cy = resource_text_container.parentElement.scrollTop + e.layerY;
}else if(dojo.isIE != undefined){//IE
var cx = e.layerX - resource_text_container.parentElement.offsetLeft;
var cy = resource_text_container.parentElement.scrollTop + e.layerY;
}else {//Firefox
var cx = e.layerX;
var cy = e.layerY;
}
fp.style.left = (cx + 0) + "px";
fp.style.top = (cy + 0) + "px";
fp.style.display = "block";
}else{
fp.style.display = "none";
}
});
on(registry.byId("add_paragraph"), "click", function(e){
alert("新建段落");
});
on(registry.byId("add_content"), "click", function(e){
alert("新建內容");
});
});
});
</script>
</body>
</html>
總結
在確定浮動窗口位置時,我們主要使用了鼠標事件的layerX和layerY屬性。關於Event對象與定位相關的屬性,和瀏覽器的版本密切相關。想支持其他版本的,可以參考這篇文章。