2015-04-21 14 views
7

Ho un'app che si occupa del widget di disegno basato su paper.js. Diversi utenti possono disegnare allo stesso tempo e le modifiche vengono trasmesse l'una all'altra in tempo reale. Il problema è che ho bisogno di memorizzare le modifiche e mostrare l'immagine disegnata mentre il documento è caricato.Disegno simultaneo con paper.js

La soluzione naturale consiste nel memorizzare i comandi inviati dai client nel DB. Ma le immagini disegnate possono essere composte da migliaia di comandi e io posso avere decine di immagini. Quindi, quando sto aprendo un documento ottenendo un elenco di comandi dal server, il disegno può richiedere troppo tempo.

C'è un modo migliore di memorizzare le immagini e l'interazione tra i clienti?

Nota che ho una funzione di ridimensionamento, quindi la memorizzazione di raster non è un'opzione.

UPDATE: Se sto memorizzando un'immagine (ad esempio in un BLOB) non è chiaro come applicare le modifiche apportate in tempo reale. Passare l'immagine ogni volta non è la soluzione che voglio.

+0

Hai guardato Firebase? Sono abbastanza bravi a fare questo tipo di cose in sincronia a 3 vie. sorgente, server e altri client allo stesso tempo ... https://www.firebase.com/tutorial/#session/nvjq7b2kop2 –

risposta

2

Se si desidera salvare il disegno come immagine, esistono alcune soluzioni possibili.

  1. salvare l'elemento da qualche parte in una cartella e salvare il percorso della directory + il nome del file nel database
  2. Salvare le immagini nel database come un blob. Tuttavia, i BLOB sono davvero intensivi di database.

Ci sono alcuni interessanti articoli su BLOB. Come this one da microsoft.

Come previsto dalla comune saggezza, gli oggetti più piccoli di 256 KB sono archiviati al meglio in un database mentre gli oggetti più grandi di 1M sono archiviati al meglio nel file system.

Quindi, in termini di prestazioni, sarebbe una soluzione migliore per salvare l'immagine in una directory.

È anche possibile esportare un file svg di un'immagine disegnata. (info) Non so se questo ti può aiutare, ma questa è la mia esperienza personale. E sono d'accordo con te che memorizzare migliaia di comandi in un database non è la soluzione migliore. Quindi potresti voler dare un'occhiata al salvataggio delle immagini da qualche parte, ma in tal caso perderai la possibilità di modificare un'immagine se hai implementato questo.

Aggiornamento:

Se non si desidera salvare un blob la soluzione migliore sarebbe quella di "rendere" l'immagine ogni volta che una modifica è fatto. Quindi è possibile eseguire tutti i comandi quando qualcuno apre il disegno. E applica solo gli ultimi comandi quando viene attivata una modifica.

