【问题标题】:collaborative canvas with angular and firestore与 Angular 和 Firestore 的协作画布
【发布时间】:2020-07-13 04:14:17
【问题描述】:

我正在尝试在 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));
          }
        }
      }));
   }

任何想法将不胜感激。 提前非常感谢!!!

【问题讨论】:

  • 画布更新是否正确推送到 Firestore?即:如果用户更改画布,更改是否序列化并从 Firestore 页面可见?如果是这种情况,错误可能出在渲染端而不是数据库端。
  • 感谢您的关注。是的,画布中的 JSON 已从不同的用户正确存储和更新,但不知何故,画布既没有加载也没有在不同的用户中刷新。这意味着当第二个用户进入画布时,已经存在的画布甚至不会被加载。第二个用户可以进行绘图并且数据会更新,但不会更新任何画布。
  • “当第二个用户进入画布时,已经存在的画布甚至没有被加载”是什么意思?它是否显示一个新的空画布?可能是您没有引用同一个文档。另外,你为什么打电话给const id = this.database.createId();?以及为什么在将画布写入 Firestore 时更新 chatId?不应该是与同一个画布交互的所有用户共享的静态Id吗?
  • 嗨,再次感谢您的提示!很抱歉关于 createId 的那一行,因为它来自之前的测试,我在发布之前忘记删除它。
  • 无论如何,按照您的提示,我意识到问题是我试图在画布上绘制之前我得到了 JSON 数据的值。你是对的,我的意思是当我打开绘图组件时,即使有从 `revious 绘图加载的数据,它也会显示一个空画布。你对我有什么暗示吗?我对 firestore 和这种使用 javascript 的异步方式很陌生...

标签: javascript angular canvas google-cloud-firestore fabricjs


【解决方案1】:

我不知道确切原因,但是当我改变从数据库读取的方式时,我得到了这个工作。我没有使用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));
      }
    }
  });

非常感谢您的帮助!

【讨论】:

猜你喜欢
  • 2022-09-22
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 2011-09-24
相关资源
最近更新 更多