Using a CSS Clip Path as a Path

Graphics applications use masking to permit editing of selected parts of an image.
This file applies the same principle to an image in a html file;

maskText

The image on the right is the original and the image on the left is edited.
I am not an artist, but I think the left image is more vivid than the original.

This is the code:

<!DOCTYPE html>
<html>
<title>Mask</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal 600 28px Arial;background: black; color: DarkViolet}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }

</style>
</head>
<body>
<img src=”S-T/SAG.png” style=”position: absolute;” />
<img src=”S-T/SAG.png” id=”im1″ style=”position: absolute; filter: contrast(200%) brightness(90%) saturate(80%)” />
<img src=”S-T/SAG.png” style=”position: absolute; left: 400px” />

<script>
str = ‘163px 102px,192px 103px,208px 116px,224px 134px,242px 158px,258px 176px,266px 166px,274px 151px,281px 186px,278px 213px,271px 228px,253px 251px,248px 268px,245px 283px,252px 304px,268px 325px,300px 352px,139px 350px,129px 311px,111px 295px,97px 271px,89px 244px,76px 241px,71px 219px,76px 206px,84px 161px,98px 133px,113px 121px,130px 109px,149px 103px,’;
str = str.substr(0,str.length – 1);
document.getElementById(“im1”).style.clipPath = “polygon(” + str + “)”;

</script>
</body></html>

The clip path points were obtained by tracing freom the image using the modified app I had described.

The clipped image is superimposed on the original, so the original displays on sections that are clipped:
<img src=”S-T/SAG.png” style=”position: absolute;” />
<img src=”S-T/SAG.png” id=”im1″ style=”position: absolute; filter: contrast(200%) brightness(90%) saturate(80%)” />

HTML Finish Line App

This app expands the split timer to add a finish line timer. The audio is disabled for this as being only a distraction.
This is a version for mobile devices.

This is the new code:

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″&gt;
<title>HTML Editor</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15px Arial;}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }
#t1, #t2, #t3, #t4, #t5 {position: absolute; border:8px inset; font:normal normal 900 64px Times New Roman; text-align: center; width: 550px; left: 220px;}
#t2{top: 180px}
#t3{top: 300px; font-size: 48px}
#t4{top: 355px; font-size: 48px}
#t5{top: 410px; font-size: 48px}
#b1,#b2,#b3, #tm{position: relative; left: 90px; top: 80px; height: 70px; font:normal normal 900 48px Times New Roman}
#tm{width:48px; font-size: 48px}
#vce{position: absolute; top: 300px;width: 100%; text-align: center; visibility: hidden}
#frame{position: relative; width: 800px; height: 760px; top:5px; border: 8px outset; background: #cccccc;}
#ta{position: absolute; top: 5px; left: 10px; width: 170px; height: 730px}
</style>
</head>
<body>
<center><div id = “frame”>
<textarea id = “ta” ></textarea>
<input type=”text” id=”t1″ value=”” /><br /><center><input type=”button” id=”b3″ value=”Start/Split” ontouchstart=’init();’/> <input type=”button” id=”b1″ value=”Stop” onclick=’stp();’/>
<input type=”button” id=”b2″ value=”Reset” onclick=’rset();’/> <input type=”text” id=”tm” value=”1″ placeholder=”” /></center><br /> <input type=”text” id=”t2″ value=”” /><input type=”text” id=”t3″ value=”” placeholder=”secs” /><input type=”text” id=”t4″ value=”” placeholder=”mins” /><input type=”text” id=”t5″ value=”” placeholder=”hrs” />
</div></center>

<div id=”vce”></div>
<script>
var m; var h; var s; var si; var secs; var mins; var si2; var hs = 0; var ms = 0; var ss = 0; var hu = 0; var hs2 = 0; var ms2 = 0; var ss2 = 0; var hu2; var ht; var cnt = 0; var dly; var tim = false;