Ci sono diverse opzioni per raggiungere questo obiettivo. Come Jimmy Chandra ha detto, firebase sarebbe una buona soluzione. Offrono anche un tutorial con praticamente tutto ciò che si desidera ottenere. (disegnare un'immagine usando le coordinate x e in tempo reale) Forse dovresti dare un'occhiata a questo.

Ulteriori informazioni su Firebase.

Firebase è un potente API per archiviare e sincronizzare i dati in tempo reale

Questo è esattamente quello che si vuole raggiungere credo. Puoi provare il loro tutorial completo here.

Un'altra opzione che è possibile prendere in considerazione è nodejs. Ho visto persone che usano nodejs per i sistemi di chat per inviare i dati a tutti gli altri utenti. Se puoi inviare dati, sono sicuro che puoi disegnare un'immagine con esso.

Alla fine spetta a voi scegliere quale tecnologia si desidera utilizzare. Quindi penso che tu possa dover indagare su alcune soluzioni come ho suggerito e fare una domanda diversa se ti imbatti in problemi con l'integrazione di quella tecnologia.

+0

che non è possibile. Se lo memorizzo come BLOB (indipendentemente dal fatto che sia raster o SVG), come posso salvare le modifiche apportate in tempo reale – Eugeny89

+0

Hai considerato di salvare le coordinate delle righe nel database? Ciò significherebbe anche molte righe nel database, ma meno come azioni che penso. Vedo che hai anche la possibilità di salvare l'immagine come un formato JSON. Potrebbe essere d'aiuto? [Link] (http://paperjs.org/reference/raster/#exportjson) – Bram

+0

questo è ciò che intendo con "La soluzione naturale è quella di memorizzare i comandi inviati dai client nel DB". Azioni (comandi) o solo coordinate non contano.Poiché il problema principale è molto tempo o la ripetizione dell'elenco di azioni (comandi) – Eugeny89

1

Il salvataggio dei dati sul lato client come memoria secondaria è accettabile?

Con api di file html5, dovrebbe essere possibile conservare una copia di tutti i comandi di salvataggio inviati dai client nel DB. Quindi la prossima volta che apre un documento, l'applicazione renderà il disegno dalla memoria secondaria mentre contemporaneamente interrogherà sul server gli ultimi aggiornamenti, questi aggiornamenti verranno aggiunti al termine del rendering dello storage secondario.

Con websockets, è possibile salvare i comandi e trasmettere le modifiche ad altri client e quindi aggiornare il loro disegno con le modifiche in tempo reale.

1

2 anni fa ho sviluppato qualcosa di simile (in una squadra, codice chiuso).

La prima cosa da notare è che qualcosa di simile è già stato risolto da google docs. Leggiamo ogni articolo del blog e articolo su come lo hanno fatto e lo abbiamo applicato ad un SVG multiutente come un semplice editor. Quindi, ecco cosa ricordo:

La suddivisione in semplici comandi è la giusta direzione. Come hai scritto, con loro puoi ricreare le tue immagini in modo molto dettagliato. Puoi persino rispondere esattamente a quale immagine è stata osservata ogni timestamp richiesto. comandi

esempio potrebbe essere

- change color 
- change color again 
- draw a line from .. to .. 
- draw a line from .. to .. 
- draw a line from .. to .. 
- draw a line from .. to .. 
- smooth that line 
- change color 
- change Stroke 
- delete those lines and draw them again ;-) 

Torna l'esempio documenti Goolge, risparmiano e in onda ogni singola modifica carattere (e più).

Sì, questo è un approccio molto chiaro e verificabile, ma per richiedere prestazioni è necessario un altro livello logico. È necessario aggiungere una routine che semplifica questi comandi a una versione compressa (vedi sotto)

Nel momento in cui un utente richiede un'immagine, il sistema cerca l'ultima immagine compressa e aggiunge i singoli comandi non inclusi nel compress routine.

La routine di impacco:

fare una registrazione video della creazione di un'immagine fittizia (simile a quello che ci si aspetta da voi utenti) nel vostro editor vettore preferito, si nota che circa il 60% al 80% per cento dei comandi sono inutili per il risultato finale.

La routine impacco mirato può avere questi tre passi:

  1. La maggior parte del tempo si vedrà se stessi nei punti di registrazione di riposizionamento, gestisce o spostare gli oggetti, cambiare di nuovo e di nuovo il colore impostazione e disfare altri parametri come lo spessore della corsa. Anche cancellando un rifacimento di elementi. La routine deve ottimizzare questi comandi per disegnare direttamente il risultato finale. Sono sicuro che questo ridurrà il tuo elenco di comandi fino al 10% -50% a seconda del tipo di immagine che stai cercando.

  2. comandi di compressione. Un percorso nell'esempio sopra è disegnato in segmenti di linea, è necessario. Di solito non sai sul primo onMouseDown che finirà in un percorso con 100 segmenti e 200 manici. Ma ancora come gli altri utenti per mostrare il processo di creazione. Aggiungi un comando al tuo programma che sia in grado di disegnare cose complesse come un percorso. Non ne avrai bisogno nel processo di disegno dell'utente. Questo comando può essere utilizzato per la ricreazione più veloce di forme complete. Un tracciato con 100 punti e 200 manici può ora essere disegnato in un unico comando. Prima che tu avessi una lista di almeno 300 comandi.

  3. Riordina comandi. Due elementi tracciati disegnati da due utenti allo stesso tempo non sono facili da comprimere. Una soluzione semplice è ordinare i comandi per elemento. Il processo potrebbe richiedere 3 minuti per creare ogni forma. Un'animazione richiederebbe il vero ordine di comando di vedere ogni shpae svilupparsi nello stesso momento, ma il risultato finale non gli interessa. Ogni forma può essere compressa molto più facilmente se ordinata per elemento.

dispiace per il lungo post, spero che aiuta

0

Ti darò una risposta più ampia con le raccomandazioni architettoniche così scuse in anticipo per perfezionisti.

userei nginx e nodejs con WebSockets come il mio livello di applicazione e utilizzare paperjs sul mio lato server tramite NPMhttps://www.npmjs.com/package/paper

per il mio livello di persistenza mi piacerebbe non solo usare un db cluster (mysql/mongodb ecc.) ma utilizzare anche redis come cache di comandi.

Ogni volta che i comandi vengono eseguiti su tela che avevo persisto nel Redis e trasmesso a tutti i clienti via socket.io, e, infine, sul terminare/save/uscita eventi ecc causati da qualsiasi utente che avrei insisto come un immagine nel mio db o fs con un riferimento di percorso nel mio db.

Spero che questo aiuti.