2013-06-24 10 views
12

Angenommen, wir möchten auf der ersten Seite einen Titel anzeigen, der die obere Hälfte der Seite einnimmt. Die untere Hälfte der Seite sollte dann mit unserem Artikeltext aufzufüllen, und der Text über in die folgenden Seiten fließt weiter, bis es zu Ende geht:Steuern des Inhaltsflusses mit Prawn

enter image description here

Dies ist ein ziemlich grundlegendes Layout-Szenario, aber ich verstehe nicht, wie man es in Prawn umsetzen würde.

Hier einige Beispiel-Code aus ihren Online-Dokumentation abgeleitet:

pdf = Prawn::Document.new do 
    text "The Prince", :align => :center, :size => 48 
    text "Niccolò Machiavelli", :align => :center, :size => 20 
    move_down 42 

    column_box([0, cursor], :columns => 3, :width => bounds.width) do 
    text((<<-END.gsub(/\s+/, ' ') + "\n\n") * 20) 
    All the States and Governments by which men are or ever have been ruled, 
    have been and are either Republics or Princedoms. Princedoms are either 
    hereditary, in which the bla bla bla bla ..... 
    END 
    end 
end.render 

aber das wird nur weiterhin die Titelraum zeigen, für jede Seite:

enter image description here

Was die richtige Art und Weise zu tun ist Dies?

Antwort

2

So erstellt die column_box Methode eine Bounding-Box. Das dokumentierte Verhalten der Bounding Box besteht darin, dass sie an der gleichen Position wie auf der vorherigen Seite beginnt, wenn sie auf die nächste Seite wechselt. Das Verhalten, das Sie sehen, ist also grundsätzlich korrekt, auch nicht das, was Sie wollen. Die empfohlene Problemumgehung, die ich beim googlen gefunden habe, besteht darin, stattdessen span zu verwenden, da Spannen dieses Verhalten nicht aufweisen.

Das Problem ist jetzt, wie man Textspalten mit Spannen baut? Sie scheinen die Stützpunkte nicht nativ zu unterstützen. Ich habe versucht, ein kleines Skript zu erstellen, das Spalten mit Spannen nachahmt. Es erstellt für jede Spalte eine Spanne und richtet sie entsprechend aus. Dann wird der Text mit text_box geschrieben, die die overflow: :truncate Option hat. Dadurch gibt die Methode den Text zurück, der nicht in das Textfeld passt, sodass dieser Text in der nächsten Spalte gerendert werden kann. Der Code benötigt wahrscheinlich einige Optimierungen, aber es sollte ausreichen, um dies zu demonstrieren.

require 'prawn' 

text_to_write = ((<<-END.gsub(/\s+/, ' ') + "\n\n") * 20) 
All the States and Governments by which men are or ever have been ruled, 
have been and are either Republics or Princedoms. Princedoms are either 
hereditary, in which the bla bla bla bla ..... 
END 

pdf = Prawn::Document.generate("test.pdf") do 
    text "The Prince", :align => :center, :size => 48 
    text "Niccolò Machiavelli", :align => :center, :size => 20 
    move_down 42 

    starting_y = cursor 
    starting_page = page_number 

    span(bounds.width/3, position: :left) do 
    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate 
    end 

    go_to_page(starting_page) 
    move_cursor_to(starting_y) 

    span(bounds.width/3, position: :center) do 
    text_to_write = text_box text_to_write, at: [bounds.left, 0], overflow: :truncate 
    end 

    go_to_page(starting_page) 
    move_cursor_to(starting_y) 

    span(bounds.width/3, position: :right) do 
    text_box text_to_write, at: [bounds.left, 0] 
    end 
end 

Ich weiß, dass dies keine ideale Lösung ist. Aber das war das Beste, was ich mir vorstellen konnte.

+0

@ mario- Ich versuchte Ihr Beispiel, aber es erzeugte nur eine einzelne Seite. – Yarin

+0

Das stimmt. Wenn der letzte Aufruf von 'text_box' noch übrig gebliebenen Text zurückgibt, müssen Sie selbst eine neue Seite starten. Wenn Sie diese Lösung verwenden möchten, sollten Sie diese gesamte Prozedur wahrscheinlich in eine Methode einbinden. Wie gesagt, das ist eher ein Workaround als eine Lösung, aber ich habe nichts Besseres gefunden. – mario

+0

