摘要:很多人都有這樣的疑問,基于實(shí)現(xiàn)的元素怎么和用戶進(jìn)行交互在這里我們用到寫了個(gè)進(jìn)行示例。給設(shè)值,是用一個(gè)名為的函數(shù)來實(shí)現(xiàn)的,實(shí)現(xiàn)代碼如下在檢測(cè)輸入框中值得存在性后,給圖元賦值用到我們的簡(jiǎn)寫為方法。
很多人都有這樣的疑問,基于HTML5 Canvas實(shí)現(xiàn)的元素怎么和用戶進(jìn)行交互?在這里我們用到HT for Web(http://www.hightopo.com/guide...)寫了個(gè)Demo進(jìn)行示例。
場(chǎng)景如下所示,在該場(chǎng)景中雙擊溫度和濕度下的Node,會(huì)生成輸入框供用戶填寫內(nèi)容,這之后,用戶按下“Enter”鍵可以將輸入內(nèi)容傳到Node中,同時(shí)刪除輸入框,地址::http://www.hightopo.com/demo/...
接下來我們探討一下具體實(shí)現(xiàn):
準(zhǔn)備工作如下:
dataModel = new ht.DataModel(); graphView = new ht.graph.GraphView(dataModel); graphView.addToDOM();
1、利用系統(tǒng)中定義好的矢量資源進(jìn)行反序列化來實(shí)現(xiàn)場(chǎng)景圖:
ht.Default.xhrLoad("TemperatureIndex.json", function(text) { var json = ht.Default.parse(text); if(json.title) document.title = json.title; dataModel.deserialize(json); }
2、雙擊事件
本例雙擊會(huì)產(chǎn)生輸入框,在我們的HT中,GraphView默認(rèn)內(nèi)置了一些交互器,以實(shí)現(xiàn)基本的選擇、單雙擊、縮放、平移和編輯等交互的功能,內(nèi)置的交互器有:
內(nèi)置的Interactor在交互過程中會(huì)派發(fā)事件,可通過GraphView#addInteractorListener進(jìn)行監(jiān)聽,簡(jiǎn)寫為mi(詳情可看HT for Web 入門手冊(cè)http://www.hightopo.com/guide...),在這里,我們用內(nèi)置的graphView.addInteractorListener監(jiān)聽雙擊事件:
graphView.addInteractorListener(function(e){ if (e.kind !== "doubleClickData") return; if (currentInput) removeInput(); var data = e.data; if (clickableTags[data.getTag()]){ setTimeout(function(){ createInput("input", data); }, 0); } });
3、創(chuàng)建輸入框
在雙擊事件發(fā)生時(shí),首先需要判斷發(fā)生雙擊事件的元素是不是場(chǎng)景中定義的標(biāo)簽名‘temperature’和‘humidity’的node圖元,我們用clickableTags對(duì)象來保存兩個(gè)node:
var clickableTags = { "temperature": true, "humidity": true }
在雙擊的圖元是‘temperature’或者‘humidity’時(shí),調(diào)用createInput()函數(shù)生成輸入框,createInput()代碼如下:
function createInput(tagName,node){ if (currentInput) { removeInput(graphView, currentInput); return; } else { var element = document.createElement(tagName); graphView.getView().appendChild(element); element.bindingNode = node; ht.Default.setFocus(element); currentInput = element; layout(currentInput);//布局 return currentInput; } }
在createInput()函數(shù)中,用全局變量currentInput保存著當(dāng)前生成的輸入框元素,為保證再次生成輸入框時(shí),調(diào)用removeInput()清除上次生成的輸入框元素,從而不影響性能。
4、布局
生成的輸入框應(yīng)該放在哪兒?這就是layout()函數(shù)中所做的事情。layout()函數(shù)修改生成的輸入框的位置信息,讓其在GraphView拓?fù)鋱D組件上的位置剛好的node圖元的位置相同。
function layout(element){ var rect = element.bindingNode.getRect(); var x = rect.x; var y = rect.y; element.style.position = "absolute"; element.style.width = rect.width + "px"; element.style.height = rect.height + "px"; element.style.top = y + "px"; element.style.left = x + "px"; element.style.background = "#fff"; element.style.color = "#000"; element.style.textAlign = "center"; }
以‘temperature’為例,在點(diǎn)擊標(biāo)簽名為‘temperature’的node圖元時(shí),會(huì)在其上生成一個(gè)輸入框,獲取該node圖元的寬、高、位置信息,并分別賦值給絕對(duì)定位后輸入框的寬、高、位置,這樣即可讓輸入框剛好覆蓋住node圖元。
5、平移和縮放
可能細(xì)心思考的朋友也會(huì)發(fā)現(xiàn),在對(duì)整個(gè)場(chǎng)景圖進(jìn)行平移和縮放時(shí),按照上訴布局方式,輸入框的位置和大小卻沒有跟隨著node圖元的位置進(jìn)行改變,所以我們?cè)诓季謺r(shí)還需要思考到平移、縮放事件。
首先,layout函數(shù)的內(nèi)容中,元素的寬、高、位置信息必須加入平移和縮放產(chǎn)生的結(jié)果,所以,最終layout代碼如下:
function layout(element){ var rect = element.bindingNode.getRect(); var zoom = graphView.getZoom(); var tx = graphView.tx(); var ty = graphView.ty(); rect.x *= zoom; rect.y *= zoom; rect.width *= zoom; rect.height *= zoom; var x = tx + rect.x; var y = ty + rect.y; element.style.position = "absolute"; element.style.width = rect.width + "px"; element.style.height = rect.height + "px"; element.style.top = y + "px"; element.style.left = x + "px"; element.style.background = "#fff"; element.style.color = "#000"; element.style.textAlign = "center"; }
其次,我們需要對(duì)平移和縮放事件添加監(jiān)聽,以便能在該事件發(fā)生時(shí),再次調(diào)用layout()函數(shù)將輸入框的位置進(jìn)行同步,在這里,我們用內(nèi)置的交互器addPropertyChangeListener(簡(jiǎn)寫為mp),監(jiān)聽zoom、translateX、translateY屬性的變化:
var changeProperties = { "zoom": true, "translateX": true, "translateY":true }
graphView.mp(function(e) { if (changeProperties[e.property]) { var elements = document.getElementsByTagName("input"); for (var i = 0; i < elements.length; i++) { layout(elements[i]); } } });
6、更新node
大家在Demo中可以發(fā)現(xiàn),我們按下Enter鍵時(shí),輸入的文字會(huì)同步到node中,其實(shí)這里做了兩件事: 給node設(shè)值后刪除輸入框。
a、給node設(shè)值,是用一個(gè)名為setText()的函數(shù)來實(shí)現(xiàn)的,實(shí)現(xiàn)代碼如下:
function setText(tagName){ var element = document.getElementsByTagName(tagName); if(!element) return; for (var i = 0; i < element.length; i++) { var value = (element[i].value) ? element[i].value : 32 ; element[i].bindingNode.s("text", value); } }
在檢測(cè)輸入框中值得存在性后,給node圖元賦值用到我們HT的setStyle(簡(jiǎn)寫為s)方法。
b、刪除輸入框
function removeInput(){ if(!currentInput) return; graphView.getView().removeChild(currentInput); currentInput = null; }
c、添加Enter的事件監(jiān)聽器
因?yàn)闆]有監(jiān)聽鍵盤的內(nèi)置交互器,所以我們通過graphView.getView().addEventListener直接對(duì)底層的div添加監(jiān)聽。
graphView.getView().addEventListener("keydown", function(event){ if(ht.Default.isEnter(event)){ setText("input"); removeInput(); } else if(ht.Default.isEsc(event)){ removeInput(); } }, false);
最后,再次貼上Demo地址(http://www.hightopo.com/demo/...),希望能夠幫助那些需要在拓?fù)鋱D中加入原生HTML的朋友,也望大家不吝賜教。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/83147.html
摘要:值得一提的是,微信瀏覽器的內(nèi)核,也即是瀏覽器內(nèi)核已經(jīng)內(nèi)置了很多游戲引擎比如白鷺游戲引擎與,供開發(fā)者開發(fā)游戲,所以長時(shí)間來看,微信瀏覽器的畫布性能將會(huì)越來越強(qiáng)大。showImg(https://user-gold-cdn.xitu.io/2019/5/17/16ac3f6acd651e01); 1、什么是流暢的用戶體驗(yàn)? 游戲的開發(fā)界有一個(gè)理論,就是當(dāng)動(dòng)畫或者交互響應(yīng)達(dá)到60FPS(60幀每秒...
摘要:前言前兩天在上尋找靈感的時(shí)候,看到了很多有關(guān)地圖類似的例子,地圖定位等等,但是好像就是沒有地鐵線路圖,就自己花了一些時(shí)間搗鼓出來了這個(gè)交互式地鐵線路圖的,地鐵線路上的點(diǎn)是在網(wǎng)上隨便下載了一個(gè),這篇文章記錄自己的一些收獲畢竟我還是個(gè)菜鳥以及代前言前兩天在 echarts 上尋找靈感的時(shí)候,看到了很多有關(guān)地圖類似的例子,地圖定位等等,但是好像就是沒有地鐵線路圖,就自己花了一些時(shí)間搗鼓出來了這個(gè)交...
閱讀 1839·2021-11-11 16:54
閱讀 2066·2019-08-30 15:56
閱讀 2375·2019-08-30 15:44
閱讀 1304·2019-08-30 15:43
閱讀 1868·2019-08-30 11:07
閱讀 825·2019-08-29 17:11
閱讀 1473·2019-08-29 15:23
閱讀 3014·2019-08-29 13:01