import AfterViewChecked, Component from '@angular/core';
@Component(
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
)
export class AppComponent implements AfterViewChecked
sizePage =
width: 21, //cm
height: 29.7 //cm
paddingPage =
top: 2, //cm
right: 2, //cm
bottom: 2, //cm
left: 2 //cm
pages = [
htmlContent: null,
full: false
,
]
currentPage = 0;
currentChar = null;
runAfterViewChecked = false;
clickPage(i)
this.currentPage = i;
inputContent(char, i)
var element = document.getElementById('content-' + i)
var heightContent = element.offsetHeight * 2.54 / 96; // Convert pixels to cm
this.pages[i].htmlContent = element.innerHTML;
console.log(this.pages);
if (Number(heightContent.toFixed(1)) > this.sizePage.height)
this.currentChar = char;
this.pages[i].full = true;
if (!this.pages[i + 1])
this.pages.push(
htmlContent: null,
full: false
)
this.currentPage = i + 1;
this.runAfterViewChecked = true;
ngAfterViewChecked()
document.getElementById('content-' + this.currentPage).focus();
if (this.runAfterViewChecked)
if (this.currentChar)
var str = this.pages[this.currentPage-1].htmlContent;
var indexLastCloseDiv = str.lastIndexOf("
");
var indexLastBr = str.lastIndexOf(" ");
var lastChar = str[indexLastCloseDiv-1];
if (indexLastBr != -1 && (indexLastBr + 4) == indexLastCloseDiv)
lastChar = ' ';
if (indexLastCloseDiv != -1)
str = str.slice(0, indexLastCloseDiv-1) + str.slice(indexLastCloseDiv);
else
str = str.slice(0, str.length - 1);
this.pages[this.currentPage-1].htmlContent = str;
if (this.pages[this.currentPage].htmlContent)
this.pages[this.currentPage].htmlContent = lastChar + this.pages[this.currentPage].htmlContent;
else
this.pages[this.currentPage].htmlContent = lastChar;
var element = null;
for (let i = 0; i < this.pages.length; i++)
element = document.getElementById('content-' + i);
element.innerHTML = this.pages[i].htmlContent;
this.runAfterViewChecked = false;
Enlace a Stackblitz
He aquí un ejemplo sencillo. Hay algunos errores, por favor dé sus sugerencias para un mayor desarrollo.
Algunas funciones como Retroceso, Eliminar, Escalar página, ... no se han procesado.
Se trata de dividir el contenido dado para que se ajuste al tamaño de página dado.
Podemos crear un componente que maneje la funcionalidad de división por nosotros. aquí hay una demostración de StackBlitz.
Y aquí hay una breve explicación.
Utilizar el ContentChildren decorador para observar el cambio de contenido. cada vez que cambie el contenido, ejecutaremos la lógica de creación de la página.
import
AfterContentInit,
AfterViewInit,
Component,
ContentChildren,
ElementRef,
Input,
OnInit,
QueryList,
ViewChild
from "@angular/core";
@Component(
selector: "app-paginated-view",
templateUrl: "paginated-view.component.html",
styleUrls: ["paginated-view.component.scss"]
)
export class PaginatedViewComponent implements AfterViewInit "A4" = "A4";
@ViewChild("paginatedView") paginatedView: ElementRef;
@ViewChild("contentWrapper") contentWrapper: ElementRef;
@ContentChildren("pageContent", read: ElementRef ) elements: QueryList<
ElementRef
>;
constructor()
ngAfterViewInit(): void
this.updatePages();
// when ever childs updated call the updatePagesfunction
this.elements.changes.subscribe(el =>
this.updatePages();
);
updatePages(): void
// clear paginated view
this.paginatedView.nativeElement.innerHTML = "";
// get a new page and add it to the paginated view
let page = this.getNewPage();
this.paginatedView.nativeElement.appendChild(page);
let lastEl: HTMLElement;
// add content childrens to the page one by one
this.elements.forEach(elRef =>
const el = elRef.nativeElement;
// if the content child height is larger than the size of the page
// then do not add it to the page
if (el.clientHeight > page.clientHeight)
return;
// add the child to the page
page.appendChild(el);
// after adding the child if the page scroll hight becomes larger than the page height
// then get a new page and append the child to the new page
if (page.scrollHeight > page.clientHeight)
page = this.getNewPage();
this.paginatedView.nativeElement.appendChild(page);
page.appendChild(el);
lastEl = el;
);
//bring the element in to view port
lastEl.scrollIntoView( behavior: "smooth", block: "nearest" );
getNewPage(): HTMLDivElement
const page = document.createElement("div");
page.classList.add("page");
page.classList.add(this.pageSize);
return page;
Podemos usar este componente en una aplicación como esta.
Hello World!!
This content will be displayed in an A4 size page
Tenemos que proporcionar la variable de plantilla #pageContent para que podamos seleccionarlos usando @ContentChildren en nuestro PaginatedViewComponent.
Tenga en cuenta que aquí estamos usando API nativas de dom para cambiar la estructura de dom. solo moverá el nodo dom de un lugar a otro, por lo que si tiene un detector de eventos agregado o tiene alguna propiedad que se vincule al contenido secundario, funcionará como está.
Editar:
También he actualizado su stackblitz https://stackblitz.com/edit/angular-ivy-zjf8rv
Si desea crear HTML A4 como la palabra de oficina A4, debe usar estos tamaños:
body
width: 21cm ;
height: 29.7cm;
margin:30mm 45mm 30mm 45mm;
Si para ti ha sido de utilidad nuestro artículo, nos gustaría que lo compartas con más programadores y nos ayudes a extender nuestra información.