[JAVA] Ich habe versucht, Animationen mit der Blazor + Canvas-API zu zeichnen

Einführung

Ich habe eine einfache Webanwendung zum Zeichnen erstellt, mit der Animationen zum Lernen wie Blazor gezeichnet werden können. Ich spreche nur von der Verwendung von Blazor und schreibe TypeScript häufiger als C #.

Demo(Firebase) Source(GitHub)

blazorcanvas2.gif Ich wünschte, ich könnte einen Anime wie einen mysteriösen Ani-Dan zeichnen, aber für mich ist das Blinken die Grenze.

Derzeit sind es nur 8 fps (sogenanntes Drei-Frame-Striking), aber irgendwann können wir die Framerate ändern. Es ist einfach, die Rate zu ändern, aber da 24 Bilder (24 fps: allgemeine Bildrate japanischer Animationen) normalerweise nicht für 1 Sekunde der Animationswiedergabe gezeichnet werden, ist es erforderlich, mit dem leeren Bild umzugehen.

Umgebung

Blazor WebAssembly 3.2.1 + .NET Standard 2.1 Microsoft.TypeScript.MSBuild 4.0.3 Firebase

Andere, wie z. B. Bootstrap, sind in der Blazor-Vorlage enthalten.

Über die Implementierung

Während Blazor Blazor sagt, steuert er nur die Benutzeroberfläche.

Wie zeichnet man eine Linie?

Als ich nach einer Implementierungsmethode zum Zeichnen einer Linie auf Canvas suchte, gab es viele Beispiele für die Verwendung der Methode "lineTo ()", aber wenn ich den Stift schnell bewegte, wurde es manchmal zu einer seltsamen Zeichenmethode, also der Stift Der Kreis wird entsprechend der Umlaufbahn platziert. Wenn Sie jedoch versuchen, so schnell wie es ist zu zeichnen, wird die Linie geschnitten, daher versuche ich, die Lücke mit einer kleinen Änderung zu füllen, wie unten gezeigt. Da es sich jedoch um eine lineare Ergänzung handelt, möchte ich eine etwas stärker gekrümmte Form in Betracht ziehen. Ich denke, ich muss Mathe überprüfen.

    private prevX :number;
    private prevY :number;
    public drawLineWithPen(x:number, y:number, isDrawing:boolean){
        let scaledX = x/this.scaleRate;
        let scaledY = y/this.scaleRate;
        if(!isDrawing) {
            this.context.beginPath();
            this.context.moveTo(scaledX,scaledY);
        } else {
            //Abteilungsnummer
            let div = 200;
            let dx = (scaledX - this.prevX) / div;
            let dy = (scaledY - this.prevY) / div;
            let r = this.context.lineWidth/2;
            for(let i = 0; i<=div; i++){
                let x = this.prevX + dx*i;
                let y = this.prevY + dy*i;
                this.context.beginPath();
                this.context.moveTo(x,y);
                this.context.arc(x,y, r, 0, 2 * Math.PI, false);
                this.context.stroke();
                this.context.fill();
                this.context.closePath();
            } 
        }
        this.prevX = scaledX;
        this.prevY = scaledY;
    }

Beim Einsetzen und Entfernen des Stifts denke ich an eine Form, die die Größe und Transparenz des Kreises mit dem Zeitunterschied als Parameter ändert.

So zeigen Sie Zwiebelschalen an

Zwiebelschale ist eine Funktion, die die Frames vor und nach dem Frame, den Sie bearbeiten, in einer bestimmten Farbe anzeigt. Dieses Mal wird der hintere Rahmen in Pink und der vordere Rahmen in Hellblau angezeigt.

Wir erstellen eine Kopie des zuvor gespeicherten ImageData-Arrays, ersetzen die Farben und legen die Transparenz fest. Nachdem die Bitmap-Daten erstellt wurden, werden sie nach der Methode von drawImage () in die Zeichenfläche geschrieben, um Zwiebelschalen anzuzeigen. Es wäre schön gewesen, mit ImageData direkt auf die Leinwand schreiben zu können, aber putImageData () ersetzt alles auf der Leinwand, also sieht es so aus.

private setOnionSkinsInternal(start:number, end:number, color:Color, frames: ImageData[], isPrev:boolean){
    let startNum = Math.max(start, 0);
    let endNum = Math.min(end,frames.length);
    for(let i= startNum; i< endNum; i++) {
        let imageData = new ImageData(frames[i].data.slice(),frames[i].width,frames[i].height);
        for(let j=0;j<imageData.data.length; j+=4) {
            imageData.data[j] = color.r;
            imageData.data[j+1] = color.g;
            imageData.data[j+2] = color.b;
            //Bilder, die weit vom aktuellen Bild entfernt sind, haben eine stärkere Transparenz und eine hellere Anzeige
            if(isPrev)
                imageData.data[j+3] = imageData.data[j+3] * (i+1) / (endNum+1);
            else
                imageData.data[j+3] = imageData.data[j+3] * (startNum+1) / (i+1);          
        }
        window.createImageBitmap(imageData).then(
            (img) => {
                // scale()Da das Bild durch die eingestellte Vergrößerung weiter verkleinert wird, dividieren Sie durch die Vergrößerung?
                this.context.drawImage(img,0,0,this.width/this.scaleRate,this.height/this.scaleRate);
            }
        ).catch(() => {
            console.log(`${i} Error`)});
    }
}

