javascript - 与 Angular 和 Firestore 的协作画布
问题描述
我正在尝试在 ionic/angular+fabric.js+firestore 上创建一个实时协作画布。我有画布,我将它序列化为 json,存储它(并从不同的用户更新它),但我没有刷新每个用户的画布。我怎样才能做到这一点?
首先,我连接到集合:
this.imageCollection = database.collection<MyImage>("images");
this.drawing = this.imageCollection.doc(this.chatId).valueChanges();
this.writeCanvas();
然后,我有一个在每次“鼠标上移”时都会调用的函数:
loadOnCanvas(){
var json = JSON.stringify(this.f_canvas);
this.us.addCanvastoDB(json, this.chatId);
this. writeCanvas();
}
以下函数是我尝试写入共享画布(实际上并未共享)的地方,因为它不会随不同用户的绘图进行更新。在类 ( ) 的开头ngOnInit
和之后loadOnCanvas
(见上文)调用此函数:
writeCanvas(){
let that = this;
this.drawing.pipe(take(1)).subscribe(data=>{
that.read_json = data[0]['canvas'];
if(that.read_json){
this.f_canvas.clear();
console.log("data loaded", that.read_json);
that.f_canvas.loadFromJSON(that.read_json, that.f_canvas.renderAll.bind(that.f_canvas));
}
});
当我开始绘图时,来自 firestore 的数据保存在数据库中,但如果另一个用户(或离开应用程序后的同一用户)再次进入,则会显示一个空画布,并且不会加载来自数据库的数据。
这是将数据存储在数据库中的函数。它在服务中:
addCanvastoDB(canvas: any, chatId:string) {
//Create an ID for document
const id = this.database.createId();
console.log("chat id: ", chatId);
//Set document id with value in database
this.imageCollection
.doc(chatId)
.set({canvas: canvas, chatid: chatId},
{ merge: true })
.then(resp => {
console.log("resp", resp);
})
.catch(error => {
console.log("error " + error);
});
}
这是我组件中的所有相关代码:
export class DrawComponent implements OnInit {
@Input() chatId: string;
@Input() typeOfImg: string;
@Input() userId: string;
@Output() passEntry: EventEmitter<any> = new EventEmitter();
@ViewChild('my_canvas', {static: false}) my_canvas: ElementRef;
images: Observable<MyImage[]>;
private imageCollection: AngularFirestoreCollection<MyImage>;
private f_canvas:any;
private read_json: any;
drawing: any;
constructor(
public popoverCtrl: PopoverController,
public cs: ChatService,
public us: UploadService,
private modalController: ModalController,
private database: AngularFirestore,
public events: Events,
) {
this.availableColours = ["#dd0000", "#000000", "#00dd00", "#ffdd00"];
//Set collection where our documents/ images info will save
this.imageCollection = database.collection("images");
}
ngOnInit() {
this.f_canvas = new fabric.Canvas('my_canvas', {selection: true});
this.f_canvas.setHeight(window.innerHeight);
this.f_canvas.setWidth(window.innerWidth);
this.f_canvas.selection = true;
this.currentColour = '#000000';
this.f_canvas.freeDrawingBrush.width = 3; // size of the drawing brush
this.tool_selected = "selection_tool";
this.background_visible = false;
this.load_background();
let that = this;
this.f_canvas.on("mouse:down", function(o) {
that.mousedown(o);
});
this.f_canvas.on("mouse:move", function(e) {
that.mousemove(e);
});
this.f_canvas.on("mouse:up", function(e) {
that.mouseup(e);
});
console.log("chatid en draw", this.chatId);
this.drawing = this.imageCollection.doc(this.chatId).valueChanges();
}
ionViewDidLoad() {
this. writeCanvas();
}
ngAfterViewInit(){
}
//save canvas in firestore
loadOnCanvas(){
var json = JSON.stringify(this.f_canvas);
console.log("chat id sent to store canvas");
this.us.addCanvastoDB(json, this.chatId);
this. writeCanvas();
}
//draw the canvas with the data from firestore
writeCanvas(){
let that = this;
console.log("writing canvas");
this.drawing.pipe(tap(data=>{
console.log(data);
if(data[0]['canvas']){
that.read_json = data[0]['canvas'];
if(that.read_json){
this.f_canvas.clear();
console.log("data loaded", that.read_json);
that.f_canvas.loadFromJSON(that.read_json, that.f_canvas.renderAll.bind(that.f_canvas));
}
}
}));
}
任何想法,将不胜感激。非常感谢提前!!!
解决方案
我不知道确切原因,但是当我改变从数据库读取的方式时,我得到了这个工作。而不是使用tap
我正在使用take(1)
. 新块是这样的:
this.drawing.pipe(take(1)).subscribe(data=>{
//OLD WAY: this.drawing.pipe(tap(data=>{
if(data.canvas){
that.read_json = data.canvas;
if(that.read_json){
this.f_canvas.clear();
that.f_canvas.loadFromJSON(that.read_json, that.f_canvas.renderAll.bind(that.f_canvas));
}
}
});
无论如何,非常感谢您的帮助!
推荐阅读
- java - 获取菜单组作为视图
- python - 无法在 Python API 中为新的 Google Cloud Platform 项目启用计费
- r - ggplot 中的直方图按比例排序,仅取决于 R 中另一个变量的“是”值
- powershell - 如何在 powershell 中测试系统上是否存在程序/可执行文件?
- python-3.x - 与numpy有关的别名,深拷贝,浅拷贝之间的区别
- javascript - 计算按键并在 HTML 中显示
- ajax - Laravel 在使用 Ajax 登录后重定向到登录
- java - 同一行中的两个文本视图,其中第二个从第二行和其他行的开头开始
- amazon-web-services - 如何在单个 CloudFormation 堆栈上创建 2 个 AWS lambda?
- spring-integration - 如何限制 JdbcPollingChannelAdapter 的事务边界