Quantcast
Viewing all articles
Browse latest Browse all 2480

為網頁加入多點觸控功能(IE10版)

之前曾以iPad為對象寫過為網頁加入多點觸控功能範例,如今支援觸控的Windows 8筆電在手,不改寫成IE10版怎能止癢?

經過簡單研究,大致整理IE10與Safari/Chrome觸控事件差異如下:

  1. 事件名稱不同,IE使用的不是touchstart、touchmove、touchend等名稱,而是MSPointerDown, MSPointerMove, MSPointerUp, MSPointerOver, MSPointerOut, MSPointerHover... 等。另外,還有高階的手勢事件: MSGestureTap, MSGestureHold, MSGestureStart, MSGestureChange, MSGestureEnd, MSInertiaStart,讓開發者不用自己費心追蹤各指座標變化,就能判定使用者正在縮放、旋轉動作,真是佛心來著,將來肯定要抽空玩一下才不會暴殄天物。
  2. MSPointerDown等事件概念與touchstart也有所差異。在touchstart中會得到touches陣列,包含多個觸控點的資料;MSPointerDown則是個每個觸控點活動都會觸發一次。
  3. 滑鼠也會觸發MSPointer*事件! 如只想對觸控產生反應,可用if (e.pointerType == e.MSPOINTER_TYPE_TOUCH)過濾。
  4. 因為事件觸發基礎不同,原先在touchmove中可以透過changedTouches取得移動中的觸控點,使用IE10則要自行比對座標值該點是否在移動。
  5. 要攔截觸控事件的元素需加上CSS設定: -ms-touch-action: none; 防止跟IE10預設的縮放、移動瀏覽等觸控操作打架。
  6. 檢查navigator.msMaxTouchPoints屬性存在與否可偵測IE是否支援觸控,由navigator.msMaxTouchPoints亦可得到裝置所支援的觸控點數。

把握以上重點,經過簡單修改,支援IE10的多點觸控展示網頁就完成囉~ 線上展示

<!DOCTYPEhtml>
 
<html>
<head>
<title>Mutli-Touch Test</title>
<scriptsrc="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.4.js"
type="text/javascript"></script>
<meta name="viewport"
     content="width=device-width, initial-scale=1.0, user-scalable=no">
<style>
        html,body {
/* 停用預設的縮放、移動瀏覽(Panning)等觸控功能, 由自訂程式接管 */
            -ms-touch-action: none;
        }
</style>
<script>
//http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx
        $.extend($.support, { ieTouch: "msMaxTouchPoints"in window.navigator });
        $(function () {
//檢查是否為支援觸控功能的IE瀏覽器
if (!$.support.ieTouch) {
                $("body").html("<span>IE on touchable device only!</span>");
return;
            }
//使用canvas繪製回應
var canvas = document.getElementById("sketchpad");
var ctx = canvas.getContext("2d");
//宣告變數儲存活動中觸控點的資訊
var touches = {}, changedTouches = {};
//傳回仿touchStart事件的touch物件
function createTouchObject(e) {
return { identifier: e.pointerId, pageX: e.clientX, pageY: e.clientY };
            }
            canvas.addEventListener("MSPointerDown", function (e) {
//由於滑鼠也會觸發,先檢查pointerType,只針對觸控做反應
if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) return;
var t = createTouchObject(e);
                touches[t.identifier] = t;
            });
            canvas.addEventListener("MSPointerMove", function (e) {
if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) return;
var t = createTouchObject(e);
var origT = touches[t.identifier];
                touches[t.identifier] = t;
//與前次保存資料比較,偵測點觸控點是否移動
if (origT &&
                    Math.abs(t.pageX - origT.pageX) + Math.abs(t.pageY - origT.pageY) > 1)
                    changedTouches[t.identifier] = t;
else
                    delete changedTouches[t.identifier];
            });
            canvas.addEventListener("MSPointerUp", function (e) {
if (e.pointerType != e.MSPOINTER_TYPE_TOUCH) return;
var t = createTouchObject(e);
//停止活動,將觸控點自touches及changedTouches移除
                delete touches[t.identifier];
                delete changedTouches[t.identifier];
            });
//定義不同顏色用來追蹤多點
var colors =
                ("red,orange,yellow,green,blue,indigo,purple," +
"aqua,khaki,darkred,lawngreen,salmon,navy," +
"deeppink,brown,olive,violet,tomato,gray").split(',');
//在canvas繪製追蹤點
            ctx.lineWidth = 3;
            ctx.font = "10pt Arial";
var r = 40;
function drawPoint(i, x, y, c, id, chg) {
                ctx.beginPath();
                ctx.fillStyle = c;
//若屬changedTouches則顯示黑框
                ctx.strokeStyle = chg ? "#000" : c;
                ctx.arc(x, y, r, 0, 2 * Math.PI, true);
                ctx.fill();
                ctx.stroke();
//顯示touch的identifier及其在陣列中的序號
//touches在上排藍字,chagedTouches在下排紅字
                ctx.fillStyle = chg ? "red" : "blue";
                ctx.fillText(id,
                    x - r, y - r - 25 + (chg ? 15 : 0));
            }
//清除canvas
function clearCanvas() {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
            }
//利用identifier識別,相同時要保持同一個顏色
var touchHash = {}, colorIdx = 0;
function getColor(id) {
if (touchHash[id] == undefined)
                    touchHash[id] = ++colorIdx % colors.length;
return colors[touchHash[id]];
            }
//每秒更新20次,顯示目前的多點觸控資訊
            setInterval(function () {
                clearCanvas();
//console.log(JSON.stringify(touches));
for (var i in touches) {
var t = touches[i];
                    drawPoint(i, t.pageX, t.pageY, getColor(t.identifier),
                              t.identifier);
                }
for (var i in changedTouches) {
var t = changedTouches[i];
                    drawPoint(i, t.pageX, t.pageY, getColor(t.identifier),
                              t.identifier, true);
                }
            }, 50);
        });
</script>
</head>
<bodystyle="padding: 0px; margin: 0px;">
<canvasid="sketchpad"width="1366"height="760"style="border: 1px solid gray">
</canvas>
</body>
</html>

實測結果如下: (幸好最多只有10點,不然連腳都要舉起來"觸控"才能完成測試,肯定抽筋)

Image may be NSFW.
Clik here to view.

Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Viewing all articles
Browse latest Browse all 2480

Trending Articles