Es gibt 921.600 oder mehr Schleifen pro Blatt. Wenn Sie also versuchen, die Größe zu erhöhen und etwa 10 Blätter anzuzeigen, ist dies ziemlich schwer. Ich möchte mir einen besseren Weg vorstellen. Ich habe darüber nachgedacht, Leinwand für die Anzahl der Zwiebelschalen hinzuzufügen, aber ich habe es nicht ausprobiert.

Radiergummi und Schichtzusammensetzung

https://hai3.net/blog/html5-canvas-eraser/ Ich bezog mich auf diese Methode. Vielen Dank.

CanvasRenderingContext2D.globalCompositeOperation = "destination-out"; Beim Zeichnen mit dem Radiergummi war es in Ordnung, wenn dies eingestellt war.

https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation Wenn ich MDN lese, habe ich das Gefühl, dass damit die Schichtzusammensetzung und die Aquarellähnlichkeit der Stiftspitze erreicht werden können.

Derzeit besteht die einzige Möglichkeit, von einem Radiergummi zu einem Stift zu wechseln, darin, die Farbe oder die Größe der Stiftspitze zu ändern. Daher möchte ich eine geeignete Optionsfeld-ähnliche Schaltmethode erstellen.

undo/redo Haben Sie einfach ein ImageData [], um den Verlauf zu speichern und jedes Mal zu öffnen oder zu drücken, wenn die Undo / Redo-Methode aufgerufen wird. Ich habe darüber nachgedacht, den Verlauf auf der TypeScript-Seite zu speichern, aber ich möchte ihn auf der UI-Seite steuern, also überlasse ich das Timing, um ihn auf der Blazor-Seite aufzurufen. Derzeit ist ~~ einfach zu implementieren ~~ Es gibt einen Verlauf für jeden Frame, aber es scheint, dass sich die Art und Weise, den Verlauf zu halten, zum Zeitpunkt der Implementierung des Löschens des Frames ändert.

public undo(){
    if(this.currentFrame.prevHistory.length > 0) {
        let prev = this.currentFrame.prevHistory.pop() ?? new ImageData(this.width,this.height) ;
        this.currentFrame.nextHistory.push(this.getImageData());
        this.putImageData(prev);      
    }
}

public redo(){
    if(this.currentFrame.nextHistory.length > 0){
        let next = this.currentFrame.nextHistory.pop() ?? new ImageData(this.width,this.height);
        this.currentFrame.prevHistory.push(this.getImageData());
        this.putImageData(next);
    }
}

public saveHistory(){
    this.currentFrame.prevHistory.push(this.getImageData());
    //Wenn ein neuer Verlauf hinzugefügt wird, wird der Weiterleitungsverlauf gelöscht.
    this.currentFrame.nextHistory = [];
}

Leinwandelement Priorität

<canvas id="1"></canvas>
<canvas id="2"></canvas>
<canvas id="3"></canvas>

Wenn das Ereignis von id =" 1 " aufgenommen wird, müssen Sie es nach unten bringen, um das Ereignis aufzunehmen.

TypeScript + dotnet CLI Es war sehr einfach, da die .ts-Datei auch mit dem C # -Code kompiliert wurde, als "dotnet run" mit dem Befehl "dotnet add package Microsoft.TypeScript.MSBuild" und den Einstellungen der json-Datei ausgeführt wurde. Ich habe darüber nachgedacht, mit Fable in F # zu schreiben, aber ich habe aufgegeben, weil es aufgrund der Spezifikation der JavaScript-Interoperabilität, bei der der Methodenname aus der Methode zur Generierung des Methodennamens angegeben werden muss, streng zu sein scheint.

Funktionen, die in Zukunft hinzugefügt werden sollen

Ich habe in READ ME von GitHub geschrieben, dass es ein Chaos war, aber da das Problem des Zeichenkomforts groß ist, möchte ich das Problem lösen, dass die Linien steif sind und der Ein- und Ausgang vollständig sind. Wenn Sie die Web Storage-API verwenden, können Sie anscheinend die Einstellungswerte für Farbe und Stiftgröße speichern. Daher möchte ich dies auch unterstützen.

Die Unterstützung von Tablets und Smartphones wird noch lange dauern.

über mich

Ordentlich scheint an der Systemerstellung mit der Windows Form-Anwendung beteiligt gewesen zu sein. Ich habe nur wenig Verständnis für C # und C und keine Erfahrung mit TypeScript.

Absicht zu machen

