2015-04-04 2 views
5

Ich habe in interessanten CSS/JavaScript-Problem. Ich erstelle eine benutzerfreundliche Webkarte mit freiwilligen geographischen Informationen und muss in der Lage sein, in mehreren Papierformaten bis zur Größe des Posters zu drucken. Für die Schnittstelle arbeite ich mit Leaflet.js, Mapbox.js und jQuery. Die Art, wie ich mich dem Druckvorgang genähert habe, besteht darin, ein Vorschaufenster einzurichten, das nur Overlays (kein tileLayer) auf einer völlig neuen L.Map mit weißem Hintergrund zeigt, wobei die Marker proportional zu der vom Benutzer gewählten Papiergröße skaliert werden. Die Idee ist, dass die Karte die Seite füllt und die Marker immer in der gleichen Größe drucken (8 mm Durchmesser für Kreismarkierungen, 10 mm für Symbole). Hier ist ein Screenshot des Vorschaufensters in Firefox:Prospekt erweitern Karte zu Seite füllen auf

print preview window

Es gibt ein gutes Stück von komplexem Code ist. Es genügt zu sagen, dass, wenn der Benutzer die Fenstergröße oder die Papierausrichtung ändert, die Vorschaubox und die Symbole entsprechend angepasst werden. Wenn der Benutzer die Papiergröße ändert, ändert sich die Größe der Symbole, aber die Vorschau-Box nicht, um die richtigen Größenverhältnisse darzustellen. Hier sind die Funktionen verwende ich es zu tun:

function adjustPreviewBox(){ 
    //set preview box dimensions based on print window size and paper orientation 
    if ($("#paperOrientation option[value=portrait]").prop("selected")){ 
     var height = $("#printBox").height() - 61; 
     var width = height/Math.sqrt(2); 
     $("#printPreview").height(height); 
     $("#printPreview").width(width); 
    } else { 
     //first set by horizontal dimension 
     var width = $("#printBox").width() - 300; 
     var height = width/Math.sqrt(2); 
     //check for vertical overflow 
     if (height > $("#printBox").height() - 61){ 
      height = $("#printBox").height() - 61; 
      width = height * Math.sqrt(2); 
     }; 
     $("#printPreview").height(height); 
     $("#printPreview").width(width); 
    } 
}; 

function adjustScale(){ 
    //change symbol sizes and ratio scale according to paper size 
    var prevWidth = $("#printPreview").width(); 
    var prevHeight = $("#printPreview").height(); 
    var size = $("#paperSize select option:selected").val(); 
    var series = size[0]; 
    var pScale = Number(size[1]); 
    var longside, mmppPaper; 
    if (series == "A"){ //equations for long side lengths in mm, minus 10mm print margins 
     longside = Math.floor(1000/(Math.pow(2,(2*pScale-1)/4)) + 0.2) - 20; 
    } else if (series == "B"){ 
     longside = Math.floor(1000/(Math.pow(2,(pScale-1)/2)) + 0.2) - 20; 
    }; 
    //find the mm per pixel ratio 
    mmppPaper = prevWidth > prevHeight ? longside/prevWidth : longside/prevHeight; 
    var mapZoom = printPreviewMap.getZoom(); 
    var scaleText = $("#printBox .leaflet-control-scale-line").html().split(" "); 
    var multiplier = scaleText[1] == "km" ? 1000000 : 1000; 
    var scalemm = Number(scaleText[0]) * multiplier; 
    var scalepx = Number($("#printBox .leaflet-control-scale-line").width()); 
    var mmppMap = scalemm/scalepx; 
    var denominator = Math.round(mmppMap/mmppPaper); 
    $("#ratioScale span").text(denominator); 
    return [mmppMap, mmppPaper]; 
} 

function resizeMarkers(markerType, init){ 
    //scale preview marker size based on paper size and orientation 
    markerType == "circle" ? changeRadius(init) : changeIconSize(init); 
}; 

function getRadius(){ 
    //adjust ratio scale and return scale ratios 
    var scales = adjustScale(); 
    var mmppPaper = scales[1]; 
    return 4/mmppPaper; 
}; 

function changeRadius(init){ 
    //each circle marker will print at 8 mm diameter regardless of map scale and page size 
    var radius = getRadius(); 
    printPreviewMap.eachLayer(function(layer){ 
     if (typeof layer._radius !== 'undefined'){ 
      if (init == true){ 
       layer.setStyle({ 
        opacity: 1, 
        fillOpacity: 1 
       }); 
       layer.unbindPopup(); 
      }; 
      layer.setRadius(radius); 
     } 
    }); 
}; 

function changeIconSize(init){ 
    //each icon will print at 10 mm per side regardless of map scale and page size 
    var side = 2.5 * getRadius(); 

    //need to change dimensions and offset 
    $("#printPreview .leaflet-marker-icon").css({ 
     width: side + "px", 
     height: side + "px", 
     "margin-left": -(side/2), 
     "margin-top": -(side/2) 
    }) 
}; 

Ich habe @media print CSS-Stile, die gut zu funktionieren scheint für das Drucken der Vorschaufenster:

@media print { 
    @page { 
     size: auto; 
     margin: 10mm; 
    } 

    #printBox, #printPreview { 
     position: absolute; 
     max-height: 100%; 
     bottom: 0; 
     left: 0; 
     top: 0; 
     right: 0; 
    } 

    #printPreview { 
     position: absolute !important; 
     width: 100% !important; 
     height: 100% !important; 
     border: none; 
    } 

    #scalegrip { 
     visibility: hidden; 
    } 

    #container { 
     visibility: hidden; 
    } 
} 

ich getestet habe dies durch Drucken auf eine PDF mit Adobe-Treiber. Hier ist das Ergebnis:

PDF print of map

Es scheint gut zu funktionieren - außer, dass die Markierungen nur den linken oberen Teil der Seite füllen, während ich sie möchte nach außen zu erweitern, um die gesamten Seite zu füllen, so dass Das Endprodukt ist dieselbe "Ansicht" wie die Vorschau-Box. Dies ist, wo ich ratlos bin und würde jeden Rat oder Ideen von jedem begrüßen, der etwas Ähnliches versucht hat oder sich in Druckerei-Websites auskennt.

Antwort

1

In einem ähnlichen Projekt musste ich die Map aktualisieren, nachdem CSS-Größenänderungen über die Methode invalidateSize durchgeführt wurden. Zum Beispiel mit jQuery Karte Größe und Gewicht div ändern:

$("map").css('width', '267mm'); 
$("map").css('height', '210mm'); 
map.invalidateSize(); 

Nach leaflet help:

invalidateSize: Prüft, ob die Karte Behältergröße geändert und aktualisiert die Karte, wenn so - nennen Sie es, nachdem Sie‘ Die Größe der Karte wurde dynamisch geändert.