function init() {
cnt ++;
if (cnt == 1) {
ss = document.getElementById(“t3”).value;
if (document.getElementById(“t3”).value == “”) ss = 0;

ms = document.getElementById(“t4”).value;
if (document.getElementById(“t4”).value == “”) ms = 0;

hs = document.getElementById(“t5”).value;
if (document.getElementById(“t5”).value == “”) hs = 0;
if (hs > 0 || ms > 0 || ss > 0) {
tim = false;
} else {
tim = true;
}
si = setInterval(“strt()”,10);
}
if (cnt > 1) {
for (var i = 1; i <= parseInt( document.getElementById(“tm”).value); i ++) {
if (hs2 < 1 && ms2 < 6) {
document.getElementById(“ta”).value += hs2 + “:” + ms2 + “:” + ss2 + “:” + hu2 + “\n”;
} else {
if (ss2 == 59 && ms2 < 59) {
ms2 ++;
ss2 = 0;
}
if (ss2 == 59 && ms2 == 59) {
hs2 ++;
ms2 = 0;
ss2 = 0;
}
if(document.getElementById(“tm”).value == “1”) ss2 ++;
if (ss2 < 10 ) ss2 = “0” + ss2;
if (ss2.toString().indexOf(“00”) > -1) ss2 = ss2.replace(“00”, “0”);
document.getElementById(“ta”).value += hs2 + “:” + ms2 + “:”+ ss2 + “\n”;
}
}
document.getElementById(“tm”).value = 1;
document.getElementById(“t2”).value = hs2 + “:” + ms2 + “:” + ss2 + “:” + hu2;
speech();
}
}

function rset() {
document.getElementById(“ta”).focus();
document.getElementById(“ta”).select();
success = document.execCommand(“copy”);
setTimeout(“location.reload()”,1000);
}

function stp() {
clearInterval(si);
cnt = 0;
document.getElementById(“ta”).value = document.getElementById(“ta”).value.substr(0,document.getElementById(“ta”).value.length – 1) + ” \nStopped \n”;
}

function speech() {
if (! tim) {
m = parseInt(ms2);
h = parseInt(hs2);
s = parseInt(ss2);
if (hs2 > 0) {
dly = 300;
} else {
dly = 0;
}
play1();
setTimeout(“play2()”,dly);
setTimeout(“play3()”,dly + 550);
}
}

function play1() {
document.getElementById(“vce”).innerHTML = ‘<audio id = “a1” autoplay = “autoplay” > <source src= “numbers/English/’ + h + ‘.wav” /></audio>’;
//alert(document.getElementById(“vce”).innerHTML);
document.getElementById(“a1”).playbackRate = 2;
}
function play2() {
document.getElementById(“vce”).innerHTML = ‘<audio id = “a2” autoplay = “autoplay” > <source src= “numbers/English/’ + m + ‘.wav” /></audio>’;
document.getElementById(“a2”).playbackRate = 2;
}
function play3() {
document.getElementById(“vce”).innerHTML = ‘<audio id = “a3” autoplay = “autoplay” > <source src= “numbers/English/’ + s + ‘.wav” /></audio>’;
document.getElementById(“a3”).playbackRate = 2;
}

function strt() {
hu ++;
hu2 = hu + “”;
if (hu2 < 10) hu2 = “0” + hu2;
if (hu == 100) {
hu = 0;
ss ++;
}

ss2 = ss + “”;
if (ss2 < 10) ss2 = “0” + ss2;
if (ss == 60) {
ss = 0;
ms ++;
}

ms2 = ms + “”;
if (ms2 < 10) ms2 = “0” + ms2;
if (ms == 60) {
ms = 0;
hs ++;
}

hs2 = hs + “”;
document.getElementById(“t1”).value = hs2 + “:” + ms2 + “:” + ss2 + “:” + hu2;
}

 

</script>
</body></html>

I will discuss only the finish line.

The sound activated only for doing splits.
This is detected by the presetting of a time:
if (hs > 0 || ms > 0 || ss > 0) {
tim = false;
} else {
tim = true;
}