@ Mario- OK, vielen Dank dafür. Ich hatte gehofft, dass Prawn eine bessere Layout-Unterstützung hat und ich würde nicht darauf beschränkt sein, solche Dinge manuell zu machen, aber das könnte die einzige Lösung sein. – Yarin

-1

Verwenden Sie stattdessen das Grid-Layout von Prawns. Es ist sehr gut dokumentiert ... und einfacher, Ihr Layout zu kontrollieren.

+1

Ich sehe nicht, wie Raster mit diesem Layout-Szenario helfen würden. Könntest du demonstrieren? – Yarin

+0

Sorry für die Verzögerung ... kein Internet für eine Weile. Ich mag es, das Rasterlayout zu verwenden, weil Sie eine gute Kontrolle haben. Ich habe nicht mit Ihrem Layout gespielt, aber ich würde denken, dass die Platzierung des "Titels" über Spalten (mit Hilfe des Rasters) Ihren restlichen Inhalt fließen würde, ohne den Titelbereich zu wiederholen. – hellion

+1

@ hellion- Immer noch nicht sehen, wie das helfen würde. Bitte fügen Sie einen Beispielcode bei. – Yarin

10

Ich habe mit dem gleichen Problem gekämpft. Ich landete Subklassen ColumnBox und das Hinzufügen eines Helfer es aufzurufen etwa so:

module Prawn 
    class Document 

    def reflow_column_box(*args, &block) 
     init_column_box(block) do |parent_box| 
     map_to_absolute!(args[0]) 
     @bounding_box = ReflowColumnBox.new(self, parent_box, *args) 
     end 
    end 

    private 

    class ReflowColumnBox < ColumnBox 
     def move_past_bottom 
     @current_column = (@current_column + 1) % @columns 
     @document.y = @y 
     if 0 == @current_column 
      @y = @parent.absolute_top 
      @document.start_new_page 
     end 
     end 
    end 
    end 
end 

Dann wird sie aufgerufen, genau wie eine normale Spalte Box, aber auf der nächsten Seite Pause wird umfließen den Eltern Begrenzungsrahmen. Ändern Sie Ihre Linie:

column_box([0, cursor], :columns => 3, :width => bounds.width) do 

zu

reflow_column_box([0, cursor], :columns => 3, :width => bounds.width) do 

Hoffe, dass es Ihnen hilft. Prawn ist ein ziemlich niedriges Level, das ein zweischneidiges Schwert ist, es schafft manchmal nicht das, was du brauchst, aber die Werkzeuge sind da, um kompliziertere Strukturen zu erweitern und zu bauen.

+1

Ich habe auch eine Pull-Anfrage für eine Option Flag zu column_box erstellt, aber da sie (langsam) versuchen, für die Veröffentlichung und dies ein Feature Pull nicht eine Bugfix Ich würde nicht erwarten, dass es jederzeit bald. Für einen anderen Ansatz siehe https://github.com/prawnpdf/prawn/pull/512 (was mehr Affe-Patching erfordern würde). –

+0

Ich muss damit herumspielen und sehen, ob ich es für mich arbeiten lassen kann, scheint aber die richtige Richtung zu sein. Danke, dass du deine Erfahrung damit geteilt hast. – Yarin

+0

Sie sind herzlich willkommen. Lassen Sie es mich wissen, wenn es für Sie nicht funktioniert, da es einen latenten Fehler anzeigen könnte, der mich schließlich beißt :-) –

1

Verwenden Sie Schwimmer.

float do 
     span((bounds.width/3) - 20, :position => :left) do 
       # Row Table Code 
     end 
end 

float do 
     span((bounds.width/3) - 20, :position => :center) do 
       # Row Table Code 
     end 
end 

float do 
     span((bounds.width/3) - 20, :position => :right) do 
       # Row Table Code 
     end 
end 
+0

Wie würden Sie dann einen Schwimmer löschen? wie in der css entspricht von klar: beide – Levin

7

Ich weiß, das ist alt, aber ich dachte, ich würde teilen, dass eine neue Option in diesem hinzugefügt wurde in v0.14.0 zu beheben.

:reflow_margins ist eine Option, die Spaltenfelder so einstellt, dass sie ihre übergeordneten Felder beim Erstellen neuer Seiten füllen.

column_box(reflow_margins: true, columns: 3) 
+0

Interessant, werde es überprüfen - danke – Yarin

Verwandte Themen