Fix scaling and tidy html
This commit is contained in:
parent
111eab6cf0
commit
ae76368d4d
4 changed files with 253 additions and 242 deletions
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# svganim
|
||||||
|
|
||||||
|
Create a hand drawn vector animation.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry run python webserver.py
|
||||||
|
```
|
310
www/draw.html
310
www/draw.html
|
@ -1,164 +1,168 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" dir="ltr">
|
<html lang="en" dir="ltr">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Draw a line animation</title>
|
|
||||||
<style media="screen">
|
|
||||||
#sample, svg{
|
|
||||||
position:absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right:0;
|
|
||||||
width:100%;
|
|
||||||
height:100%;
|
|
||||||
font-family: sans-serif;
|
|
||||||
z-index:2;
|
|
||||||
cursor: url('/cursor.png') 6 6, auto;
|
|
||||||
}
|
|
||||||
img{
|
|
||||||
position:absolute;
|
|
||||||
top:0;
|
|
||||||
bottom:0;
|
|
||||||
right:0;
|
|
||||||
left:0;
|
|
||||||
width:100%;
|
|
||||||
height:100%;
|
|
||||||
z-index:1;
|
|
||||||
}
|
|
||||||
|
|
||||||
path {
|
<head>
|
||||||
fill: none;
|
<meta charset="utf-8">
|
||||||
stroke: red;
|
<title>Draw a line animation</title>
|
||||||
stroke-width: 1mm;
|
<style media="screen">
|
||||||
stroke-linecap: round;
|
#sample,
|
||||||
}
|
svg {
|
||||||
|
position: absolute;
|
||||||
#wrapper {
|
top: 0;
|
||||||
position:absolute;
|
left: 0;
|
||||||
top:0;
|
bottom: 0;
|
||||||
right:0;
|
right: 0;
|
||||||
bottom:0;
|
width: 100%;
|
||||||
left:0;
|
height: 100%;
|
||||||
background:none;
|
font-family: sans-serif;
|
||||||
}
|
z-index: 2;
|
||||||
.gray{
|
cursor: url('/cursor.png') 6 6, auto;
|
||||||
position:absolute;
|
}
|
||||||
background:rgba(255,255,255,0.7);
|
|
||||||
}
|
img {
|
||||||
html, body{
|
position: absolute;
|
||||||
height: 100%;
|
top: 0;
|
||||||
width: 100%;
|
bottom: 0;
|
||||||
margin:0;
|
right: 0;
|
||||||
font-family: sans-serif;
|
left: 0;
|
||||||
}
|
width: 100%;
|
||||||
#interface{
|
height: 100%;
|
||||||
height: 0;
|
z-index: 1;
|
||||||
overflow: hidden;
|
}
|
||||||
padding-top: calc({HEIGHT}/{WIDTH} * 100%);
|
|
||||||
position: relative;
|
path {
|
||||||
margin: 0 auto;
|
fill: none;
|
||||||
background-size: 100% 100%;
|
stroke: red;
|
||||||
position: absolute;
|
stroke-width: 1mm;
|
||||||
top: 0;
|
stroke-linecap: round;
|
||||||
left: 0;
|
}
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
#wrapper {
|
||||||
}
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
#info{
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gray {
|
||||||
|
position: absolute;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#interface {
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
padding-top: calc( {
|
||||||
|
HEIGHT
|
||||||
|
}
|
||||||
|
|
||||||
|
/ {
|
||||||
|
WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
* 100%);
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#info {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 15px;
|
bottom: 15px;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
left: calc(50% - 250px);
|
left: calc(50% - 250px);
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
.buttons{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#submit{
|
|
||||||
background: lightblue;
|
|
||||||
border: solid 1px blue;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-size: 110%;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
.toolbox{
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 50px;
|
|
||||||
z-index: 100;
|
|
||||||
background-color: white;
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 0 5px 5px 0;
|
|
||||||
background-color:#ccc;
|
|
||||||
}
|
|
||||||
.toolbox > ul{
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.toolbox > ul > li{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toolbox .colors > li.selected {
|
.buttons {
|
||||||
border-width: 3px;
|
text-align: center;
|
||||||
border-color: gray;
|
}
|
||||||
}
|
|
||||||
.toolbox .colors > li {
|
|
||||||
display: block;
|
|
||||||
border: solid 3px white;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
width: 25px;
|
|
||||||
height: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filename{
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
color:gray;
|
|
||||||
z-index: -1;
|
|
||||||
font-size:8pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
.closed{
|
#submit {
|
||||||
background-color: lightgray;
|
background: lightblue;
|
||||||
}
|
border: solid 1px blue;
|
||||||
.closed svg{
|
border-radius: 5px;
|
||||||
cursor:wait;
|
font-size: 110%;
|
||||||
pointer-events: none;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id='interface'>
|
|
||||||
</div>
|
|
||||||
<!-- <div id='wrapper'>
|
|
||||||
<svg id="canvas" preserveAspectRatio="none">
|
|
||||||
<path d="" id="stroke" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div id='info'>
|
|
||||||
<div class='buttons'>
|
|
||||||
|
|
||||||
<button id='submit'>Submit</button>
|
.toolbox {
|
||||||
<form method='post' action='' id='finishedForm'>
|
position: absolute;
|
||||||
</form>
|
left: 0;
|
||||||
</div>
|
top: 50px;
|
||||||
</div>
|
z-index: 100;
|
||||||
<div class="toolbox">
|
background-color: white;
|
||||||
<ul class="colors">
|
padding: 5px;
|
||||||
<li class="red"></li>
|
border-radius: 0 5px 5px 0;
|
||||||
<li class="blue"></li>
|
background-color: #ccc;
|
||||||
<li class="green"></li>
|
}
|
||||||
</ul>
|
|
||||||
</div>
|
.toolbox>ul {
|
||||||
</div> -->
|
padding: 0;
|
||||||
<script src="draw.js"></script>
|
margin: 0;
|
||||||
<script type='text/javascript'>
|
}
|
||||||
const canvas = new Canvas( document.getElementById("interface"));
|
|
||||||
</script>
|
.toolbox>ul>li {
|
||||||
</body>
|
cursor: pointer;
|
||||||
</html>
|
}
|
||||||
|
|
||||||
|
.toolbox .colors>li.selected {
|
||||||
|
border-width: 3px;
|
||||||
|
border-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbox .colors>li {
|
||||||
|
display: block;
|
||||||
|
border: solid 3px white;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filename {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
color: gray;
|
||||||
|
z-index: -1;
|
||||||
|
font-size: 8pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closed {
|
||||||
|
background-color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closed svg {
|
||||||
|
cursor: wait;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id='interface'>
|
||||||
|
</div>
|
||||||
|
<script src="draw.js"></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
const canvas = new Canvas(document.getElementById("interface"));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
156
www/play.html
156
www/play.html
|
@ -1,74 +1,88 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" dir="ltr">
|
<html lang="en" dir="ltr">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Play a line animation</title>
|
|
||||||
<style media="screen">
|
|
||||||
#sample, svg{
|
|
||||||
position:absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right:0;
|
|
||||||
width:100%;
|
|
||||||
height:100%;
|
|
||||||
font-family: sans-serif;
|
|
||||||
z-index:2;
|
|
||||||
cursor: url('/cursor.png') 6 6, auto;
|
|
||||||
}
|
|
||||||
img{
|
|
||||||
position:absolute;
|
|
||||||
top:0;
|
|
||||||
bottom:0;
|
|
||||||
right:0;
|
|
||||||
left:0;
|
|
||||||
width:100%;
|
|
||||||
height:100%;
|
|
||||||
z-index:1;
|
|
||||||
}
|
|
||||||
|
|
||||||
path {
|
<head>
|
||||||
fill: none;
|
<meta charset="utf-8">
|
||||||
stroke: gray;
|
<title>Play a line animation</title>
|
||||||
stroke-width: 1mm;
|
<style media="screen">
|
||||||
stroke-linecap: round;
|
#sample,
|
||||||
}
|
svg {
|
||||||
|
position: absolute;
|
||||||
#wrapper {
|
top: 0;
|
||||||
position:absolute;
|
left: 0;
|
||||||
top:0;
|
bottom: 0;
|
||||||
right:0;
|
right: 0;
|
||||||
bottom:0;
|
width: 100%;
|
||||||
left:0;
|
height: 100%;
|
||||||
background:none;
|
font-family: sans-serif;
|
||||||
}
|
z-index: 2;
|
||||||
.gray{
|
}
|
||||||
position:absolute;
|
|
||||||
background:rgba(255,255,255,0.7);
|
img {
|
||||||
}
|
position: absolute;
|
||||||
html, body{
|
top: 0;
|
||||||
height: 100%;
|
bottom: 0;
|
||||||
width: 100%;
|
right: 0;
|
||||||
margin:0;
|
left: 0;
|
||||||
font-family: sans-serif;
|
width: 100%;
|
||||||
}
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
.playlist{
|
}
|
||||||
position: absolute;
|
|
||||||
left:0;
|
path {
|
||||||
top:0;
|
fill: none;
|
||||||
z-index: 50;
|
stroke: gray;
|
||||||
}
|
stroke-width: 1mm;
|
||||||
</style>
|
stroke-linecap: round;
|
||||||
</head>
|
}
|
||||||
<body>
|
|
||||||
<div id='interface'>
|
#wrapper {
|
||||||
</div>
|
position: absolute;
|
||||||
<script src="play.js"></script>
|
top: 0;
|
||||||
<script type='text/javascript'>
|
right: 0;
|
||||||
const player = new Player( document.getElementById("interface"));
|
bottom: 0;
|
||||||
player.playlist('/files/');
|
left: 0;
|
||||||
// player.play('/files/2021-11-22-3-75b0f0');
|
background: none;
|
||||||
</script>
|
}
|
||||||
</body>
|
|
||||||
</html>
|
.gray {
|
||||||
|
position: absolute;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist li{
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.playlist li:hover{
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id='interface'>
|
||||||
|
</div>
|
||||||
|
<script src="play.js"></script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
const player = new Player(document.getElementById("interface"));
|
||||||
|
player.playlist('/files/');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
22
www/play.js
22
www/play.js
|
@ -6,7 +6,6 @@ class Player {
|
||||||
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
this.wrapperEl.appendChild(this.svgEl);
|
this.wrapperEl.appendChild(this.svgEl);
|
||||||
|
|
||||||
this.resize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist(url) {
|
playlist(url) {
|
||||||
|
@ -34,7 +33,7 @@ class Player {
|
||||||
liEl.innerText = fileUrl
|
liEl.innerText = fileUrl
|
||||||
liEl.addEventListener('click', (e) => {
|
liEl.addEventListener('click', (e) => {
|
||||||
this.play(fileUrl);
|
this.play(fileUrl);
|
||||||
|
playlist.style.display = "none";
|
||||||
});
|
});
|
||||||
listEl.appendChild(liEl);
|
listEl.appendChild(liEl);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +61,7 @@ class Player {
|
||||||
this.strokes = drawing.shape;
|
this.strokes = drawing.shape;
|
||||||
this.currentPath = null;
|
this.currentPath = null;
|
||||||
this.dimensions = drawing.dimensions;
|
this.dimensions = drawing.dimensions;
|
||||||
this.svgEl.setAttributeNS('http://www.w3.org/2000/svg', 'viewBox', `0 0 ${this.dimensions.width} ${this.dimensions.height}`)
|
this.svgEl.setAttribute('viewBox', `0 0 ${this.dimensions[0]} ${this.dimensions[1]}`)
|
||||||
this.startTime = window.performance.now() - this.strokes[0].points[0][3];
|
this.startTime = window.performance.now() - this.strokes[0].points[0][3];
|
||||||
this.playStroke(0,1);
|
this.playStroke(0,1);
|
||||||
}
|
}
|
||||||
|
@ -105,19 +104,6 @@ class Player {
|
||||||
// for scrubber
|
// for scrubber
|
||||||
}
|
}
|
||||||
|
|
||||||
resize() {
|
|
||||||
this.width = window.innerWidth;
|
|
||||||
this.height = window.innerHeight;
|
|
||||||
const viewBox = `0 0 ${this.width} ${this.height}`;
|
|
||||||
this.svgEl.setAttribute('viewBox', viewBox);
|
|
||||||
this.svgEl.setAttribute('width', this.width + 'mm');
|
|
||||||
this.svgEl.setAttribute('height', this.height + 'mm');
|
|
||||||
}
|
|
||||||
|
|
||||||
requestResize() {
|
|
||||||
alert('Resize not implemented yet. Please reloade the page');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
strokes2D(strokes) {
|
strokes2D(strokes) {
|
||||||
// strokes to a d attribute for a path
|
// strokes to a d attribute for a path
|
||||||
|
@ -126,7 +112,7 @@ class Player {
|
||||||
let cmd = "";
|
let cmd = "";
|
||||||
for (let stroke of strokes) {
|
for (let stroke of strokes) {
|
||||||
if (!last_stroke) {
|
if (!last_stroke) {
|
||||||
d += `M${stroke[0] * this.width},${stroke[1] * this.height} `;
|
d += `M${stroke[0] * this.dimensions[0]},${stroke[1] * this.dimensions[1]} `;
|
||||||
cmd = 'M';
|
cmd = 'M';
|
||||||
} else {
|
} else {
|
||||||
if (last_stroke[2] == 1) {
|
if (last_stroke[2] == 1) {
|
||||||
|
@ -137,7 +123,7 @@ class Player {
|
||||||
cmd = 'l';
|
cmd = 'l';
|
||||||
}
|
}
|
||||||
let rel_stroke = [stroke[0] - last_stroke[0], stroke[1] - last_stroke[1]];
|
let rel_stroke = [stroke[0] - last_stroke[0], stroke[1] - last_stroke[1]];
|
||||||
d += `${rel_stroke[0] * this.width},${rel_stroke[1] * this.height} `;
|
d += `${rel_stroke[0] * this.dimensions[0]},${rel_stroke[1] * this.dimensions[1]} `;
|
||||||
}
|
}
|
||||||
last_stroke = stroke;
|
last_stroke = stroke;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue