196 lines
5.9 KiB
HTML
Raw Normal View History

2021-11-08 09:11:46 +10:30
{{ define "content" }}
<main role="main" class="" x-data="editor()" x-init="setup_canvas();">
<div class="row">
<div class="col">
<canvas id="c" x-bind:style="canvas_style">
</canvas>
<img :src="img_data">
</div>
<div class="col">
<div id="tools-top" x-show="!toolbar">
<button type="button" @click="add_some_text()" class="btn btn-primary">Add text</button>
<button type="button" @click="crop()" class="btn btn-primary">Crop</button>
<button type="button" @click="apply()" class="btn btn-primary">Apply</button>
<button type="button" @click="cancel()" class="btn btn-primary">Cancel</button>
</div>
<div id="tools-delete" x-show="toolbar == 'text'">
<button type="button" @click="delete_selected();" class="btn btn-primary" style="">delete</button>
</div>
<div id="tools-crop" x-show="toolbar == 'crop'">
<button type="button" @click="apply_crop();" class="btn btn-primary" style="">crop</button>
</div>
<div id="tools-colour" x-show="toolbar == 'text'">
<table>
<tr>
<th>foreground</th>
<template x-for="colour in colours">
<td>
<button type="button" @click="set_colour(colour, 'fg')" class="btn btn-primary" :style="'background-color: '+colour">&nbsp;</button>
</td>
</template>
<td>
<button type="button" @click="set_colour('#fff0', 'fg')" class="btn btn-primary" style="">-</button>
</td>
</tr>
<tr>
<th>background</th>
<template x-for="colour in colours">
<td>
<button type="button" @click="set_colour(colour, 'bg')" class="btn btn-primary" :style="'background-color: '+colour">&nbsp;</button>
</td>
</template>
<td>
<button type="button" @click="set_colour('#fff0', 'bg')" class="btn btn-primary" style="">-</button>
</td>
</tr>
<tr>
<th>outline</th>
<template x-for="colour in colours">
<td>
<button type="button" @click="set_colour(colour, 'stroke')" class="btn btn-primary" :style="'background-color: '+colour">&nbsp;</button>
</td>
</template>
<td>
<button type="button" @click="set_colour('#fff0', 'stroke')" class="btn btn-primary" style="">-</button>
</td>
</tr>
</table>
</div>
</div>
2021-12-14 23:15:40 +10:30
</div>
2021-11-08 09:11:46 +10:30
</main>
{{ end }}
{{ define "js" }}
<script>
2021-12-14 23:15:40 +10:30
// for some reason, canvas does not work correctly if the object
// is managed by alpine - see https://github.com/fabricjs/fabric.js/issues/7485
var canvas = null;
2021-11-08 09:11:46 +10:30
function editor() {
return {
img_data: "", scaleFactor: 0.5,
2021-12-14 23:15:40 +10:30
toolbar: null,
colours: [ 'red', 'blue', 'green', 'white', 'yellow', 'black', 'purple'],
canvas_style: "",
// "position: absolute; width: 100%; height: 100%; left: 0px; top: 0px; touch-action: none; -webkit-user-select: none;",
2021-11-08 09:11:46 +10:30
setup_canvas() {
// seriously javascript? just imagine, in 2021....
var url = new URL(window.location);
var id = url.searchParams.get("id");
var self = this;
2021-12-14 23:15:40 +10:30
canvas = new fabric.Canvas('c');
canvas.on('selection:cleared', function(options) {
self.toolbar = null;
});
2021-11-08 09:11:46 +10:30
fabric.Image.fromURL('/rest/image/'+id, function(oImg) {
2021-12-30 21:53:34 +10:30
self.scaleFactor = scalefactor(oImg.width, oImg.height);
2021-12-14 23:15:40 +10:30
canvas.setDimensions({width: oImg.width, height: oImg.height});
2021-11-08 09:11:46 +10:30
oImg.selectable = false;
2021-12-14 23:15:40 +10:30
canvas.add(oImg);
canvas.setHeight(canvas.getHeight() * (self.scaleFactor));
canvas.setWidth(canvas.getWidth() * (self.scaleFactor));
canvas.setZoom(self.scaleFactor);
2021-11-08 09:11:46 +10:30
});
},
export_image() {
2021-12-14 23:15:40 +10:30
this.img_data = canvas.toDataURL({multiplier: 1/this.scaleFactor});
2021-11-08 09:11:46 +10:30
},
add_some_text() {
2021-12-14 23:15:40 +10:30
var text = new fabric.Textbox('double click to change', { left: 20, top: 20, width: 300, fontSize: 40 });
canvas.add(text);
canvas.setActiveObject(text);
this.toolbar = 'text';
var self = this;
text.on('selected', function(options) {
self.toolbar = 'text';
});
2021-11-08 09:11:46 +10:30
},
delete_selected() {
selected = canvas.getActiveObjects();
selected.forEach(el => {
canvas.discardActiveObject(el);
canvas.remove(el);
});
},
2021-12-14 23:15:40 +10:30
set_colour(colour, type) {
selected = canvas.getActiveObjects();
console.log();
selected.forEach(el => {
if (type === 'fg') {
el.set('fill', colour);
}
if (type === 'bg') {
el.set('textBackgroundColor', colour);
}
if (type === 'stroke') {
el.set('stroke', colour);
}
//["stroke","strokeWidth","fill","fontFamily","fontSize","fontWeight","fontStyle","underline","overline","linethrough","deltaY","textBackgroundColor"]
});
canvas.renderAll();
},
// crop mode
crop() {
},
apply() {
image_data = canvas.toDataURL({
format: 'png',
multiplier: 1.0/this.scaleFactor});
let formData = new FormData();
formData.append('image', image_data);
var url = new URL(window.location);
var id = url.searchParams.get("id");
fetch('/rest/upload/'+id+'/markup', {method: 'POST', body: formData})
.then(response => response.json()) // convert to json
.then(json => {
console.log(json);
window.location = '/uploads.html';
})
},
cancel() {
window.location = '/uploads.html';
},
2021-12-14 23:15:40 +10:30
2021-11-08 09:11:46 +10:30
}
}
2021-12-30 21:53:34 +10:30
function scalefactor(width, height) {
2022-03-27 14:51:56 +10:30
max_width = window.innerWidth * 3/5;
max_height = window.innerHeight * 5/6;
2021-12-30 21:53:34 +10:30
if (width <= max_width && height <= max_height) {
return 1.0;
}
factor = max_width/width;
if (height*factor <= max_height) {
return factor;
}
2022-03-27 14:51:56 +10:30
return 1/ (height/max_height);
2021-12-30 21:53:34 +10:30
}
2021-11-08 09:11:46 +10:30
</script>
{{ end }}