function speech() {
if (! tim) {
m = parseInt(ms2);
h = parseInt(hs2);
s = parseInt(ss2);
if (hs2 > 0) {
dly = 300;
} else {
dly = 0;
}
play1();
setTimeout(“play2()”,dly);
setTimeout(“play3()”,dly + 550);
}
}

For times less than 6 minutes, the text area lists to the 1/100 second.
Above 6 minutes the times are rounded up to the nearest second, to be in compliance with the rules for race timing:
if (hs2 < 1 && ms2 < 6) {
document.getElementById(“ta”).value += hs2 + “:” + ms2 + “:” + ss2 + “:” + hu2 + “\n”;
if (hs2 < 1 && ms2 < 6) {
document.getElementById(“ta”).value += hs2 + “:” + ms2 + “:” + ss2 + “:” + hu2 + “\n”;
} else {
if (ss2 == 59 && ms2 < 59) {
ms2 ++;
ss2 = 0;
}
if (ss2 == 59 && ms2 == 59) {
hs2 ++;
ms2 = 0;
ss2 = 0;
}
if(document.getElementById(“tm”).value == “1”) ss2 ++;
if (ss2 < 10 ) ss2 = “0” + ss2;
if (ss2.toString().indexOf(“00”) > -1) ss2 = ss2.replace(“00”, “0”);
document.getElementById(“ta”).value += hs2 + “:” + ms2 + “:”+ ss2 + “\n”;
}

One of the banes of hand timing is entering times for multiple runners finishing very close.
There is often an error with rapid clicking, either a time not registering or accidentally clicking too many times.
One of the worst things is having the list of times not equal to the list of finishers.

This treats that in the following manner:
As runners approach the finish, if it appears multiple runners will finish nearly simultaneously, the number of mutiple finishers is entered
in text box tm.
Then when Split is touched, the list has mutuple copies of the same time added.

When the race is over, clicking Reset selects and copies the time list, so it can be pasted into a spreadsheet.

This is an example of a simulated spreadsheet:

audiostopwatch2Text

Tracing a Polygon CSS Clip Path

I had previously described a polygon clip path derived from equations.
The points for this clip path are traced from an image.
I modified an app I had written to allow it to generate the points for the clip path.
This is the modified code:

<!DOCTYPE html>
<html xmlns=’http://www.w3.org/1999/xhtml’&gt;
<head profile=’http://gmpg.org/xfn/11′&gt;
<title>Bezier</title>
<style type=’text/css’>
body {margin-left:0;margin-right:0;font:normal normal normal 12px Arial;}
a{ text-decoration: }
:link { color: rgb(0, 0, 255) }
:visited {color :rgb(100, 0,100) }
:hover { }
:active { }
.d1{position: absolute; width: 1600px; height: 850px; left: 0; top: 50px}
#canvas{position: absolute; width: 1600px; height: 900px: left: 0; top: 0}
form {position: absolute; width: 1500px; left: 50%; margin-left: -650px;}
#values{position: relative; width: 850px; font:normal normal 700 15px Arial}
#files{position: relative; width: 100px; values font:normal normal 700 15px Arial}
#limt {position: relative; width: 25px; font:normal normal 700 15px Arial}
</style>
</head>
<body>
<div id=’canvas’></div>
<form name=”form1″>
<select id=”radio1″ name=”radio1″ value=”” onchange = ‘getChecked(“1”);’ >
<option>jsDraw2d</option>
<option>Trace Image</option>
</select>

<select id=”radio2″ name=”radio2″ value=”” onchange = ‘getChecked(“2”);’ >
<option>SVG</option>
<option>SVG Poly</option>
<option>CSS Poly</option>
</select>

<input id = “values” type=”text” name=”values” value=”” />
<input type=”file” id = “files” name=”files” value=”test” onchange=’filenme();’ />
<input id = “color” type=”color” name=”color” value=simple color />
# pts
<input id = “limt” type=”text” name=”limt” value=”0″ />
</form>
<div class=”d1″>
<svg width=”100%” height=”100%” xmlns=”http://www.w3.org/2000/svg”&gt;
<defs>
<pattern id=”smallGrid” width=”8″ height=”8″ patternUnits=”userSpaceOnUse”>
<path d=”M 8 0 L 0 0 0 8″ fill=”none” stroke=”gray” stroke-width=”0.5″/>
</pattern>
<pattern id=”grid” width=”80″ height=”80″ patternUnits=”userSpaceOnUse”>
<rect width=”80″ height=”80″ fill=”url(#smallGrid)”/>
<path d=”M 80 0 L 0 0 0 80″ fill=”none” stroke=”gray” stroke-width=”1″/>
</pattern>
</defs>

<rect width=”100%” height=”100%” fill=”url(#grid)” />
</svg>
</div>

<select id=”fldr” name=”fldr” style=”position: absolute; left: 400px; top: 2px; ” >
<option>Choose Folder</option>
<option></option>
<option>A-E/</option>
<option>F-J/</option>
<option>K-O/</option>
<option>P-R/</option>
<option>S-T/</option>
</select>

http://jsDraw2D.js
<script type=”text/JavaScript”>

var IE = document.all?true:false;
if (!IE) document.captureEvents(Event.MOUSEMOVE)
document.onclick = getMouse2;;
document.onmousemove = getMouseXY;
var tempX = 0;
var tempY = 0;
var lim = 0;
var cl = “”;
var cnt = 0;
var fname = “”;
var px = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
var py = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
var col = new jsColor(“red”);
var col2 = new jsColor(“blue”);
var pen = new jsPen(col,3);
var on = false; var str2 = “”;
var gr = new jsGraphics(document.getElementById(“canvas”));
var radiovalue; var ini = 0;

function filenme() {
if (document.getElementById(“files”).value != “” && document.getElementById(“files”).value != “Choose File”) fname = document.getElementById(“files”).value;
fname = fname.substr(fname.lastIndexOf(“\\”) + 1);
fname = document.getElementById(“fldr”).value + fname;
}

function getChecked(l) {
if (l == “1”) radiovalue = document.form1.radio1.value;
if (l == “2”) radiovalue = document.form1.radio2.value;
if (radiovalue == “CSS Poly”) {
document.getElementById(“values”).value = document.getElementById(“values”).value.replace(‘style=”fill: ;stroke: ;stroke-width: ” />’,”);
document.getElementById(“values”).value = document.getElementById(“values”).value.replace(‘<polygon points=”‘,”);
document.getElementById(“values”).value = document.getElementById(“values”).value.replace(new RegExp(‘,’, ‘g’),’px ‘);
document.getElementById(“values”).value = document.getElementById(“values”).value.replace(new RegExp(‘” ‘, ‘g’),’px,’);
}
if (radiovalue == “Trace Image”) gr.drawImage(fname, new jsPoint(0,40));
document.getElementById(“fldr”).style.visibility=”hidden”;
}

function drawPolyBezier() {
gr.fillRectangle(new jsColor(“white”),new jsPoint(0,40) , 1600,900);
var points = new Array();

if (radiovalue == “SVG Poly” ) {
for (var i = 0; i < lim; i ++) {
if (py[i] > 40 && lim > 1) {
points[i] = new jsPoint(px[i], py[i]);
gr.fillCircle(col2, points[i], 3);
}
}
}

if (radiovalue == “SVG Poly”) {
gr.fillPolygon(new jsColor(“#EEFFF8”), points);
gr.fillPolygon(new jsColor(cl), points);
gr.drawPolygon(new jsPen( new jsColor(“black”),3), points);
}
}

for (var i = 0; i < lim; i ++) {
if (py[i] > 40 && lim > 1) {
points[i] = new jsPoint(px[i], py[i]);
gr.fillCircle(col2, points[i], 6);
}
}

function getMouse2(e) {
cl = document.getElementById(“color”).value;
if (cnt < 2) lim = parseInt(document.getElementById(“limt”).value);
if (lim > 1 ) {
if (on ) {
on = false;
} else if (cnt > lim) {
on = true;
}
tempX = e.pageX;
tempY = e.pageY;
if (tempX < 0){tempX = 0;}
if (tempY < 0){tempY = 0;}
if (tempY > 40) cnt ++;
if (cnt <= lim) document.getElementById(“values”).value = cnt;

if (radiovalue == “SVG Poly”) {
if ( cnt <= lim) {
px[cnt – 1] = tempX;
py[cnt -1]= tempY;
gr.fillCircle(col2, new jsPoint(px[cnt – 1] , py[cnt – 1]), 3);
if (cnt == lim) drawPolyBezier();
}
}
}
return true;
}

function getMouseXY(e) {
if (cnt > 1 && on && lim) {
tempX = e.pageX;
tempY = e.pageY;
if (tempX < 0)tempX = 0;
if (tempY < 0)tempY = 0;

if ( radiovalue == “SVG Poly”) ini = 0;
for (var j = ini; j <= lim; j ++) {
if ((Math.abs(tempX – px[j]) < 5 && Math.abs(tempY – py[j]) < 5) ) {
px[j] = tempX;
py[j] = tempY;
}
}

var str2 = “”;
if (radiovalue == “SVG Poly”) str2 = str2 + ‘<polygon points=”‘;
for (var i = 0; i <= lim + 1; i ++) {
if (py[i] > 40 && radiovalue == “SVG Poly”) str2 = str2 + px[i].toString() + ‘,’ + (py[i] – 40).toString() + ‘” ‘;
}
if (radiovalue == “SVG Poly”) str2 = str2 + ‘style=”fill: ;stroke: ;stroke-width: ” />’ ;

document.getElementById(“values”).value = str2;
str2 = “”;
if (radiovalue != “CSS Poly”) drawPolyBezier();

}
if (cnt == lim) on = false;

return true;
}

</script>
</body></html>

This is a tracing of a part of an image when set to clip a division:

Mask2Text

This is the code:

<!DOCTYPE html>
<html>
<title>Mask</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal 600 28px Arial;background: black; color: DarkViolet}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }

</style>
</head>
<body>
<div id=”d1″ style=”position: absolute; width: 500px; height: 500px; background: yellow” ></div>

<script>
var str = “”;

str = ‘163px 102px,192px 103px,208px 116px,224px 134px,242px 158px,258px 176px,266px 166px,274px 151px,281px 186px,278px 213px,271px 228px,253px 251px,248px 268px,245px 283px,252px 304px,268px 325px,300px 352px,139px 350px,129px 311px,111px 295px,97px 271px,89px 244px,76px 241px,71px 219px,76px 206px,84px 161px,98px 133px,113px 121px,130px 109px,149px 103px,’;
str = str.substr(0,str.length – 1);
document.getElementById(“d1”).style.clipPath = “polygon(” + str + “)”;

</script>
</body></html>

As before, the clip path is added to the division style:
str = ‘163px 102px,192px 103px,208px 116px,224px 134px,242px 158px,258px 176px,266px 166px,274px 151px,281px 186px,278px 213px,271px 228px,253px 251px,248px 268px,245px 283px,252px 304px,268px 325px,300px 352px,139px 350px,129px 311px,111px 295px,97px 271px,89px 244px,76px 241px,71px 219px,76px 206px,84px 161px,98px 133px,113px 121px,130px 109px,149px 103px,’;
str = str.substr(0,str.length – 1);

document.getElementById(“d1”).style.clipPath = “polygon(” + str + “)”;

CSS Clip Paths

There is a SVG clip path that can crop images to a predefined shape.
There is now a CSS clip path that can crop images as well as other elements.
The shapes that can be used are Circle, Ellipse, Polygon and a Rectangle.

Here is an example of a Circle clip path which together with another division forms a sort of silo or bullet.

CSSClipText

This is the code:

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head profile=”http://gmpg.org/xfn/11″><defs&gt;
<title>Silo</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal normal 15px Arial; background: #555555}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }
</style>
<body>
<div id=”d1″ style= “position: absolute; top: -150px; left: 50%; margin-left: -150px; width:300px; height: 300px; background-image: -webkit-radial-gradient(center center, circle closest-corner, #eeeeee 5%, #888888 80%); ;clip-path: circle(150px at 150px 300px);” ></div>
<div id=”d2″ style= “position: absolute; top: 150px; left: 50%; margin-left: -150px; width:300px; height: 500px; background-image: -webkit-linear-gradient(left,#888888,#bbbbbb,#eeeeee,#bbbbbb,#888888” ></div>
</body></html>

The second division was given a bilinear gradient and placed at the bottom of the first.
div id=”d2″ style= “position: absolute; top: 150px; left: 50%; margin-left: -150px; width:300px; height: 500px; background-image: -webkit-linear-gradient(left,#888888,#bbbbbb,#eeeeee,#bbbbbb,#888888” ></div>

I could have clipped the first division to a circle and covered half with the second division, but I made a semicircular clip by placing the top at -15opx:
<div id=”d1″ style= “position: absolute; top: -150px; left: 50%; margin-left: -150px; width:300px; height: 300px; background-image: -webkit-radial-gradient(center center, circle closest-corner, #eeeeee 5%, #888888 80%); ;clip-path: circle(150px at 150px 300px);” ></div>

This is an example of a Polygon Clip Path:

CSSClipText2

<img src = “images/CSSClipText2.png” />

This is that code:

<!DOCTYPE html>
<html>
<head>
<title>CSS Poly Clip</title>
<style>
body {margin-left:0;margin-right:0;font:normal normal 600 28px Arial;background: black; color: DarkViolet}
a{ text-decoration: }:link { color: rgb(0, 0, 255) }:visited {color :rgb(100, 0,100) }:hover { }:active { }

</style>
</head>
<body>
<div id=”d1″ style=”position: absolute;width: 300px; height: 300px; top: 100px; left: 500px; background-image: -webkit-linear-gradient(left,#888855,#aaaa55,#bbbb55,#eeee55,#bbbb55,#aaaa55,#888855); text-align: center” ><br /><br /><br /><br />This is a test</div>
<script>
var ang = -Math.PI/6; var ptX = []; var ptY = []; var str = “”;
for (var i = 0; i <= 11; i ++) {
ang += Math.PI / 6;
ptX[i] = 150 + Math.round(150 * Math.sin(ang)) + “px”;
ptY[i] = 150 + Math.round(150 * Math.cos(ang)) + “px”;
str += ptX[i] + ” ” + ptY[i] + “,” ;
}

str = str.substr(0,str.length – 1);
document.getElementById(“d1”).style.clipPath = “polygon(” + str + “)”;

</script>
</body></html>

I generated a dodecagon clip path and used it to crop a division with a gold bilinear gradient:
<script>
var ang = -Math.PI/6; var ptX = []; var ptY = []; var str = “”;
for (var i = 0; i <= 11; i ++) {
ang += Math.PI / 6;
ptX[i] = 150 + Math.round(150 * Math.sin(ang)) + “px”;
ptY[i] = 150 + Math.round(150 * Math.cos(ang)) + “px”;
str += ptX[i] + ” ” + ptY[i] + “,” ;
}

str = str.substr(0,str.length – 1);
document.getElementById(“d1”).style.clipPath = “polygon(” + str + “)”;

HTML Interactive Word Process Like Documents

This HTML file interactively creates word processor type pages than can be printed to pdf files.
This is the page as first loaded:

WPText

and after interactively adjusting:

WPText2

This is the code:

<!DOCTYPE html>
<html><head><title>Page</title>
<style>
#tb{position: relative; left: 0; }
td {border: 1px solid; text-align: center}
</style>
<body>
<center>
<div style=”position: relative; width:680px; height:900px; border:1px solid; padding: 68px 34px 34px 68px; font: normal normal 500 15pt Times New Roman; text-align: left” contenteditable=”true”>

<span id=”sp1″ style=”position: relative; border: 1px solid; font: normal normal 600 18pt Times New Roman” onclick=’sze(“s1”);’>This is a test</span>

<img id=”im1″ src=”SAG.png” width=”120″ onclick=’sze(“1”);’/>

This is also a test

<img id=”im2″ src=”SAG.png” width=”120″ onclick=’sze(“2”);’/>

<table id = “tb”><tr><td onclick = ‘sze(“t1”);’>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>
</div>
<div style=”position: relative; top: 10px; width:680px; height:900px; border:1px solid; padding: 68px 34px 34px 68px; font: normal normal 500 15pt Times New Roman; text-align: left” contenteditable=”true”>
</div>
</center>
<script>
var wd; var ht; var el;
function sze(par) {
el = par;
if (el == “1”) {
wd = im1.clientWidth;
ht = im1.clientHeight;
}
if (el == “2”) {
wd = im2.clientWidth;
ht = im2.clientHeight;
}
if(el == “t1” || el == “s1”) wd = 0;
}
document.onkeydown = prnt;
function prnt(e) {
if (e.keyCode == 18) window.print();
if (e.keyCode == 39) wd += 5;
if (e.keyCode == 37) wd -= 5;
if (el == “1”) document.getElementById(“im1”).style.width = wd + “px”;
if (el == “2”) document.getElementById(“im2”).style.width = wd + “px”;
if (el == “t1”) document.getElementById(“tb”).style.left = wd + “px”;
if (el == “s1”) document.getElementById(“sp1”).style.left = wd + “px”;
}
</script>
</body></html>

It is best to prepare the page and then modify it interactively.
This is the page as created:
<center>
<div style=”position: relative; width:680px; height:900px; border:1px solid; padding: 68px 34px 34px 68px; font: normal normal 500 15pt Times New Roman; text-align: left” contenteditable=”true”>

<span id=”sp1″ style=”position: relative; border: 1px solid; font: normal normal 600 18pt Times New Roman” onclick=’sze(“s1”);’>This is a test</span>

<img id=”im1″ src=”SAG.png” width=”120″ onclick=’sze(“1”);’/>

This is also a test

<img id=”im2″ src=”SAG.png” width=”120″ onclick=’sze(“2”);’/>

<table id = “tb”><tr><td onclick = ‘sze(“t1”);’>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>
</div>
<div style=”position: relative; top: 10px; width:680px; height:900px; border:1px solid; padding: 68px 34px 34px 68px; font: normal normal 500 15pt Times New Roman; text-align: left” contenteditable=”true”>
</div>
</center>

The two division “pages” are made contenteditable.

I included two images, reduced to take less space, which can be resized:
<img id=”im1″ src=”SAG.png” width=”120″ onclick=’sze(“1”);’/>

<img id=”im2″ src=”SAG.png” width=”120″ onclick=’sze(“2”);’/>

I also included two texts,one of which was placed in a span:
<span id=”sp1″ style=”position: relative; border: 1px solid; font: normal normal 600 18pt Times New Roman” onclick=’sze(“s1”);’>This is a test</span> – I edited this string.

This is also a test

I also added a table which I resized and moved:
<table id = “tb”><tr><td onclick = ‘sze(“t1”);’>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>

The script includes a keydown listener:
document.onkeydown = prnt;

The alt key prints the page to a pdf file:
function prnt(e) {
if (e.keyCode == 18) window.print();

Clicking an element calls the function sze(par):
function sze(par) {
el = par;
if (el == “1”) {
wd = im1.clientWidth;
ht = im1.clientHeight;
}
if (el == “2”) {
wd = im2.clientWidth;
ht = im2.clientHeight;
}
if(el == “t1” || el == “s1”) wd = 0;
}

wd is used to resize the selected image or move the table or span, controlled by the right and left arrows:
if (e.keyCode == 39) wd += 5;
if (e.keyCode == 37) wd -= 5;
if (el == “1”) document.getElementById(“im1”).style.width = wd + “px”;
if (el == “2”) document.getElementById(“im2”).style.width = wd + “px”;
if (el == “t1”) document.getElementById(“tb”).style.left = wd + “px”;
if (el == “s1”) document.getElementById(“sp1”).style.left = wd + “px”;

The contents of both the table and span can be modified interactively.