上回講到將人民日報的首版圖片顯示出來,本次將實現點擊新聞對應區域,閱讀該新聞html
熱區就是在網頁上進行了連接的一個區域算法
在人民日報電子版的版面圖片上,點擊想要看的新聞,右側就會出現該新聞的詳細報道,咱們點擊的地方就是「熱區」,在網頁中可經過<map></map>
標籤實現此項功能,可是小程序中未提供相似功能的組件,要腫麼辦?小程序
俗話說:只要思想不滑坡,辦法總比困難多this
雖然沒有相似組件,但是咱們只要知道區域的範圍就好啦,點擊版面圖片的某塊區域時,判斷觸點是否在該區域內就好了。那麼如何判斷?url
如上所述,版面圖片的熱區信息包含在map標籤內,正則匹配走起~
修改paper.js的onLoad方法爲:code
onLoad: function (options) { var self = this; //獲取系統寬高,並計算寬高比 .......... wx.request({ url: url, success: function (res) { var html = res.data; //正則式-匹配版面圖片 var pagePicImgReg = /<img[^>]+src=(.*)\s+border=0\s+usemap=#pagepicmap[^>]*>/i; //正則式-匹配熱區信息 var pagePicMapReg = /<map[^>]+name=pagepicmap[^>]*>.*<\/map>/i; //版面圖片匹配結果 var pagePicImgMatch = html.match(pagePicImgReg); //熱區信息匹配結果 var pagePicMapMatch = html.match(pagePicMapReg); //中間變量,存放map標籤內容 var mapHtml = ""; //中間變量,存放img的src內容 var imgSrc = ""; pagePicMapMatch && (mapHtml = pagePicMapMatch[0]); pagePicImgMatch && (imgSrc = pagePicImgMatch[1].replace('../../..', imgUrl)); //正則式-匹配map標籤裏area信息,coords是區域定點信息,href是該區域所連接到的文章 var areaReg = /<area\s+coords="(.*?)"[^>]+href="(.*?)"[^>]*>/ig; var area; //存放該版面圖片的area內容 var areaArray = [] while ((area = areaReg.exec(mapHtml)) != null) { areaArray.push({ "coords": area[1].split(",").map(self.computeCoords), "href": area[2] });//href爲當前版面每條文章的連接 } //console.log("areaArray ", areaArray); self.setData({ paperInfo: [{ "imgSrc": imgSrc, "areaArray": areaArray}] }); } }) },
paper.js添加computeCoords方法: 因爲響應的coords座標信息對應的版面圖片默認爲400*571px的,因此不一樣設備的coords要做等比例縮放xml
//計算適合該設備的coords大小 computeCoords: function (coord, index) { var self = this; var tmpCoord = parseInt(coord); if (index % 2 == 1) {//表明x座標 tmpCoord = Math.ceil(tmpCoord * (400 / self.data.windowWidth)); } if (index % 2 == 0) {//表明y座標 tmpCoord = Math.ceil(tmpCoord * (571 / self.data.windowHeight)); } return tmpCoord; },
知道了版面圖片的熱區狀況,如何判斷用戶點擊的是哪篇文章呢?
ray-crossing算法
1.簡單來講,該算法能夠判斷一點是否在給定的某個不規則封閉區域內。(幸運的是版面圖片上畫的熱區是簡單的封閉圖形,且大可能是矩形)
該算法的大體思路是:過被判斷的點(觸點)做一條向右的射線,若射線與區域的邊的交點爲奇數,則認爲該點在此區域內,若爲偶數,則未在該區域內
對於邊界點(區域頂點和邊上的點),對於本應用來講,用戶點到邊界的機率很小,是能夠忽略的
2.實現:在paper.js中添加如下方法htm
//point爲用戶觸點的座標,coords爲某個熱區頂點狀況 pointInRegin: function (point, coords) { //coords中每兩個是一對座標 var count = 0;//統計目標點向右畫射線與多邊形相交次數 var x = point[0];//用戶觸點x位置 var y = point[1];//用戶觸點y位置 var i = 0, j = 0;//j表明i的下一個座標點 //coords中肯定一條直線的兩點的座標 var xi = 0; var yi = 0; var xj = 0; var yj = 0; for (i = 0, j = coords.length - 2; i < coords.length - 1; j = i, i = +2) { xi = coords[i]; yi = coords[i + 1]; xj = coords[j]; yj = coords[j + 1]; if (yi == yj) { continue; }//若是兩點水平,則跳過 if (y < Math.min(yi, yj)||y > Math.max(yi, yj)) { continue; }//若是觸點低於該線段或高於該線段,則跳過 if (x >= Math.max(xi, xj)) { continue; }//若是觸點在該線段的右邊,則跳過 //該觸點與coords所肯定的區域有交叉,求該交叉點的x座標的值 var intersection_x = (xj - xi) * (y - yi) / (yj - yi) + xi; if (x < intersection_x) { count++; }//若是交叉點在觸點的右邊,相交次數加1 } if (count % 2 == 0) { return false; }//在多邊形外面或邊上 if (count % 2 == 1) { return true; }//在多邊形裏面 },
paper.js添加肯定觸點點擊的新聞連接方法:事件
/** * 肯定觸點的文章 * 返回文章的href * pagenum表明版面號(從1開始編號) */ getArticleHref: function (fingerx, fingery, pagenum) { var self = this; var currentPageAreas = self.data.paperInfo[pagenum - 1].areaArray; var aresLength = currentPageAreas.length; var i; var points = []; for (i = 0; i < aresLength; i++) { points = currentPageAreas[i].coords; if (self.pointInRegin([fingerx, fingery], points)) { console.log("找到href",currentPageAreas[i].href); return currentPageAreas[i].href; }else{console.log("未在當前coords內");} } }, /** * 點擊跳轉到相關文章 *記得在paper.wxml文件的img組件上綁定toArticle事件 */ toArticle: function (e) { var self = this; var fingerx = e.detail.x;//x,y表明距離其父文檔左上角的距離 var fingery = e.detail.y; //獲取觸點所在的文章href,目前只有初版因此pagenum爲1 var href = self.getArticleHref(fingerx, fingery, pagenum); if (href) { console.log("獲取的文章連接爲 ",href); }else{ console.log("未找到文章連接"); } },
按照上篇文章的方法,編譯運行程序,點擊版面圖片上的任意一條新聞,查看控制檯是否輸出該文章的href圖片