Ich kann mit einer bestimmten Zeichensoftware keine einfachen Animationen zeichnen und verschieben. Die Verwendung ist schwierig, selbst wenn ich Animationen erstelle. Es gibt keinen Bildschirmeffekt. Ich denke, dass es anscheinend keine Zeichenanwendung (Webanwendung) gibt, die sich unerwartet in diese Richtung gedreht hat. Von. Es gibt auch keine Datenbankoperation oder Anmeldefunktion, aber abgesehen von Problemen wie Gelegenheit und Qualität dient sie dazu, jemandem irgendwo etwas zu zeigen.

Ursprünglich habe ich die Canvas-API ausprobiert und nicht über die Animationsfunktion nachgedacht, aber als ich sie erstellte, wollte ich die Funktion hinzufügen, und jetzt bin ich es.

abschließend

Es gibt noch viele Funktionen, die ich implementieren möchte, und Punkte, die ich verbessern möchte. Daher möchte ich so lange fortfahren, wie meine Motivation anhält. TypeScript wurde von Microsoft entwickelt und war viel einfacher, da ich beim Kompilieren einige Fehler auf der TypeScript-Seite feststellen konnte, da es einen ähnlichen Teil wie C # und eine Kombination mit Dotnet CLI gab. Blazor kann auch die API des Browsers selbst berühren. Da dies jedoch nur über IJS Runtime möglich ist, scheint es streng zu sein, nur Blazor (C #) zu verwenden.

Recommended Posts

Ich habe versucht, Animationen mit der Blazor + Canvas-API zu zeichnen
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, den Chat mit dem Minecraft-Server mit der Discord-API zu verknüpfen
Ich habe versucht, mit Web Assembly zu beginnen
Ich habe versucht, die Stream-API zusammenzufassen
Ich habe versucht, eine Web-API zu erstellen, die mit Quarkus eine Verbindung zur Datenbank herstellt
Ich habe versucht, AdoptOpenJDK 11 (11.0.2) mit dem Docker-Image zu überprüfen
Ich habe versucht, eine Standardauthentifizierung mit Java durchzuführen
Ich habe versucht, Anmeldeinformationen mit JMX zu verwalten
Ich habe versucht, den Block mit Java zu brechen (1)
Ich habe versucht, was ich mit Stream leise versuchen wollte.
Ich habe versucht, das Hochladen von Dateien mit Spring MVC zu implementieren
Ich habe versucht, CSV mit Outsystems zu lesen und auszugeben
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
[Java 11] Ich habe versucht, Java auszuführen, ohne mit Javac zu kompilieren
Ich habe versucht, mit Spring Data JPA zu beginnen
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
[Java] Ich habe versucht, die Yahoo API-Produktsuche zu implementieren
Ich habe versucht, den Betrieb der http-Anfrage (Put) mit dem Talented API Tester zu überprüfen
Ich habe DI mit Ruby versucht
Ich habe UPSERT mit PostgreSQL ausprobiert.
Ich habe BIND mit Docker ausprobiert
Ich habe versucht, yum-cron zu verifizieren
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit spiritueller Technik zu erhöhen
[Rails] Ich habe versucht, eine Mini-App mit FullCalendar zu erstellen
Ich habe versucht, Ben zu einer leicht verständlichen GIF-Animation zu machen
[Rails] Ich habe versucht, die Stapelverarbeitung mit der Rake-Task zu implementieren
Was ich mit der Redmine REST API süchtig gemacht habe
Ich habe versucht, mit Docker eine Padrino-Entwicklungsumgebung zu erstellen
Ich habe versucht, mit Swagger mit Spring Boot zu beginnen
Ich habe versucht, mit Ractor mehrere Objekte übergeben zu können
Ich habe versucht, einen API-Server mit Go (Echo) x MySQL x Docker x Clean Architecture zu erstellen
Ich habe versucht, C # (Indexer) zu kauen.
Ich habe versucht, JOOQ mit Gradle zu verwenden
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
Ich habe versucht, mithilfe von JDBC Template mit Spring MVC eine Verbindung zu MySQL herzustellen
Ich habe versucht, die Unterstützung für iOS 14 zusammenzufassen
Ich habe versucht, die Bildvorschau mit Rails / jQuery zu implementieren
Ich habe versucht, mit Eclipse + Tomcat eine http2-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine flexible ODER-Zuordnung mit MyBatis Dynamic SQL zu implementieren
Ich habe versucht, UDP mit Java zu kommunizieren
Ich habe versucht, die Methode zu erklären
Ich habe versucht, Ruby's Float (arg, Ausnahme: true) mit Builtin neu zu implementieren
Ich habe versucht, die Java8 Stream API zu verwenden
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, den Betrieb des gRPC-Servers mit grpcurl zu überprüfen
Ich habe GraphQL mit Spring Boot ausprobiert
Ich habe versucht, das Java-Lernen zusammenzufassen (1)
Ich habe Flyway mit Spring Boot ausprobiert
Ich habe jetzt versucht, Java 8 zusammenzufassen
C # (Polymorphismus: Polymorphismus)
Ich habe versucht, Slim mit Scaffold anzupassen
Ich habe versucht, Active Hash zu erklären