working trilium canvas note

This commit is contained in:
thfrei 2020-11-09 23:04:46 +01:00 committed by Tom
parent 2a2c82cd29
commit 22363f5b74
2 changed files with 95 additions and 27 deletions

View File

@ -13,11 +13,12 @@ img.src = deleteIcon;
* const canvasState = new CanvasState();
* canvasState.on('selecting', ()=>{});
* canvasState.activate('selecting');
Inspiration: https://stackoverflow.com/a/53917410
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
Inspiration: https://stackoverflow.com/a/53917410
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
*/
class CanvasState extends EventTarget {
constructor(initialState) {
super();
this.states = {
IDLE: 'idle',
INTERACTING: 'interacting',
@ -99,6 +100,9 @@ class InfiniteCanvas {
this.resetZoom = this.resetZoom.bind(this);
this.cropCanvas = this.cropCanvas.bind(this);
this.placeTextBox = this.placeTextBox.bind(this);
this.getInfiniteCanvas = this.getInfiniteCanvas.bind(this);
this.setInfiniteCanvas = this.setInfiniteCanvas.bind(this);
this.overrideFabric = this.overrideFabric.bind(this);
}
overrideFabric() {
@ -178,6 +182,55 @@ class InfiniteCanvas {
return self;
}
/**
* prepares object that has width, scale and height of current view
* @returns {{canvas: *, width: *, lastScale: number, height: *}}
*/
getInfiniteCanvas() {
const canvas = this.$canvas;
const canvasContent = canvas.toJSON();
console.log('Canvas JSON', canvasContent);
const payload = {
width: this.width,
height: this.height,
lastScale: this.lastScale,
canvas: canvasContent,
};
return payload;
}
/**
* load infinite canvas json into canvas
* @param infiniteCanvasState
*/
async setInfiniteCanvas(infiniteCanvasState) {
const self = this;
const canvasContainer = this.$canvasContainer;
const {lastScale, width, height, canvas} = infiniteCanvasState;
// console.log('sICJSON', payload, canvasContainer);
return new Promise((resolve, reject) => {
const savedCanvas = canvas;
if (savedCanvas) {
this.$canvas.loadFromJSON(savedCanvas, function() {
console.log('loaded?');
self.width = self.scaledWidth = parseInt(width, 10);
self.height = self.scaledHeight = parseInt(height, 10);
self.lastScale = lastScale;
self.$canvas.setWidth(self.width);
self.$canvas.setHeight(self.height);
self.$canvasContainer.width(self.width).height(self.height);
self.$canvas.renderAll();
resolve();
});
} else {
console.log('payload empty?');
reject('payload empty?');
}
});
}
/**
*
* @param {string} direction [top, left, right, bottom]
@ -205,7 +258,7 @@ class InfiniteCanvas {
}
let newWidth = this.scaledWidth,
newHeight = this.scaledHeight;
newHeight = this.scaledHeight;
if (direction === 'top' || direction === 'bottom') {
newHeight = this.scaledHeight + distance;
@ -246,7 +299,10 @@ class InfiniteCanvas {
// place text box independent of touch type
if (this.activatePlaceTextBox) {
if (fabricEvent && fabricEvent.absolutePointer) {
this.placeTextBox(fabricEvent.absolutePointer.x, fabricEvent.absolutePointer.y);
this.placeTextBox(
fabricEvent.absolutePointer.x,
fabricEvent.absolutePointer.y,
);
this.activatePlaceTextBox = false;
return;
}
@ -284,13 +340,13 @@ class InfiniteCanvas {
placeTextBox(x, y) {
const canvas = this.$canvas;
canvas.add(
new fabric.IText('Tap and Type', {
fontFamily: 'Arial',
// fontWeith: '200',
fontSize: 15,
left: x,
top: y,
}),
new fabric.IText('Tap and Type', {
fontFamily: 'Arial',
// fontWeith: '200',
fontSize: 15,
left: x,
top: y,
}),
);
canvas.isDrawingMode = false;
}
@ -333,8 +389,8 @@ class InfiniteCanvas {
console.log('panstart', e);
if (
e.pointerType === 'touch' &&
!this.drawWithTouch // pointertype mouse and canvas state mouse-drag
e.pointerType === 'touch' &&
!this.drawWithTouch // pointertype mouse and canvas state mouse-drag
) {
canvas.isDrawingMode = false;
canvas.isDragging = true;
@ -454,14 +510,14 @@ class InfiniteCanvas {
/**
* Crop the canvas to the surrounding box of all elements on the canvas
*
Learnings: we must NOT use fabric.Group, since this messes with items and then
SVG export is scwed. Items coordinates are not set correctly!
fabric.Group(items).aCoords does NOT work.
Therefore we need to get bounding box ourselves
Note: Or maybe we can use group, destroy and readd everything afterwards:
http://fabricjs.com/manage-selection
https://gist.github.com/msievers/6069778#gistcomment-2030151
https://stackoverflow.com/a/31828460
Learnings: we must NOT use fabric.Group, since this messes with items and then
SVG export is scwed. Items coordinates are not set correctly!
fabric.Group(items).aCoords does NOT work.
Therefore we need to get bounding box ourselves
Note: Or maybe we can use group, destroy and readd everything afterwards:
http://fabricjs.com/manage-selection
https://gist.github.com/msievers/6069778#gistcomment-2030151
https://stackoverflow.com/a/31828460
*/
async cropCanvas() {
console.log('cropCanvas');

View File

@ -9,7 +9,7 @@ import _debounce from './canvas-note-utils/lib/lodash.debounce.js';
const TPL = `
<div id="parentContainer" class="note-detail-canvas-note note-detail-printable"
style=" /*resize: both;*/
overflow:auto; width: 100%; height: 80%; background-color: rgba(255,248,230,0.58); border: 1px double #efefef;">
overflow:auto; width: 100%; height: 70%; background-color: rgba(255,248,230,0.58); border: 1px double #efefef;">
<div id="canvasContainer" style="width: 1500px; height: 1500px;">
<canvas id="c" class="canvasElement" style="border:1px solid #aaa; width: 1500px; height: 1500px"></canvas>
</div>
@ -25,7 +25,6 @@ const TPL = `
<button id="pen-2" class="btn btn-info"><i class='bx bx-pencil' style="border-left: 3px solid red"></i></button>
<button id="pen-3" class="btn btn-info"><i class='bx bx-pencil' style="border-left: 3px solid green"></i></button>
<button id="pen-4" class="btn btn-info"><i class='bx bx-pencil' style="border-left: 3px solid blue"></i></button>
<br />
<button id="marker-1" class="btn btn-info"><i class='bx bx-pen' style="border-left: 7px solid yellow"></i></button>
<button id="marker-2" class="btn btn-info"><i class='bx bx-pen' style="border-left: 7px solid wheat"></i></button>
<button id="marker-3" class="btn btn-info"><i class='bx bx-pen'
@ -61,6 +60,9 @@ export default class CanvasNoteTypeWidget extends TypeWidget {
super();
this.initCanvas = this.initCanvas.bind(this);
this.saveData = this.saveData.bind(this);
this.getContent = this.getContent.bind(this);
this.doRefresh = this.doRefresh.bind(this);
}
static getType() {
return "canvas-note";
@ -74,6 +76,14 @@ export default class CanvasNoteTypeWidget extends TypeWidget {
.then(() => {
console.log("fabric.js-loaded")
this.initCanvas();
})
.then(async () => {
const noteComplement = await this.tabContext.getNoteComplement();
if (this.infiniteCanvas && noteComplement.content) {
const content = JSON.parse(noteComplement.content || "");
await this.infiniteCanvas.setInfiniteCanvas(content);
}
this.canvas.on('after:render', _debounce(this.saveData, 1000));
});
return this.$widget;
@ -82,8 +92,9 @@ export default class CanvasNoteTypeWidget extends TypeWidget {
async doRefresh(note) {
// get note from backend and put into canvas
const noteComplement = await this.tabContext.getNoteComplement();
if (this.canvas && noteComplement.content) {
this.canvas.loadFromJSON(noteComplement.content);
if (this.infiniteCanvas && noteComplement.content) {
const content = JSON.parse(noteComplement.content || "");
await this.infiniteCanvas.setInfiniteCanvas(content);
}
console.log('doRefresh', note, noteComplement);
}
@ -92,9 +103,9 @@ export default class CanvasNoteTypeWidget extends TypeWidget {
* Function gets data that will be sent via spacedUpdate.scheduleUpdate();
*/
getContent() {
const content = JSON.stringify(this.__canvas.toJSON());
const content = this.infiniteCanvas.getInfiniteCanvas();
console.log('gC', content);
return content;
return JSON.stringify(content);
}
saveData() {
@ -110,6 +121,7 @@ export default class CanvasNoteTypeWidget extends TypeWidget {
this.infiniteCanvas = myCanvas.initFabric();
this.canvas = this.infiniteCanvas.$canvas;
// this.canvas.clear();
this.canvas.setWidth(myCanvas.width);
this.canvas.setHeight(myCanvas.height);