SELF-Treffen in Mannheim 2025
SELFHTML wird 30 Jahre alt!
Die Mitgliederversammlung findet am 24.05.2025 um 10:00 statt. Alle Mitglieder und Interessierte sind herzlich eingeladen.
Davor und danach gibt es Gelegenheiten zum gemütlichen Beisammensein. → Veranstaltungs-Ankündigung.
Beispiel:JS-Anw-SVG-Zoom.html
Aus SELFHTML-Wiki
<!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 - SVG-Zoom</title>
<style>
#roi_target { display: table; padding:0; border:1px dotted black; }
</style>
<script>
"use strict";
window.addEventListener("load",function() {
// Zoomen eines SVG
var svg_zoom = function(id_zoom_ele, id_zoomin_button, id_zoomout_button, id_orginalgroesse_button) {
// id_zoom_ele: ID des Objects mit dem SVG
// id_zoomin_button : ID des Zoom-In-Buttons
// id_zoomout_button : ID des Zoom-Out-Buttons
// id_orginalgroesse_button: ID des Originalgröße-Buttons
var img = document.querySelector("#" + id_zoom_ele);
if(!img) {
console.error("Element " + id_zoom_ele + " nicht gefunden.");
return null;
}
var svgDoc = img.contentDocument.querySelector("svg");
if(!svgDoc) { console.error("Im Element " + id_zoom_ele + " kein SVG gefunden."); return null; }
// Original-Viewportwerte abragen
var ox0 = svgDoc.viewBox.baseVal.x;
var oy0 = svgDoc.viewBox.baseVal.y;
var owidth = svgDoc.viewBox.baseVal.width;
var oheight = svgDoc.viewBox.baseVal.height;
// Größe des SVG im Browser
var width = img.offsetWidth;
var height = img.offsetHeight;
// Skalierung
var xfaktorprodukt = owidth/width;
var yfaktorprodukt = oheight/height;
// Eventhandler für für den Originalgröße-Button
if( document.querySelector("#" + id_orginalgroesse_button) ) document.querySelector("#" + id_orginalgroesse_button).addEventListener("click",function() {
xfaktorprodukt = owidth/width;;
yfaktorprodukt = oheight/height;
svgDoc.viewBox.baseVal.width = owidth;
svgDoc.viewBox.baseVal.height = oheight;
svgDoc.viewBox.baseVal.x = ox0;
svgDoc.viewBox.baseVal.y = oy0;
});
// Eventhandler für den Zoom-Out-Button
if( document.querySelector("#" + id_zoomout_button) ) document.querySelector("#" + id_zoomout_button).addEventListener("click",function() {
zoom(-width/2,-height/2,3*width/2,3*height/2);
});
// Eventhandler für den Zoom-In-Button
if( document.querySelector("#" + id_zoomin_button) ) document.querySelector("#" + id_zoomin_button).addEventListener("click",function() {
zoom(width/4,height/4,3*width/4,3*height/4);
});
// Die Zoomfunktion
var zoom = function(xs,ys,xe,ye) {
svgDoc.viewBox.baseVal.x += xs * xfaktorprodukt;
svgDoc.viewBox.baseVal.y += ys * yfaktorprodukt;
var xfaktor = (xe-xs)/width;
var yfaktor = (ye-ys)/height;
xfaktorprodukt *= xfaktor;
yfaktorprodukt *= yfaktor;
svgDoc.viewBox.baseVal.width *= xfaktor;
svgDoc.viewBox.baseVal.height *= yfaktor;
}
return zoom;
} // svg_zoom
var svgzoom = svg_zoom("selflogo", "zp", "zm", "z0");
get_roi("roi_target", function(xs,ys,xe,ye) {
var t;
if(xe<xs) { t = xs; xs = xe; xe = t; }
if(ye<ys) { t = ys; ys = ye; ye = t; }
svgzoom(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)<br>Wechseln der aktiven (roten) Ecke mit <SPACE><br>Ende mit <RET><br>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.min(roi_width,xs+d);
else if(activecross == 1 || activecross == 2) xe = Math.min(roi_width,xe+d);
break;
case 40: // runter
if(activecross == 0 || activecross == 1) ys = Math.min(roi_height,ys+d);
else if(activecross == 2 || activecross == 3) ye = Math.min(roi_height,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>
<h1>Region of Interest - SVG-Zoom</h1>
<main>
<p>Im Bild unter diesem Text kann man mit der Maus oder mit ein oder zwei Fingern ein Rechteck aufziehen. Das Bild wird dann auf dieses Rechteck gezoomt. Zur Bedienung mit der Tastatur kann das Bild mit der Tabulatortaste fokussiert werden.</p>
<figure id="roi_target"><object data="/images/d/d5/SVG-Zoom_Selfwikilogo.svg" type="image/svg+xml" id="selflogo" width="240" height="267"></object></figure>
<button type="button" id="z0">Originalgröße</button>
<button type="button" id="zp">Vergrößern</button>
<button type="button" id="zm">Verkleinern</button>
</main>
</body>
</html>