249 lines
6.7 KiB
HTML
249 lines
6.7 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Touch and Stylus Events</title>
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
background-color: #eee;
|
|
}
|
|
|
|
#container {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
#touches {
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
#touches div {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 200px;
|
|
height: 200px;
|
|
margin-top: -100px;
|
|
margin-left: -100px;
|
|
will-change: transform;
|
|
transform: translate(0, 0);
|
|
}
|
|
|
|
#touches div svg.touch {
|
|
width: 200px;
|
|
height: 200px;
|
|
}
|
|
|
|
#touches div svg.touch circle {
|
|
cx: 100px;
|
|
cy: 100px;
|
|
fill: #cccf;
|
|
stroke: #aaa;
|
|
stroke-width: 1px;
|
|
}
|
|
|
|
#touches div.stylus svg.touch circle {
|
|
fill: #fccf;
|
|
stroke: #faa;
|
|
}
|
|
|
|
#touches div svg.touch line {
|
|
stroke: #666;
|
|
stroke-width: 4px;
|
|
stroke-linecap: round;
|
|
}
|
|
|
|
#touches div svg.altitude {
|
|
position: absolute;
|
|
top: -100px;
|
|
left: 50px;
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
#touches div svg.altitude line.x-axis {
|
|
stroke: green;
|
|
stroke-opacity: 0.6;
|
|
stroke-width: 2px;
|
|
}
|
|
|
|
#touches div svg.altitude line.angle {
|
|
stroke: #666;
|
|
stroke-width: 2px;
|
|
}
|
|
|
|
</style>
|
|
<script>
|
|
|
|
const SVGNS = "http://www.w3.org/2000/svg";
|
|
|
|
var container;
|
|
var touchObjects = {};
|
|
|
|
class TouchObject {
|
|
constructor(touch) {
|
|
this.element = document.createElement("div");
|
|
this._touchType = touch.touchType;
|
|
this.root = document.createElementNS(SVGNS, "svg");
|
|
this.root.setAttribute("class", "touch");
|
|
this.touchCircle = document.createElementNS(SVGNS, "circle");
|
|
this.root.appendChild(this.touchCircle);
|
|
if (this._touchType == "stylus") {
|
|
this.element.className = touch.touchType;
|
|
this.line = document.createElementNS(SVGNS, "line");
|
|
this.line.setAttribute("x1", 100);
|
|
this.line.setAttribute("y1", 100);
|
|
this._azimuthAngle = touch.azimuthAngle;
|
|
this.root.appendChild(this.line);
|
|
|
|
var altitudeDiagram = document.createElementNS(SVGNS, "svg");
|
|
altitudeDiagram.setAttribute("class", "altitude");
|
|
var screenAxis = document.createElementNS(SVGNS, "line");
|
|
screenAxis.setAttribute("class", "x-axis");
|
|
screenAxis.setAttribute("x1", 0);
|
|
screenAxis.setAttribute("y1", 100);
|
|
screenAxis.setAttribute("x2", 100);
|
|
screenAxis.setAttribute("y2", 100);
|
|
altitudeDiagram.appendChild(screenAxis);
|
|
this.altitudeLine = document.createElementNS(SVGNS, "line");
|
|
this.altitudeLine.setAttribute("class", "angle");
|
|
this.altitudeLine.setAttribute("x1", 1);
|
|
this.altitudeLine.setAttribute("y1", 99);
|
|
altitudeDiagram.appendChild(this.altitudeLine);
|
|
this._altitudeAngle = touch.altitudeAngle;
|
|
this.element.appendChild(altitudeDiagram);
|
|
}
|
|
|
|
this.element.appendChild(this.root);
|
|
this._x = 0;
|
|
this._y = 0;
|
|
this._size = 0;
|
|
touchObjects[touch.identifier] = this;
|
|
document.getElementById("touches").appendChild(this.element);
|
|
this._update();
|
|
}
|
|
get position() {
|
|
return {x: this._x, y: this._y};
|
|
}
|
|
set position(newPosition) {
|
|
this._x = newPosition.x;
|
|
this._y = newPosition.y;
|
|
this._update();
|
|
}
|
|
get size() {
|
|
return this._size;
|
|
}
|
|
set size(newSize) {
|
|
this._size = newSize;
|
|
this._update();
|
|
}
|
|
get azimuthAngle() {
|
|
return this._azimuthAngle;
|
|
}
|
|
set azimuthAngle(newAzimuthAngle) {
|
|
this._azimuthAngle = newAzimuthAngle;
|
|
this._update();
|
|
}
|
|
get altitudeAngle() {
|
|
return this._altitudeAngle;
|
|
}
|
|
set altitudeAngle(newAltitudeAngle) {
|
|
this._altitudeAngle = newAltitudeAngle;
|
|
this._update();
|
|
}
|
|
delete () {
|
|
document.getElementById("touches").removeChild(this.element);
|
|
this.element = null;
|
|
}
|
|
_update() {
|
|
this.element.style.transform = `translate(${this._x}px, ${this._y}px)`;
|
|
this.touchCircle.setAttribute("r", 50 + Math.round(this._size * 49));
|
|
if (this._touchType == "stylus") {
|
|
var x = Math.round(100 - Math.cos(this._azimuthAngle) * 80);
|
|
var y = Math.round(100 - Math.sin(this._azimuthAngle) * 80);
|
|
this.line.setAttribute("x2", x);
|
|
this.line.setAttribute("y2", y);
|
|
x = Math.round(Math.cos(this._altitudeAngle) * 99);
|
|
y = Math.round(100 - Math.sin(this._altitudeAngle) * 99);
|
|
this.altitudeLine.setAttribute("x2", x);
|
|
this.altitudeLine.setAttribute("y2", y);
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener("load", init, false);
|
|
|
|
function handleTouchStart(event) {
|
|
event.preventDefault();
|
|
window.addEventListener("touchmove", handleTouchMove, false);
|
|
window.addEventListener("touchforcechange", handleTouchMove, false);
|
|
window.addEventListener("touchend", handleTouchEnd, false);
|
|
window.addEventListener("touchcancel", handleTouchEnd, false);
|
|
|
|
Array.from(event.changedTouches).forEach(function (touch) {
|
|
touchObjects[touch.identifier] = new TouchObject(touch);
|
|
});
|
|
updateTouches(event.touches);
|
|
}
|
|
|
|
function handleTouchMove(event) {
|
|
event.preventDefault();
|
|
|
|
updateTouches(event.touches);
|
|
}
|
|
|
|
function handleTouchEnd(event) {
|
|
event.preventDefault();
|
|
Array.from(event.changedTouches).forEach(function (touch) {
|
|
var touchObject = touchObjects[touch.identifier];
|
|
touchObject.delete();
|
|
touchObjects[touch.identifier] = undefined;
|
|
});
|
|
updateTouches(event.touches);
|
|
|
|
if (!event.touches || !event.touches.length) {
|
|
window.removeEventListener("touchmove", handleTouchMove);
|
|
window.removeEventListener("touchforcechange", handleTouchMove);
|
|
window.removeEventListener("touchend", handleTouchEnd);
|
|
window.removeEventListener("touchcancel", handleTouchEnd);
|
|
}
|
|
}
|
|
|
|
function updateTouches(touches) {
|
|
Array.from(touches).forEach(function (touch) {
|
|
var touchObject = touchObjects[touch.identifier];
|
|
if (touchObject) {
|
|
touchObject.position = {x: touch.pageX, y: touch.pageY};
|
|
if (touch.force) {
|
|
touchObject.size = touch.force;
|
|
touchObject.azimuthAngle = touch.azimuthAngle;
|
|
touchObject.altitudeAngle = touch.altitudeAngle;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function init() {
|
|
container = document.getElementById("container");
|
|
container.addEventListener("touchstart", handleTouchStart, false);
|
|
}
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="touches"></div>
|
|
<div id="container"></div>
|
|
</body>
|
|
</html>
|