Beispiel:JS-Anw-RoI.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" media="screen" href="./Beispiel:SELFHTML-Beispiel-Grundlayout.css" /> <title>RoI</title> <style> #roi_target { padding:0; border:1px dotted black; width:200px; height:200px } </style>

<script>

"use strict";

window.addEventListener("load",function() {

get_roi("roi_target", function(xs,ys,xe,ye) { console.log(xs,ys,xe,ye); },false);

},false);


// Bei einem Element mit Maus oder Touch oder Tastatur einen rechteckigen Bereich (Region of Interest) auswählen // Version 11 vom 3. 1. 2018 "use strict"; var get_roi = function(ele,callback,preserveAspectRatio) { // ele: ID des sensiblen Elements // callback: Funktion, die nach dem Markieren aufgerufen wird // preserveAspectRatio: Verzerren möglich (false) oder nicht (true) var roi = document.getElementById(ele); if(!roi) { console.error(ele + " nicht gefunden!"); return; } // Target-Element relativ positioniern und Canvas für das RoI-Rechteck anlegen roi.style.position = "relative"; roi.style.cursor = "crosshair"; var roi_width = roi.clientWidth; var roi_height = roi.clientHeight; if(roi_height==0) { console.error("Höhe 0 reicht nicht!"); return; } var aspectRatio = roi_width/roi_height; var cv = document.createElement("canvas"); cv.style.position = "absolute"; cv.width = roi_width; cv.height = roi_height; cv.style.left = 0; cv.style.top = 0; roi.appendChild(cv); var ctx = cv.getContext("2d"); ctx.lineWidth = 1; ctx.strokeStyle = 'gray';

// Ermitteln der unterstützten Methoden var can_touch = ("TouchEvent" in window); var can_pointer = ("PointerEvent" in window);

// Statusvariablen var pointer_active = false; var touch_active = false; var mouse_active = false; var moved = false;

// Weitere Variablen var xs=0,xe=roi_width,ys=0,ye=roi_height,offset,pointereventcache=[];

// Zeichnen eines Rechtecks var draw_rect = function(xs,ys,xe,ye) { ctx.clearRect(0,0,roi_width,roi_height); ctx.strokeRect(xs,ys,xe-xs,ye-ys); } // draw_rect

// Löschen des Rechtecks var clear_rect = function() { ctx.clearRect(0,0,roi_width,roi_height); } // clear_rect

// Rechteck zum Quadrat vergrößern var fix_aspectRatio = function() { var dx = xe - xs; var dy = ye - ys; var sdx = dx>0?1:-1; var sdy = dy>0?1:-1; var adx = dx*sdx; var ady = dy*sdy; if(adx<ady*aspectRatio) adx = ady*aspectRatio; else ady = adx/aspectRatio; dx = adx*sdx; dy = ady*sdy; xe = xs + dx; ye = ys + dy; } // fix_aspectRatio

// Eventhandler für Mausbewegung var move_mouse = function(event) { if(mouse_active) { moved = true; event.preventDefault(); xe = event.clientX - offset.left; ye = event.clientY - offset.top; if(preserveAspectRatio) fix_aspectRatio(); draw_rect(xs,ys,xe,ye); } } // move_mouse

// Eventhandler für einen oder mehrere bewegte Pointer (touch) var move_touch = function(event) { if(touch_active) { moved = true; event.preventDefault(); if(event.targetTouches.length>1) { xs = event.targetTouches[0].clientX - offset.left; ys = event.targetTouches[0].clientY - offset.top; xe = event.targetTouches[1].clientX - offset.left; ye = event.targetTouches[1].clientY - offset.top; } else { xe = event.targetTouches[0].clientX - offset.left; ye = event.targetTouches[0].clientY - offset.top; } if(preserveAspectRatio) fix_aspectRatio(); draw_rect(xs,ys,xe,ye); } } // move_touch

// Eventhandler für einen oder mehrere bewegte Pointer (pointer) var move_pointer = function(event) { if(pointer_active) { moved = true; event.preventDefault(); for (var i=0; i<pointereventcache.length; i++) { if (event.pointerId == pointereventcache[i].pointerId) { pointereventcache[i] = event; break; } } if(pointereventcache.length>1) { xs = pointereventcache[0].clientX - offset.left; ys = pointereventcache[0].clientY - offset.top; xe = pointereventcache[1].clientX - offset.left; ye = pointereventcache[1].clientY - offset.top; } else { xe = pointereventcache[0].clientX - offset.left; ye = pointereventcache[0].clientY - offset.top; } if(preserveAspectRatio) fix_aspectRatio(); draw_rect(xs,ys,xe,ye); } } // move_pointer

// Eventhandler für das Ende der Aktion bei mouseup, touchend oder pointerup var end_move = function(event) { if(pointer_active || touch_active || mouse_active) { event.preventDefault(); pointereventcache = []; clear_rect(); if(moved) callback(Math.floor(xs),Math.floor(ys),Math.floor(xe),Math.floor(ye)); xs = 0; ys = 0; xe = roi_width; ye = roi_height; pointer_active = touch_active = mouse_active = moved = false; } } // end_move

// Eventhandler für den Start der Aktion bei mousedown, touchstart oder pointerdown var start_roi = function(event) { event.preventDefault(); offset = roi.getBoundingClientRect(); if(can_pointer) { pointereventcache.push(event); if(pointereventcache.length==1) { xs = pointereventcache[0].clientX - offset.left; ys = pointereventcache[0].clientY - offset.top; } pointer_active = true; } else if(event.targetTouches && event.targetTouches.length) { if(event.targetTouches.length==1) { xs = event.targetTouches[0].clientX - offset.left; ys = event.targetTouches[0].clientY - offset.top; } touch_active = true; } else { xs = event.clientX - offset.left; ys = event.clientY - offset.top; mouse_active = true; } } // start_roi

// Die Eventhandler für pointer-, touch- und mouse-Events setzen if(can_pointer) { roi.style.touchAction = "none"; roi.addEventListener("pointerdown",start_roi,false); roi.addEventListener("pointermove",move_pointer,false); roi.addEventListener("pointerup",end_move,false); } else { if(can_touch) { roi.addEventListener("touchstart",start_roi,false); roi.addEventListener("touchmove",move_touch,false); roi.addEventListener("touchend",end_move,false); } roi.addEventListener("mousedown",start_roi,false); roi.addEventListener("mousemove",move_mouse,false); roi.addEventListener("mouseup",end_move,false); }

// Tastatursteuerung roi.tabIndex = 0; var saved_border = roi.style.border; var activecross; var info = document.createElement("output"),showinfo,removeinfo; info.style.position = "absolute"; info.style.top = "0px"; info.style.left = "0px"; info.style.margin = "10px"; info.style.backgroundColor = "white"; info.style.lineHeight = "1.4em"; info.innerHTML = "Bewegen der Ecken mit den Pfeiltasten (mit Shift schnell)
Wechseln der aktiven (roten) Ecke mit <SPACE>
Ende mit <RET>
Abruch mit <ESC>"; info.hidden = true; roi.appendChild(info);

// Zeichnen eines Fadenkreuzes var draw_crosshair = function(x,y) { ctx.beginPath(); ctx.moveTo(x-15,y); ctx.lineTo(x+15,y); ctx.moveTo(x,y-15); ctx.lineTo(x,y+15); ctx.stroke(); } // draw_crosshair

// Zeichnen eines Rechtecks mit Fadenkreuz var draw_rect_crosshair = function(xs,ys,xe,ye,active) { draw_rect(xs,ys,xe,ye); var current_color = ctx.strokeStyle; var current_width = ctx.lineWidth;

   ctx.strokeStyle = "red";

ctx.lineWidth = 3; if(active == 0) draw_crosshair(xs,ys); else if(active == 1) draw_crosshair(xe,ys); else if(active == 2) draw_crosshair(xe,ye); else draw_crosshair(xs,ye); ctx.strokeStyle = current_color; ctx.lineWidth = current_width; } // draw_rect_crosshair

// Eventhandler für focus var focus = function() { roi.style.border = "1px solid red"; xs = 10; ys = 10; xe = roi_width - 10 ; ye = roi_height - 10; activecross = 0; draw_rect_crosshair(xs,ys,xe,ye,activecross); document.documentElement.addEventListener("keydown", keydown, false); showinfo = window.setTimeout(function(){ info.hidden = false; },500); removeinfo = window.setTimeout(function(){ info.hidden = true; },12000); }

// Eventhandler für blur var blur = function() { roi.style.border = saved_border; clear_rect(); xs = 0; ys = 0; xe = roi_width ; ye = roi_height; document.documentElement.removeEventListener("keydown", keydown, false); window.clearTimeout(showinfo); window.clearTimeout(removeinfo); info.hidden = true; }

// Eventhandler für keydown var keydown = function(event) { var keyCode = event.keyCode; if(keyCode && (keyCode==13 || keyCode==27 || keyCode==32 || keyCode==37 || keyCode==38 || keyCode==39 || keyCode==40)) { var d = event.shiftKey?10:1; event.preventDefault(); window.clearTimeout(showinfo); window.clearTimeout(removeinfo); info.hidden = true; switch(keyCode){ case 37: // links if(activecross == 0 || activecross == 3) xs = Math.max(0,xs-d); else if(activecross == 1 || activecross == 2) xe = Math.max(0,xe-d); break; case 38: // rauf if(activecross == 0 || activecross == 1) ys = Math.max(0,ys-d); else if(activecross == 2 || activecross == 3) ye = Math.max(0,ye-d); break; case 39: // rechts if(activecross == 0 || activecross == 3) xs = Math.max(0,xs+d); else if(activecross == 1 || activecross == 2) xe = Math.max(0,xe+d); break; case 40: // runter if(activecross == 0 || activecross == 1) ys = Math.max(0,ys+d); else if(activecross == 2 || activecross == 3) ye = Math.max(0,ye+d); break; case 32: // space activecross = (activecross+1)%4; break; case 13: // return if(preserveAspectRatio) fix_aspectRatio(); if(xs!=xe && ys!=ye) callback(xs,ys,xe,ye); case 27: // escape blur(); return; break; } draw_rect_crosshair(xs,ys,xe,ye,activecross); } }

roi.addEventListener("focus", focus, false); roi.addEventListener("blur", blur, false);

} // get_roi

</script>

</head>

<body>

Region of Interest
Ziehen mit Maus, Touch und Pointer oder Tastatur

<main>

Im Bereich unter diesem Text kann man mit der Maus oder mit ein oder zwei Fingern ein Rechteck aufziehen. Zur Bedienung mit der Tastatur kann der Bereich mit der Tabulatortaste fokussiert werden.

<figure id="roi_target"></figure> </main> </body> </html>